Buckets:
| import { SECRET } from "./secret" | |
| import { domain } from "./stage" | |
| const description = "Managed by SST (Don't edit in Honeycomb UI)" | |
| const alertsDisabled = $app.stage !== "production" | |
| const webhookRecipient = new honeycombio.WebhookRecipient("DiscordAlerts", { | |
| name: $app.stage === "production" ? "Discord Alerts" : `Discord Alerts (${$app.stage})`, | |
| url: `https://${domain}/honeycomb/webhook`, | |
| secret: SECRET.HoneycombWebhookSecret.result, | |
| templates: [ | |
| { | |
| type: "trigger", | |
| body: `{ | |
| "url": {{ .Result.URL | quote }}, | |
| "type": {{ .Vars.type | quote }}, | |
| "name": {{ .Name | quote }}, | |
| "status": {{ .Alert.Status | quote }}, | |
| "isTest": {{ .Alert.IsTest }}, | |
| "groups": {{ .Result.GroupsTriggered | toJson }} | |
| }`, | |
| }, | |
| ], | |
| variables: [ | |
| { | |
| name: "type", | |
| }, | |
| ], | |
| }) | |
| // Honeycomb can keep stale query-local calculated fields when the name is unchanged, | |
| // so tie the field name to the expression while avoiding deploy-to-deploy churn. | |
| // https://github.com/honeycombio/terraform-provider-honeycombio/issues/852 | |
| const calculatedField = (field: { name: string; expression: string }) => ({ | |
| ...field, | |
| name: `${field.name}_${( | |
| Array.from(field.expression).reduce((result, char) => Math.imul(31, result) + char.charCodeAt(0), 0) >>> 0 | |
| ).toString(36)}`, | |
| }) | |
| const modelHttpErrorsQuery = (product: "go" | "zen") => { | |
| const filters = [ | |
| { column: "model", op: "exists" }, | |
| { column: "event_type", op: "=", value: "completions" }, | |
| { column: "user_agent", op: "contains", value: "opencode" }, | |
| { column: "isGoTier", op: "=", value: product === "go" ? "true" : "false" }, | |
| ] | |
| const failedHttpStatus = calculatedField({ | |
| name: "is_failed_http_status", | |
| expression: ` | |
| IF( | |
| AND( | |
| GTE($status, "400"), | |
| NOT(EQUALS($status, "401")), | |
| NOT( | |
| AND( | |
| EQUALS($status, "429"), | |
| OR( | |
| EQUALS($error.type, "GoUsageLimitError"), | |
| EQUALS($error.type, "FreeUsageLimitError") | |
| ) | |
| ) | |
| ) | |
| ), | |
| 1, | |
| 0 | |
| )`, | |
| }) | |
| return honeycombio.getQuerySpecificationOutput({ | |
| breakdowns: ["model"], | |
| calculatedFields: [failedHttpStatus], | |
| calculations: [ | |
| { op: "COUNT", name: "TOTAL", filterCombination: "AND", filters }, | |
| { | |
| op: "SUM", | |
| name: "FAILED", | |
| column: failedHttpStatus.name, | |
| filterCombination: "AND", | |
| filters, | |
| }, | |
| ], | |
| formulas: [{ name: "ERROR", expression: "IF(GTE($TOTAL, 150), DIV($FAILED, $TOTAL), 0)" }], | |
| timeRange: 900, | |
| }).json | |
| } | |
| const providerHttpErrorsQuery = () => { | |
| const filters = [ | |
| { column: "provider", op: "exists" }, | |
| { column: "user_agent", op: "contains", value: "opencode" }, | |
| ] | |
| const successHttpStatus = calculatedField({ | |
| name: "is_success_http_status", | |
| expression: `IF(AND(GTE($status, "200"), LT($status, "400")), 1, 0)`, | |
| }) | |
| const failedProviderHttpStatus = calculatedField({ | |
| name: "is_failed_provider_http_status", | |
| expression: `IF(GT($llm.error.code, "400"), 1, 0)`, | |
| }) | |
| return honeycombio.getQuerySpecificationOutput({ | |
| breakdowns: ["provider"], | |
| calculatedFields: [successHttpStatus, failedProviderHttpStatus], | |
| calculations: [ | |
| { | |
| op: "SUM", | |
| name: "SUCCESS", | |
| column: successHttpStatus.name, | |
| filterCombination: "AND", | |
| filters: [...filters, { column: "event_type", op: "=", value: "completions" }], | |
| }, | |
| { | |
| op: "SUM", | |
| name: "FAILED", | |
| column: failedProviderHttpStatus.name, | |
| filterCombination: "AND", | |
| filters: [ | |
| ...filters, | |
| { column: "event_type", op: "=", value: "llm.error" }, | |
| { column: "llm.error.code", op: "!=", value: "404" }, | |
| ], | |
| }, | |
| ], | |
| formulas: [ | |
| { name: "ERROR", expression: "IF(GTE(SUM($SUCCESS, $FAILED), 150), DIV($FAILED, SUM($SUCCESS, $FAILED)), 0)" }, | |
| ], | |
| timeRange: 900, | |
| }).json | |
| } | |
| const modelLowTpsQuery = (product: "go" | "zen") => { | |
| const filters = [ | |
| { column: "model", op: "exists" }, | |
| { column: "event_type", op: "=", value: "completions" }, | |
| { column: "user_agent", op: "contains", value: "opencode" }, | |
| { column: "isGoTier", op: "=", value: product === "go" ? "true" : "false" }, | |
| { column: "status", op: ">=", value: "200" }, | |
| { column: "status", op: "<", value: "400" }, | |
| { column: "tps.output", op: "exists" }, | |
| ] | |
| return honeycombio.getQuerySpecificationOutput({ | |
| breakdowns: ["model"], | |
| calculations: [ | |
| { op: "COUNT", name: "TOTAL", filterCombination: "AND", filters }, | |
| { | |
| op: "P50", | |
| name: "TPS", | |
| column: "tps.output", | |
| filterCombination: "AND", | |
| filters, | |
| }, | |
| ], | |
| formulas: [{ name: "LOW_TPS", expression: "IF(GTE($TOTAL, 100), $TPS, 999)" }], | |
| timeRange: 1800, | |
| }).json | |
| } | |
| new honeycombio.Trigger("IncreasedModelHttpErrorsGo", { | |
| name: "Increased Model HTTP Errors [Go]", | |
| description, | |
| disabled: alertsDisabled, | |
| queryJson: modelHttpErrorsQuery("go"), | |
| alertType: "on_change", | |
| frequency: 300, | |
| thresholds: [{ op: ">=", value: 0.7, exceededLimit: 1 }], | |
| recipients: [ | |
| { | |
| id: webhookRecipient.id, | |
| notificationDetails: [ | |
| { | |
| variables: [{ name: "type", value: "model_http_errors" }], | |
| }, | |
| ], | |
| }, | |
| ], | |
| }) | |
| new honeycombio.Trigger("IncreasedModelHttpErrorsZen", { | |
| name: "Increased Model HTTP Errors [Zen]", | |
| description, | |
| disabled: alertsDisabled, | |
| queryJson: modelHttpErrorsQuery("zen"), | |
| alertType: "on_change", | |
| frequency: 300, | |
| thresholds: [{ op: ">=", value: 0.7, exceededLimit: 1 }], | |
| recipients: [ | |
| { | |
| id: webhookRecipient.id, | |
| notificationDetails: [ | |
| { | |
| variables: [{ name: "type", value: "model_http_errors" }], | |
| }, | |
| ], | |
| }, | |
| ], | |
| }) | |
| new honeycombio.Trigger("LowModelTpsGo", { | |
| name: "Low Model TPS [Go]", | |
| description, | |
| disabled: alertsDisabled, | |
| queryJson: modelLowTpsQuery("go"), | |
| alertType: "on_change", | |
| frequency: 600, | |
| thresholds: [{ op: "<=", value: 10, exceededLimit: 1 }], | |
| recipients: [ | |
| { | |
| id: webhookRecipient.id, | |
| notificationDetails: [ | |
| { | |
| variables: [{ name: "type", value: "model_low_tps" }], | |
| }, | |
| ], | |
| }, | |
| ], | |
| }) | |
| new honeycombio.Trigger("LowModelTpsZen", { | |
| name: "Low Model TPS [Zen]", | |
| description, | |
| disabled: alertsDisabled, | |
| queryJson: modelLowTpsQuery("zen"), | |
| alertType: "on_change", | |
| frequency: 600, | |
| thresholds: [{ op: "<=", value: 10, exceededLimit: 1 }], | |
| recipients: [ | |
| { | |
| id: webhookRecipient.id, | |
| notificationDetails: [ | |
| { | |
| variables: [{ name: "type", value: "model_low_tps" }], | |
| }, | |
| ], | |
| }, | |
| ], | |
| }) | |
| new honeycombio.Trigger("IncreasedProviderHttpErrors", { | |
| name: "Increased Provider HTTP Errors", | |
| description, | |
| disabled: alertsDisabled, | |
| queryJson: providerHttpErrorsQuery(), | |
| alertType: "on_change", | |
| frequency: 300, | |
| thresholds: [{ op: ">=", value: 0.7, exceededLimit: 1 }], | |
| recipients: [ | |
| { | |
| id: webhookRecipient.id, | |
| notificationDetails: [ | |
| { | |
| variables: [{ name: "type", value: "provider_http_errors" }], | |
| }, | |
| ], | |
| }, | |
| ], | |
| }) | |
| new honeycombio.Trigger("IncreasedFreeTierRequests", { | |
| name: "Increased Free Tier Requests", | |
| description, | |
| disabled: alertsDisabled, | |
| queryJson: honeycombio.getQuerySpecificationOutput({ | |
| calculations: [{ op: "COUNT" }], | |
| filters: [ | |
| { column: "event_type", op: "=", value: "completions" }, | |
| { column: "user_agent", op: "contains", value: "opencode" }, | |
| { column: "isFreeTier", op: "=", value: "true" }, | |
| ], | |
| timeRange: 3600, | |
| }).json, | |
| alertType: "on_change", | |
| frequency: 900, | |
| thresholds: [{ op: ">=", value: 50, exceededLimit: 1 }], | |
| baselineDetails: [{ type: "percentage", offsetMinutes: 1440 }], | |
| recipients: [ | |
| { | |
| id: webhookRecipient.id, | |
| notificationDetails: [ | |
| { | |
| variables: [{ name: "type", value: "custom" }], | |
| }, | |
| ], | |
| }, | |
| ], | |
| }) | |
Xet Storage Details
- Size:
- 8.03 kB
- Xet hash:
- 11b1aead59f7a859f230c07da6ef5d40018580c1942c138d5e559bdd821fffee
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.