monitoring.ts 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import { SECRET } from "./secret"
  2. import { domain } from "./stage"
  3. const webhookRecipient = new honeycomb.WebhookRecipient("DiscordAlerts", {
  4. name: $app.stage === "production" ? "Discord Alerts" : `Discord Alerts (${$app.stage})`,
  5. url: `https://${domain}/honeycomb/webhook`,
  6. secret: SECRET.HoneycombWebhookSecret.result,
  7. templates: [
  8. {
  9. type: "trigger",
  10. body: `{
  11. "url": {{ .Result.URL | quote }},
  12. "type": {{ .Vars.type | quote }},
  13. "name": {{ .Name | quote }},
  14. "status": {{ .Alert.Status | quote }},
  15. "isTest": {{ .Alert.IsTest }},
  16. "groups": {{ .Result.GroupsTriggered | toJson }}
  17. }`,
  18. },
  19. ],
  20. variables: [
  21. {
  22. name: "type",
  23. },
  24. ],
  25. })
  26. const modelHttpErrorsQuery = (product: "go" | "zen") => {
  27. const filters = [
  28. { column: "model", op: "exists" },
  29. { column: "event_type", op: "=", value: "completions" },
  30. { column: "user_agent", op: "contains", value: "opencode" },
  31. { column: "isGoTier", op: "=", value: product === "go" ? "true" : "false" },
  32. ]
  33. return honeycomb.getQuerySpecificationOutput({
  34. breakdowns: ["model"],
  35. calculatedFields: [
  36. {
  37. name: "is_failed_http_status",
  38. expression: `IF(AND(GTE($status, "400"), NOT(EQUALS($status, "401"))), 1, 0)`,
  39. },
  40. ],
  41. calculations: [
  42. { op: "COUNT", name: "TOTAL", filterCombination: "AND", filters },
  43. { op: "SUM", name: "FAILED", column: "is_failed_http_status", filterCombination: "AND", filters },
  44. ],
  45. formulas: [{ name: "ERROR", expression: "IF(GTE($TOTAL, 2500), DIV($FAILED, $TOTAL), 0)" }],
  46. timeRange: 900,
  47. }).json
  48. }
  49. const description = "Managed by SST (Don't edit in Honeycomb UI)"
  50. new honeycomb.Trigger("IncreasedModelHttpErrorsGo", {
  51. name: "Increased Model HTTP Errors [Go]",
  52. description,
  53. queryJson: modelHttpErrorsQuery("go"),
  54. alertType: "on_change",
  55. frequency: 300,
  56. thresholds: [{ op: ">=", value: 0.8, exceededLimit: 1 }],
  57. recipients: [
  58. // {
  59. // id: webhookRecipient.id,
  60. // notificationDetails: [
  61. // {
  62. // variables: [{ name: "type", value: "model_http_errors" }],
  63. // },
  64. // ],
  65. // },
  66. ],
  67. })
  68. new honeycomb.Trigger("IncreasedModelHttpErrorsZen", {
  69. name: "Increased Model HTTP Errors [Zen]",
  70. description,
  71. queryJson: modelHttpErrorsQuery("zen"),
  72. alertType: "on_change",
  73. frequency: 300,
  74. thresholds: [{ op: ">=", value: 0.8, exceededLimit: 1 }],
  75. recipients: [
  76. // {
  77. // id: webhookRecipient.id,
  78. // notificationDetails: [
  79. // {
  80. // variables: [{ name: "type", value: "model_http_errors" }],
  81. // },
  82. // ],
  83. // },
  84. ],
  85. })