Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { HttpApiBuilder, HttpApiScalar } from "effect/unstable/httpapi"
import { McpLive } from "./mcp/app"
import { HttpBillingLive, HttpBillingPublicLive } from "./routes/billing.http"
import { HttpAiTriageLive } from "./routes/ai-triage.http"
import { HttpAlertsLive } from "./routes/alerts.http"
import { HttpAnomaliesLive } from "./routes/anomalies.http"
import { HttpErrorsLive } from "./routes/errors.http"
import { HttpApiKeysLive } from "./routes/api-keys.http"
import { HttpV2AlertDeliveriesLive } from "./routes/v2/alert-deliveries.http"
import { HttpV2AlertDestinationsLive } from "./routes/v2/alert-destinations.http"
import { HttpV2AlertIncidentsLive } from "./routes/v2/alert-incidents.http"
import { HttpV2AlertRulesLive } from "./routes/v2/alert-rules.http"
Expand Down Expand Up @@ -306,7 +306,6 @@ const ApiRoutes = HttpApiBuilder.layer(MapleApi).pipe(
Layer.provide(Layer.mergeAll(HttpAiTriageLive, HttpAnomaliesLive, HttpChatLive, HttpInvestigationsLive)),
Layer.provide(HttpApiKeysLive),
Layer.provide(Layer.mergeAll(HttpBillingLive, HttpBillingPublicLive)),
Layer.provide(HttpAlertsLive),
Layer.provide(HttpErrorsLive),
Layer.provide(HttpDashboardsLive),
Layer.provide(HttpDemoLive),
Expand Down Expand Up @@ -334,6 +333,7 @@ const ApiV2Routes = HttpApiBuilder.layer(MapleApiV2).pipe(
Layer.mergeAll(
HttpV2ApiKeysLive,
HttpV2DashboardsLive,
HttpV2AlertDeliveriesLive,
HttpV2AlertRulesLive,
HttpV2AlertDestinationsLive,
HttpV2AlertIncidentsLive,
Expand Down
25 changes: 1 addition & 24 deletions apps/api/src/mcp/tools/create-alert-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,6 @@ interface CreateAlertRuleParams {
consecutive_breaches?: number
consecutive_healthy?: number
renotify_interval_minutes?: number
metric_name?: string
metric_type?: string
metric_aggregation?: string
apdex_threshold_ms?: number
query_builder_draft?: string
raw_query_sql?: string
Expand Down Expand Up @@ -139,14 +136,6 @@ function buildAlertRuleRequest(
// or, for builder_query, parses the draft JSON. Non-special signal types
// (error_rate, p95_latency, …) fall through with no extra checks.
const signalValidation = Match.value(signalType).pipe(
Match.when("metric", (): { error: string } | { draft?: unknown } => {
if (!params.metric_name || !params.metric_type || !params.metric_aggregation) {
return {
error: 'signal_type=metric requires metric_name, metric_type, and metric_aggregation. Use list_metrics to discover available metrics.\n\nExample:\n signal_type="metric" metric_name="http.server.duration" metric_type="histogram" metric_aggregation="avg"',
}
}
return {}
}),
Match.when("apdex", (): { error: string } | { draft?: unknown } => {
if (!params.apdex_threshold_ms && !templateDefaults.apdexThresholdMs) {
return {
Expand Down Expand Up @@ -219,11 +208,6 @@ function buildAlertRuleRequest(
if (params.renotify_interval_minutes !== undefined)
request.renotifyIntervalMinutes = params.renotify_interval_minutes

// Metric-specific fields
if (params.metric_name) request.metricName = params.metric_name
if (params.metric_type) request.metricType = params.metric_type
if (params.metric_aggregation) request.metricAggregation = params.metric_aggregation

// Apdex-specific fields
if (params.apdex_threshold_ms !== undefined) request.apdexThresholdMs = params.apdex_threshold_ms

Expand Down Expand Up @@ -280,7 +264,7 @@ export function registerCreateAlertRuleTool(server: McpToolRegistrar) {
enabled: optionalBooleanParam("Whether the rule is enabled (default: true)"),
// Custom-mode params (used when template is 'custom' or omitted)
signal_type: optionalStringParam(
"Signal type (for custom): error_rate, p95_latency, p99_latency, apdex, throughput, metric, builder_query, raw_query",
"Signal type (for custom): error_rate, p95_latency, p99_latency, apdex, throughput, builder_query, raw_query. Use builder_query with a metrics draft for custom metrics.",
),
comparator: optionalStringParam(
"Comparison operator (for custom): gt (>), gte (>=), lt (<), lte (<=)",
Expand All @@ -296,13 +280,6 @@ export function registerCreateAlertRuleTool(server: McpToolRegistrar) {
renotify_interval_minutes: optionalNumberParam(
"Re-notification interval in minutes (default: 60)",
),
metric_name: optionalStringParam("Metric name (required when signal_type=metric)"),
metric_type: optionalStringParam(
"Metric type: sum, gauge, histogram, exponential_histogram (required when signal_type=metric)",
),
metric_aggregation: optionalStringParam(
"Metric aggregation: avg, min, max, sum, count (required when signal_type=metric)",
),
apdex_threshold_ms: optionalNumberParam(
"Apdex threshold in milliseconds (required when signal_type=apdex)",
),
Expand Down
11 changes: 0 additions & 11 deletions apps/api/src/mcp/tools/get-alert-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,6 @@ export function registerGetAlertRuleTool(server: McpToolRegistrar) {
lines.push(``)

// Signal-specific fields
if (rule.metricName || rule.metricType || rule.metricAggregation) {
lines.push(`### Metric Configuration`)
if (rule.metricName) lines.push(`Metric Name: ${rule.metricName}`)
if (rule.metricType) lines.push(`Metric Type: ${rule.metricType}`)
if (rule.metricAggregation) lines.push(`Metric Aggregation: ${rule.metricAggregation}`)
lines.push(``)
}

if (rule.apdexThresholdMs) {
lines.push(`### Apdex Configuration`)
lines.push(`Apdex Threshold: ${rule.apdexThresholdMs}ms`)
Expand Down Expand Up @@ -171,9 +163,6 @@ export function registerGetAlertRuleTool(server: McpToolRegistrar) {
consecutiveBreachesRequired: rule.consecutiveBreachesRequired,
consecutiveHealthyRequired: rule.consecutiveHealthyRequired,
renotifyIntervalMinutes: rule.renotifyIntervalMinutes,
metricName: rule.metricName,
metricType: rule.metricType,
metricAggregation: rule.metricAggregation,
apdexThresholdMs: rule.apdexThresholdMs,
queryBuilderDraft: rule.queryBuilderDraft,
rawQuerySql: rule.rawQuerySql,
Expand Down
18 changes: 1 addition & 17 deletions apps/api/src/mcp/tools/update-alert-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ interface UpdateAlertRuleParams {
consecutive_breaches?: number
consecutive_healthy?: number
renotify_interval_minutes?: number
metric_name?: string
metric_type?: string
metric_aggregation?: string
apdex_threshold_ms?: number
query_builder_draft?: string
raw_query_sql?: string
Expand Down Expand Up @@ -85,9 +82,6 @@ function buildUpdatedRequest(
consecutiveBreachesRequired: current.consecutiveBreachesRequired,
consecutiveHealthyRequired: current.consecutiveHealthyRequired,
renotifyIntervalMinutes: current.renotifyIntervalMinutes,
metricName: current.metricName,
metricType: current.metricType,
metricAggregation: current.metricAggregation,
apdexThresholdMs: current.apdexThresholdMs,
queryBuilderDraft: current.queryBuilderDraft,
rawQuerySql: current.rawQuerySql,
Expand All @@ -113,9 +107,6 @@ function buildUpdatedRequest(
request.consecutiveHealthyRequired = params.consecutive_healthy
if (params.renotify_interval_minutes !== undefined)
request.renotifyIntervalMinutes = params.renotify_interval_minutes
if (params.metric_name !== undefined) request.metricName = params.metric_name
if (params.metric_type !== undefined) request.metricType = params.metric_type
if (params.metric_aggregation !== undefined) request.metricAggregation = params.metric_aggregation
if (params.apdex_threshold_ms !== undefined) request.apdexThresholdMs = params.apdex_threshold_ms
if (params.raw_query_sql !== undefined) request.rawQuerySql = params.raw_query_sql
if (params.raw_query_reducer !== undefined) request.rawQueryReducer = params.raw_query_reducer
Expand Down Expand Up @@ -168,7 +159,7 @@ export function registerUpdateAlertRuleTool(server: McpToolRegistrar) {
"Comma-separated destination IDs to notify (replaces the current destinations; use list_alert_rules to find IDs)",
),
signal_type: optionalStringParam(
"Signal type: error_rate, p95_latency, p99_latency, apdex, throughput, metric, builder_query, raw_query",
"Signal type: error_rate, p95_latency, p99_latency, apdex, throughput, builder_query, raw_query. Use builder_query with a metrics draft for custom metrics.",
),
comparator: optionalStringParam("Comparison operator: gt (>), gte (>=), lt (<), lte (<=)"),
group_by: optionalStringParam(
Expand All @@ -179,13 +170,6 @@ export function registerUpdateAlertRuleTool(server: McpToolRegistrar) {
consecutive_breaches: optionalNumberParam("Consecutive breaches before alerting"),
consecutive_healthy: optionalNumberParam("Consecutive healthy evaluations before resolving"),
renotify_interval_minutes: optionalNumberParam("Re-notification interval in minutes"),
metric_name: optionalStringParam("Metric name (for signal_type=metric)"),
metric_type: optionalStringParam(
"Metric type: sum, gauge, histogram, exponential_histogram (for signal_type=metric)",
),
metric_aggregation: optionalStringParam(
"Metric aggregation: avg, min, max, sum, count (for signal_type=metric)",
),
apdex_threshold_ms: optionalNumberParam(
"Apdex threshold in milliseconds (for signal_type=apdex)",
),
Expand Down
162 changes: 0 additions & 162 deletions apps/api/src/routes/alerts.http.ts

This file was deleted.

46 changes: 46 additions & 0 deletions apps/api/src/routes/v2/alert-deliveries.http.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { HttpApiBuilder } from "effect/unstable/httpapi"
import type { AlertDeliveryEventDocument } from "@maple/domain/http"
import { CurrentTenant } from "@maple/domain/http"
import type { V2AlertDelivery } from "@maple/domain/http/v2"
import { MapleApiV2, paginateOffsetQuery, timestamp, timestampOrNull } from "@maple/domain/http/v2"
import { Effect } from "effect"
import { AlertsService } from "../../services/AlertsService"
import { mapAlertError } from "./alerts-error-map"

const toV2Delivery = (doc: AlertDeliveryEventDocument): V2AlertDelivery => ({
id: doc.id,
object: "alert_delivery",
incident_id: doc.incidentId,
rule_id: doc.ruleId,
destination_id: doc.destinationId,
destination_name: doc.destinationName,
destination_type: doc.destinationType,
delivery_key: doc.deliveryKey,
event_type: doc.eventType,
attempt_number: doc.attemptNumber,
status: doc.status,
scheduled_at: timestamp(doc.scheduledAt),
attempted_at: timestampOrNull(doc.attemptedAt),
provider_message: doc.providerMessage,
provider_reference: doc.providerReference,
response_code: doc.responseCode,
error_message: doc.errorMessage,
})

export const HttpV2AlertDeliveriesLive = HttpApiBuilder.group(MapleApiV2, "alertDeliveries", (handlers) =>
Effect.gen(function* () {
const alerts = yield* AlertsService
return handlers.handle("list", ({ query }) =>
Effect.gen(function* () {
const tenant = yield* CurrentTenant.Context
const page = yield* paginateOffsetQuery(query, ({ limit, offset }) =>
alerts.listDeliveryEvents(tenant.orgId, { limit, offset }).pipe(
mapAlertError("delivery_list"),
Effect.map((response) => response.events.map(toV2Delivery)),
),
)
return { object: "list" as const, ...page }
}),
)
}),
)
Loading
Loading