@obsunified/collector 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/auth.d.ts +2 -0
- package/dist/auth.js +9 -0
- package/dist/auth.js.map +1 -0
- package/dist/chunk-UGWDOGGH.js +319 -0
- package/dist/chunk-UGWDOGGH.js.map +1 -0
- package/dist/chunk-XKQTVIRE.js +671 -0
- package/dist/chunk-XKQTVIRE.js.map +1 -0
- package/dist/index.d.ts +1197 -0
- package/dist/index.js +17707 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest-auth-HFVO1zIp.d.ts +165 -0
- package/dist/openai-FJYOQ7WO.js +384 -0
- package/dist/openai-FJYOQ7WO.js.map +1 -0
- package/package.json +73 -0
- package/src/ai-parity/ai-parity.acceptance.test.ts +449 -0
- package/src/analyses/derive.ts +642 -0
- package/src/analyses/index.ts +50 -0
- package/src/analyses/investigations.ts +277 -0
- package/src/analyses/tier0.ts +568 -0
- package/src/auth/dashboard-auth.ts +269 -0
- package/src/auth/ingest-auth.ts +147 -0
- package/src/durable-objects/tail-hub.test.ts +32 -0
- package/src/durable-objects/tail-hub.ts +158 -0
- package/src/framework/collector.ts +467 -0
- package/src/framework/env.ts +90 -0
- package/src/framework/logger.ts +81 -0
- package/src/index.ts +211 -0
- package/src/lib/action-aggregates.ts +1031 -0
- package/src/lib/action-identity.ts +106 -0
- package/src/lib/actions-store.ts +397 -0
- package/src/lib/ai-pricing.ts +80 -0
- package/src/lib/ai-store/calls.ts +148 -0
- package/src/lib/ai-store/evaluations.test.ts +47 -0
- package/src/lib/ai-store/evaluations.ts +125 -0
- package/src/lib/ai-store/helpers.ts +37 -0
- package/src/lib/ai-store/retention.ts +17 -0
- package/src/lib/ai-store/sessions.ts +277 -0
- package/src/lib/ai-store/spans.ts +109 -0
- package/src/lib/ai-store/types.ts +112 -0
- package/src/lib/ai-store.ts +76 -0
- package/src/lib/alerts-store.ts +458 -0
- package/src/lib/analyses-runner.ts +439 -0
- package/src/lib/analyses-store.test.ts +243 -0
- package/src/lib/analyses-store.ts +454 -0
- package/src/lib/ask.test.ts +302 -0
- package/src/lib/ask.ts +390 -0
- package/src/lib/blob-store-s3.ts +213 -0
- package/src/lib/blob-store.ts +366 -0
- package/src/lib/eval-cases-store.test.ts +171 -0
- package/src/lib/eval-cases-store.ts +1033 -0
- package/src/lib/evidence-references.test.ts +10 -0
- package/src/lib/evidence-references.ts +684 -0
- package/src/lib/hash.ts +26 -0
- package/src/lib/identity-index/action-lookups.ts +805 -0
- package/src/lib/identity-index/constants.ts +1 -0
- package/src/lib/identity-index/key-lookups.ts +199 -0
- package/src/lib/identity-index/mappers.ts +349 -0
- package/src/lib/identity-index/types.ts +196 -0
- package/src/lib/identity-index/user-lookup.ts +137 -0
- package/src/lib/identity-index.test.ts +624 -0
- package/src/lib/identity-index.ts +85 -0
- package/src/lib/json.ts +39 -0
- package/src/lib/llm.ts +263 -0
- package/src/lib/logs-store.ts +188 -0
- package/src/lib/metrics-store.test.ts +189 -0
- package/src/lib/metrics-store.ts +312 -0
- package/src/lib/narrate-gate.test.ts +260 -0
- package/src/lib/narrate-gate.ts +253 -0
- package/src/lib/openai.test.ts +300 -0
- package/src/lib/openai.ts +512 -0
- package/src/lib/otlp.ts +212 -0
- package/src/lib/parse-pprof.test.ts +64 -0
- package/src/lib/parse-pprof.ts +184 -0
- package/src/lib/payload-capture.ts +22 -0
- package/src/lib/projects-store.ts +207 -0
- package/src/lib/propagation-metric.test.ts +196 -0
- package/src/lib/propagation-metric.ts +175 -0
- package/src/lib/sql-db-dialect.test.ts +22 -0
- package/src/lib/sql-db-postgres.ts +229 -0
- package/src/lib/sql-db.ts +166 -0
- package/src/lib/stage6.test.ts +216 -0
- package/src/lib/store/export.ts +65 -0
- package/src/lib/store/helpers.ts +367 -0
- package/src/lib/store/ingest.ts +68 -0
- package/src/lib/store/issues.ts +158 -0
- package/src/lib/store/overview.ts +127 -0
- package/src/lib/store/retention.ts +10 -0
- package/src/lib/store/service-map.ts +384 -0
- package/src/lib/store/trace-detail.bench.ts +76 -0
- package/src/lib/store/trace-detail.test.ts +410 -0
- package/src/lib/store/trace-detail.ts +427 -0
- package/src/lib/store/trace-queries.test.ts +29 -0
- package/src/lib/store/trace-queries.ts +89 -0
- package/src/lib/store-overview.test.ts +77 -0
- package/src/lib/store.ts +96 -0
- package/src/lib/tail-publisher.ts +64 -0
- package/src/lib/test-utils/mem-sql-db.test.ts +93 -0
- package/src/lib/test-utils/mem-sql-db.ts +86 -0
- package/src/lib/ua-parser.ts +61 -0
- package/src/lib/usage-store.ts +567 -0
- package/src/migrations/001_telemetry_spans.sql +28 -0
- package/src/migrations/002_usage_events.sql +24 -0
- package/src/migrations/003_usage_analytics_columns.sql +13 -0
- package/src/migrations/004_logs.sql +19 -0
- package/src/migrations/005_ai_calls.sql +25 -0
- package/src/migrations/006_user_profiles.sql +11 -0
- package/src/migrations/007_session_replay_metadata.sql +10 -0
- package/src/migrations/008_session_replay_storage_bytes.sql +1 -0
- package/src/migrations/009_projects_and_keys.sql +22 -0
- package/src/migrations/010_signal_project_id.sql +15 -0
- package/src/migrations/011_default_project_seed.sql +3 -0
- package/src/migrations/012_alert_rules.sql +17 -0
- package/src/migrations/013_alert_evaluations.sql +13 -0
- package/src/migrations/014_alert_state.sql +9 -0
- package/src/migrations/015_metrics.sql +58 -0
- package/src/migrations/016_metrics_exp_histogram_summary.sql +5 -0
- package/src/migrations/017_span_dropped_counts.sql +11 -0
- package/src/migrations/018_log_flags.sql +8 -0
- package/src/migrations/019_ai_span_payloads.sql +30 -0
- package/src/migrations/020_ai_span_evaluations.sql +33 -0
- package/src/migrations/021_ai_span_session.sql +13 -0
- package/src/migrations/022_span_log_session_id.sql +13 -0
- package/src/migrations/023_service_map_indexes.sql +32 -0
- package/src/migrations/024_analysis_results.sql +49 -0
- package/src/migrations/025_stage6_autopinning_alerts.sql +38 -0
- package/src/migrations/026_obs_dashboard_project_seed.sql +18 -0
- package/src/migrations/027_identity_propagation.sql +50 -0
- package/src/migrations/028_profile_blobs.sql +57 -0
- package/src/migrations/029_telemetry_sdk_name.sql +20 -0
- package/src/migrations/030_analysis_claim.sql +18 -0
- package/src/migrations/031_agent_action_graph.sql +154 -0
- package/src/migrations/032_payload_capture_flags.sql +8 -0
- package/src/migrations/033_eval_cases.sql +52 -0
- package/src/migrations/034_eval_case_results.sql +23 -0
- package/src/migrations/035_metric_exemplars.sql +33 -0
- package/src/migrations/036_trace_instrumentation_gaps.sql +19 -0
- package/src/migrations/037_eval_runs.sql +37 -0
- package/src/migrations/038_tool_call_evidence.sql +11 -0
- package/src/migrations/039_drop_trace_instrumentation_gaps.sql +11 -0
- package/src/migrations/040_evidence_retrieval_refs.sql +50 -0
- package/src/migrations-postgres/001_telemetry_spans.sql +33 -0
- package/src/migrations-postgres/002_usage_events.sql +24 -0
- package/src/migrations-postgres/003_usage_analytics_columns.sql +13 -0
- package/src/migrations-postgres/004_logs.sql +19 -0
- package/src/migrations-postgres/005_ai_calls.sql +25 -0
- package/src/migrations-postgres/006_user_profiles.sql +11 -0
- package/src/migrations-postgres/007_session_replay_metadata.sql +10 -0
- package/src/migrations-postgres/008_session_replay_storage_bytes.sql +2 -0
- package/src/migrations-postgres/009_projects_and_keys.sql +25 -0
- package/src/migrations-postgres/010_signal_project_id.sql +18 -0
- package/src/migrations-postgres/011_default_project_seed.sql +5 -0
- package/src/migrations-postgres/012_alert_rules.sql +17 -0
- package/src/migrations-postgres/013_alert_evaluations.sql +13 -0
- package/src/migrations-postgres/014_alert_state.sql +9 -0
- package/src/migrations-postgres/015_metrics.sql +47 -0
- package/src/migrations-postgres/016_metrics_exp_histogram_summary.sql +1 -0
- package/src/migrations-postgres/017_span_dropped_counts.sql +4 -0
- package/src/migrations-postgres/018_log_flags.sql +2 -0
- package/src/migrations-postgres/019_ai_span_payloads.sql +18 -0
- package/src/migrations-postgres/020_ai_span_evaluations.sql +21 -0
- package/src/migrations-postgres/021_ai_span_session.sql +7 -0
- package/src/migrations-postgres/022_span_log_session_id.sql +7 -0
- package/src/migrations-postgres/023_service_map_indexes.sql +9 -0
- package/src/migrations-postgres/024_analysis_results.sql +41 -0
- package/src/migrations-postgres/025_stage6_autopinning_alerts.sql +17 -0
- package/src/migrations-postgres/026_obs_dashboard_project_seed.sql +14 -0
- package/src/migrations-postgres/027_identity_propagation.sql +27 -0
- package/src/migrations-postgres/028_profile_blobs.sql +48 -0
- package/src/migrations-postgres/029_telemetry_sdk_name.sql +5 -0
- package/src/migrations-postgres/030_analysis_claim.sql +5 -0
- package/src/migrations-postgres/031_agent_action_graph.sql +190 -0
- package/src/migrations-postgres/032_payload_capture_flags.sql +8 -0
- package/src/migrations-postgres/033_eval_cases.sql +55 -0
- package/src/migrations-postgres/034_eval_case_results.sql +26 -0
- package/src/migrations-postgres/035_metric_exemplars.sql +31 -0
- package/src/migrations-postgres/036_trace_instrumentation_gaps.sql +19 -0
- package/src/migrations-postgres/037_eval_runs.sql +40 -0
- package/src/migrations-postgres/038_tool_call_evidence.sql +11 -0
- package/src/migrations-postgres/039_drop_trace_instrumentation_gaps.sql +11 -0
- package/src/migrations-postgres/040_evidence_retrieval_refs.sql +47 -0
- package/src/migrations-postgres/README.md +40 -0
- package/src/otlp/acceptance.test.ts +373 -0
- package/src/otlp/decode/body.ts +127 -0
- package/src/otlp/decode/logs.ts +96 -0
- package/src/otlp/decode/metrics.ts +402 -0
- package/src/otlp/decode/traces.ts +92 -0
- package/src/otlp/decode/values.ts +150 -0
- package/src/otlp/decode.test.ts +800 -0
- package/src/otlp/decode.ts +11 -0
- package/src/otlp/gen/opentelemetry/proto/collector/logs/v1/logs_service_pb.ts +132 -0
- package/src/otlp/gen/opentelemetry/proto/collector/metrics/v1/metrics_service_pb.ts +158 -0
- package/src/otlp/gen/opentelemetry/proto/collector/trace/v1/trace_service_pb.ts +158 -0
- package/src/otlp/gen/opentelemetry/proto/common/v1/common_pb.ts +289 -0
- package/src/otlp/gen/opentelemetry/proto/logs/v1/logs_pb.ts +397 -0
- package/src/otlp/gen/opentelemetry/proto/metrics/v1/metrics_pb.ts +1329 -0
- package/src/otlp/gen/opentelemetry/proto/resource/v1/resource_pb.ts +86 -0
- package/src/otlp/gen/opentelemetry/proto/trace/v1/trace_pb.ts +710 -0
- package/src/otlp/response.test.ts +158 -0
- package/src/otlp/response.ts +129 -0
- package/src/plugins/_context.ts +15 -0
- package/src/plugins/action-graph-processor/enrichers.ts +45 -0
- package/src/plugins/action-graph-processor/redaction.ts +84 -0
- package/src/plugins/action-graph-processor.test.ts +1023 -0
- package/src/plugins/action-graph-processor.ts +1172 -0
- package/src/plugins/action-routes.test.ts +716 -0
- package/src/plugins/action-routes.ts +343 -0
- package/src/plugins/ai-receiver.ts +254 -0
- package/src/plugins/ai-span-payloads-processor.test.ts +90 -0
- package/src/plugins/ai-span-payloads-processor.ts +180 -0
- package/src/plugins/alerts-evaluator.test.ts +91 -0
- package/src/plugins/alerts-evaluator.ts +328 -0
- package/src/plugins/alerts-routes.ts +101 -0
- package/src/plugins/analyses-routes.ts +138 -0
- package/src/plugins/ask-routes.ts +182 -0
- package/src/plugins/bot-filter.ts +19 -0
- package/src/plugins/connected-routes/manifest.ts +531 -0
- package/src/plugins/connected-routes.test.ts +1791 -0
- package/src/plugins/connected-routes.ts +1103 -0
- package/src/plugins/dashboard-routes.ts +41 -0
- package/src/plugins/default-span-enrichment.ts +92 -0
- package/src/plugins/eval-cases-routes.test.ts +391 -0
- package/src/plugins/eval-cases-routes.ts +529 -0
- package/src/plugins/evidence-retrieval-routes.benchmark.test.ts +245 -0
- package/src/plugins/evidence-retrieval-routes.test.ts +932 -0
- package/src/plugins/evidence-retrieval-routes.ts +2179 -0
- package/src/plugins/gen-ai-normalizer.test.ts +680 -0
- package/src/plugins/gen-ai-normalizer.ts +302 -0
- package/src/plugins/identity-receiver.ts +96 -0
- package/src/plugins/issue-enrichment.ts +132 -0
- package/src/plugins/issue-insights.ts +81 -0
- package/src/plugins/logs-receiver.ts +160 -0
- package/src/plugins/metrics-receiver.ts +91 -0
- package/src/plugins/onboarding-routes.ts +54 -0
- package/src/plugins/otlp-receiver.ts +124 -0
- package/src/plugins/platform-routes.ts +165 -0
- package/src/plugins/profile-routes.ts +468 -0
- package/src/plugins/projects-routes.ts +92 -0
- package/src/plugins/query-routes.ts +220 -0
- package/src/plugins/redaction-processor.ts +132 -0
- package/src/plugins/replay-query-routes.test.ts +38 -0
- package/src/plugins/replay-query-routes.ts +199 -0
- package/src/plugins/replay-receiver.ts +81 -0
- package/src/plugins/tail-routes.test.ts +47 -0
- package/src/plugins/tail-routes.ts +42 -0
- package/src/plugins/timeline-routes.ts +244 -0
- package/src/plugins/ua-enrichment.ts +27 -0
- package/src/plugins/usage-normalization.ts +46 -0
- package/src/plugins/usage-privacy.ts +55 -0
- package/src/plugins/usage-query-routes.ts +102 -0
- package/src/plugins/usage-receiver.ts +129 -0
- package/src/plugins/users-query-routes.ts +78 -0
- package/src/plugins/utm-enrichment.ts +36 -0
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
// RFC 0002 Stage 1 — Tier 0 universal analyses.
|
|
2
|
+
//
|
|
3
|
+
// These six analyses apply to any install regardless of detected app shape.
|
|
4
|
+
// Each `sql` string is executable as-is by the runner (Agent 1). The runner
|
|
5
|
+
// substitutes the literal token `{{PROJECT_ID}}` with the active project's
|
|
6
|
+
// id before execution; everything else (time windows, thresholds) is baked
|
|
7
|
+
// into the SQL itself.
|
|
8
|
+
//
|
|
9
|
+
// The runner expects a single-row result with these columns:
|
|
10
|
+
// status TEXT — 'ok' | 'warn' | 'critical' | 'unknown'
|
|
11
|
+
// primary_value REAL — the headline number (NULL allowed)
|
|
12
|
+
// baseline_value REAL — the comparison number (NULL allowed)
|
|
13
|
+
// payload TEXT — JSON string built with json_object(...) /
|
|
14
|
+
// json_group_array(...) for charts, contributors, etc.
|
|
15
|
+
//
|
|
16
|
+
// delta_pct is precomputed by the runner from primary/baseline.
|
|
17
|
+
|
|
18
|
+
import type { AnalysisDefinition } from "@obsunified/types";
|
|
19
|
+
|
|
20
|
+
// ── overall_error_rate ──────────────────────────────────────────────────────
|
|
21
|
+
// Error spans in the last 5 minutes vs. the trailing 1h baseline rate.
|
|
22
|
+
// Status: critical if rate>5%, warn if rate>1%, ok otherwise. unknown if
|
|
23
|
+
// no traffic in either window.
|
|
24
|
+
const overallErrorRate: AnalysisDefinition = {
|
|
25
|
+
id: "overall_error_rate",
|
|
26
|
+
title: "Overall error rate",
|
|
27
|
+
group: "Health",
|
|
28
|
+
source: "tier0",
|
|
29
|
+
view: "tile",
|
|
30
|
+
refreshSeconds: 60,
|
|
31
|
+
narrate: {
|
|
32
|
+
prompt:
|
|
33
|
+
"Errors moved to {{primary}} (was {{baseline}}, {{delta_pct}}). Name the dominant offending span name or service if visible in the payload, with a time anchor.",
|
|
34
|
+
only_when: "status_changed || delta_pct>20",
|
|
35
|
+
},
|
|
36
|
+
sql: `
|
|
37
|
+
WITH now_window AS (
|
|
38
|
+
SELECT
|
|
39
|
+
COUNT(*) AS total,
|
|
40
|
+
SUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors
|
|
41
|
+
FROM telemetry_spans
|
|
42
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
43
|
+
AND received_at >= datetime('now', '-5 minutes')
|
|
44
|
+
),
|
|
45
|
+
base_window AS (
|
|
46
|
+
SELECT
|
|
47
|
+
COUNT(*) AS total,
|
|
48
|
+
SUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors
|
|
49
|
+
FROM telemetry_spans
|
|
50
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
51
|
+
AND received_at >= datetime('now', '-1 hour')
|
|
52
|
+
AND received_at < datetime('now', '-5 minutes')
|
|
53
|
+
),
|
|
54
|
+
spark AS (
|
|
55
|
+
-- per-minute error rate over the last 30 minutes for sparkline rendering
|
|
56
|
+
SELECT
|
|
57
|
+
strftime('%Y-%m-%dT%H:%M:00Z', received_at) AS minute,
|
|
58
|
+
COUNT(*) AS total,
|
|
59
|
+
SUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors
|
|
60
|
+
FROM telemetry_spans
|
|
61
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
62
|
+
AND received_at >= datetime('now', '-30 minutes')
|
|
63
|
+
GROUP BY minute
|
|
64
|
+
ORDER BY minute ASC
|
|
65
|
+
)
|
|
66
|
+
SELECT
|
|
67
|
+
CASE
|
|
68
|
+
WHEN (SELECT total FROM now_window) = 0 THEN 'unknown'
|
|
69
|
+
WHEN (CAST((SELECT errors FROM now_window) AS REAL)
|
|
70
|
+
/ (SELECT total FROM now_window)) > 0.05 THEN 'critical'
|
|
71
|
+
WHEN (CAST((SELECT errors FROM now_window) AS REAL)
|
|
72
|
+
/ (SELECT total FROM now_window)) > 0.01 THEN 'warn'
|
|
73
|
+
ELSE 'ok'
|
|
74
|
+
END AS status,
|
|
75
|
+
CASE WHEN (SELECT total FROM now_window) = 0 THEN NULL
|
|
76
|
+
ELSE CAST((SELECT errors FROM now_window) AS REAL)
|
|
77
|
+
/ (SELECT total FROM now_window) END AS primary_value,
|
|
78
|
+
CASE WHEN (SELECT total FROM base_window) = 0 THEN NULL
|
|
79
|
+
ELSE CAST((SELECT errors FROM base_window) AS REAL)
|
|
80
|
+
/ (SELECT total FROM base_window) END AS baseline_value,
|
|
81
|
+
(SELECT json_object(
|
|
82
|
+
'window', '5m',
|
|
83
|
+
'baselineWindow', '1h',
|
|
84
|
+
'currentErrors', (SELECT errors FROM now_window),
|
|
85
|
+
'currentTotal', (SELECT total FROM now_window),
|
|
86
|
+
'baselineErrors',(SELECT errors FROM base_window),
|
|
87
|
+
'baselineTotal', (SELECT total FROM base_window),
|
|
88
|
+
'sparkline', (
|
|
89
|
+
SELECT json_group_array(json_object(
|
|
90
|
+
'minute', minute,
|
|
91
|
+
'total', total,
|
|
92
|
+
'errors', errors,
|
|
93
|
+
'rate', CASE WHEN total = 0 THEN 0
|
|
94
|
+
ELSE CAST(errors AS REAL) / total END
|
|
95
|
+
)) FROM spark
|
|
96
|
+
)
|
|
97
|
+
)) AS payload
|
|
98
|
+
`,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// ── top_error_services ──────────────────────────────────────────────────────
|
|
102
|
+
// Top 5 services by error count in the last 5 minutes.
|
|
103
|
+
// Status: critical if any service has >10 errors/min (i.e. >50 in 5min),
|
|
104
|
+
// warn if any has >2 errors/min (i.e. >10 in 5min), ok otherwise. unknown
|
|
105
|
+
// if no errors at all.
|
|
106
|
+
const topErrorServices: AnalysisDefinition = {
|
|
107
|
+
id: "top_error_services",
|
|
108
|
+
title: "Top error services",
|
|
109
|
+
group: "Health",
|
|
110
|
+
source: "tier0",
|
|
111
|
+
view: "tile",
|
|
112
|
+
refreshSeconds: 60,
|
|
113
|
+
narrate: {
|
|
114
|
+
prompt:
|
|
115
|
+
"List the top 1–2 erroring services and their counts (from payload). Include a time anchor like 'in the last 5 minutes'.",
|
|
116
|
+
only_when: "signature_changed",
|
|
117
|
+
},
|
|
118
|
+
sql: `
|
|
119
|
+
WITH per_service AS (
|
|
120
|
+
SELECT
|
|
121
|
+
COALESCE(service_name, '<unknown>') AS service,
|
|
122
|
+
COUNT(*) AS total,
|
|
123
|
+
SUM(CASE WHEN status_code = 2 THEN 1 ELSE 0 END) AS errors
|
|
124
|
+
FROM telemetry_spans
|
|
125
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
126
|
+
AND received_at >= datetime('now', '-5 minutes')
|
|
127
|
+
GROUP BY service
|
|
128
|
+
),
|
|
129
|
+
top5 AS (
|
|
130
|
+
SELECT service, total, errors
|
|
131
|
+
FROM per_service
|
|
132
|
+
WHERE errors > 0
|
|
133
|
+
ORDER BY errors DESC
|
|
134
|
+
LIMIT 5
|
|
135
|
+
),
|
|
136
|
+
max_err AS (SELECT COALESCE(MAX(errors), 0) AS m FROM top5)
|
|
137
|
+
SELECT
|
|
138
|
+
CASE
|
|
139
|
+
WHEN (SELECT m FROM max_err) = 0 THEN 'unknown'
|
|
140
|
+
-- thresholds are per-minute averaged over the 5-minute window
|
|
141
|
+
WHEN (SELECT m FROM max_err) > 50 THEN 'critical'
|
|
142
|
+
WHEN (SELECT m FROM max_err) > 10 THEN 'warn'
|
|
143
|
+
ELSE 'ok'
|
|
144
|
+
END AS status,
|
|
145
|
+
(SELECT m FROM max_err) AS primary_value,
|
|
146
|
+
NULL AS baseline_value,
|
|
147
|
+
(SELECT json_object(
|
|
148
|
+
'window', '5m',
|
|
149
|
+
'services', (
|
|
150
|
+
SELECT json_group_array(json_object(
|
|
151
|
+
'service', service,
|
|
152
|
+
'errors', errors,
|
|
153
|
+
'total', total
|
|
154
|
+
)) FROM top5
|
|
155
|
+
)
|
|
156
|
+
)) AS payload
|
|
157
|
+
`,
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// ── latency_p95_overall ─────────────────────────────────────────────────────
|
|
161
|
+
// p95 across all spans this hour vs. the same hour yesterday.
|
|
162
|
+
// SQLite has no native percentile, so we approximate via ROW_NUMBER ordering:
|
|
163
|
+
// pick the row at offset CEIL(0.95 * n) - 1 in ascending duration order.
|
|
164
|
+
// Status by delta_pct: critical>50%, warn>20%, ok else. unknown when either
|
|
165
|
+
// window is empty.
|
|
166
|
+
const latencyP95Overall: AnalysisDefinition = {
|
|
167
|
+
id: "latency_p95_overall",
|
|
168
|
+
title: "Latency p95 — overall",
|
|
169
|
+
group: "Health",
|
|
170
|
+
source: "tier0",
|
|
171
|
+
view: "tile",
|
|
172
|
+
// Latency is one of the primary signals; 60s matches Tier 0 spec.
|
|
173
|
+
refreshSeconds: 60,
|
|
174
|
+
narrate: {
|
|
175
|
+
prompt:
|
|
176
|
+
"p95 moved to {{primary}}ms from {{baseline}}ms ({{delta_pct}}). Name the slowest service or route if visible in the payload, with a time anchor.",
|
|
177
|
+
only_when: "status_changed || delta_pct>25",
|
|
178
|
+
},
|
|
179
|
+
sql: `
|
|
180
|
+
WITH cur AS (
|
|
181
|
+
SELECT duration_ms,
|
|
182
|
+
ROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,
|
|
183
|
+
COUNT(*) OVER () AS n
|
|
184
|
+
FROM telemetry_spans
|
|
185
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
186
|
+
AND received_at >= datetime('now', '-1 hour')
|
|
187
|
+
),
|
|
188
|
+
base AS (
|
|
189
|
+
SELECT duration_ms,
|
|
190
|
+
ROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,
|
|
191
|
+
COUNT(*) OVER () AS n
|
|
192
|
+
FROM telemetry_spans
|
|
193
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
194
|
+
AND received_at >= datetime('now', '-25 hours')
|
|
195
|
+
AND received_at < datetime('now', '-24 hours')
|
|
196
|
+
),
|
|
197
|
+
cur_p95 AS (
|
|
198
|
+
SELECT duration_ms FROM cur
|
|
199
|
+
WHERE rn = MAX(1, (95 * n + 99) / 100)
|
|
200
|
+
LIMIT 1
|
|
201
|
+
),
|
|
202
|
+
base_p95 AS (
|
|
203
|
+
SELECT duration_ms FROM base
|
|
204
|
+
WHERE rn = MAX(1, (95 * n + 99) / 100)
|
|
205
|
+
LIMIT 1
|
|
206
|
+
),
|
|
207
|
+
spark AS (
|
|
208
|
+
-- per-5-minute approx-p95 buckets across the current hour for sparkline
|
|
209
|
+
SELECT
|
|
210
|
+
strftime('%Y-%m-%dT%H:%M:00Z',
|
|
211
|
+
datetime((CAST(strftime('%s', received_at) AS INTEGER) / 300) * 300, 'unixepoch')
|
|
212
|
+
) AS bucket,
|
|
213
|
+
MAX(duration_ms) AS approx_max,
|
|
214
|
+
COUNT(*) AS n
|
|
215
|
+
FROM telemetry_spans
|
|
216
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
217
|
+
AND received_at >= datetime('now', '-1 hour')
|
|
218
|
+
GROUP BY bucket
|
|
219
|
+
ORDER BY bucket ASC
|
|
220
|
+
),
|
|
221
|
+
cur_val AS (SELECT (SELECT duration_ms FROM cur_p95) AS v),
|
|
222
|
+
base_val AS (SELECT (SELECT duration_ms FROM base_p95) AS v),
|
|
223
|
+
delta AS (
|
|
224
|
+
SELECT CASE
|
|
225
|
+
WHEN (SELECT v FROM cur_val) IS NULL THEN NULL
|
|
226
|
+
WHEN (SELECT v FROM base_val) IS NULL OR (SELECT v FROM base_val) = 0 THEN NULL
|
|
227
|
+
ELSE ((SELECT v FROM cur_val) - (SELECT v FROM base_val))
|
|
228
|
+
* 100.0 / (SELECT v FROM base_val)
|
|
229
|
+
END AS pct
|
|
230
|
+
)
|
|
231
|
+
SELECT
|
|
232
|
+
CASE
|
|
233
|
+
WHEN (SELECT v FROM cur_val) IS NULL THEN 'unknown'
|
|
234
|
+
WHEN (SELECT pct FROM delta) IS NULL THEN 'ok'
|
|
235
|
+
WHEN ABS((SELECT pct FROM delta)) > 50 THEN 'critical'
|
|
236
|
+
WHEN ABS((SELECT pct FROM delta)) > 20 THEN 'warn'
|
|
237
|
+
ELSE 'ok'
|
|
238
|
+
END AS status,
|
|
239
|
+
(SELECT v FROM cur_val) AS primary_value,
|
|
240
|
+
(SELECT v FROM base_val) AS baseline_value,
|
|
241
|
+
(SELECT json_object(
|
|
242
|
+
'window', '1h',
|
|
243
|
+
'baselineWindow', 'same hour yesterday',
|
|
244
|
+
'unit', 'ms',
|
|
245
|
+
'sparkline', (
|
|
246
|
+
SELECT json_group_array(json_object(
|
|
247
|
+
'bucket', bucket,
|
|
248
|
+
'approxP95Ms', approx_max,
|
|
249
|
+
'samples', n
|
|
250
|
+
)) FROM spark
|
|
251
|
+
)
|
|
252
|
+
)) AS payload
|
|
253
|
+
`,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// ── throughput_slope ────────────────────────────────────────────────────────
|
|
257
|
+
// Spans/minute trend: last 30 minutes vs the prior 30 minutes.
|
|
258
|
+
// Status: warn if slope > 1.5x AND p99 trending up (current p99 > prior p99);
|
|
259
|
+
// ok otherwise. unknown if both windows empty.
|
|
260
|
+
const throughputSlope: AnalysisDefinition = {
|
|
261
|
+
id: "throughput_slope",
|
|
262
|
+
title: "Throughput slope",
|
|
263
|
+
group: "Health",
|
|
264
|
+
source: "tier0",
|
|
265
|
+
view: "tile",
|
|
266
|
+
refreshSeconds: 60,
|
|
267
|
+
sql: `
|
|
268
|
+
WITH cur AS (
|
|
269
|
+
SELECT duration_ms,
|
|
270
|
+
ROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,
|
|
271
|
+
COUNT(*) OVER () AS n
|
|
272
|
+
FROM telemetry_spans
|
|
273
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
274
|
+
AND received_at >= datetime('now', '-30 minutes')
|
|
275
|
+
),
|
|
276
|
+
prev AS (
|
|
277
|
+
SELECT duration_ms,
|
|
278
|
+
ROW_NUMBER() OVER (ORDER BY duration_ms ASC) AS rn,
|
|
279
|
+
COUNT(*) OVER () AS n
|
|
280
|
+
FROM telemetry_spans
|
|
281
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
282
|
+
AND received_at >= datetime('now', '-60 minutes')
|
|
283
|
+
AND received_at < datetime('now', '-30 minutes')
|
|
284
|
+
),
|
|
285
|
+
cur_n AS (SELECT COALESCE((SELECT n FROM cur LIMIT 1), 0) AS n),
|
|
286
|
+
prev_n AS (SELECT COALESCE((SELECT n FROM prev LIMIT 1), 0) AS n),
|
|
287
|
+
cur_p99 AS (
|
|
288
|
+
SELECT duration_ms FROM cur
|
|
289
|
+
WHERE rn = MAX(1, (99 * n + 99) / 100)
|
|
290
|
+
LIMIT 1
|
|
291
|
+
),
|
|
292
|
+
prev_p99 AS (
|
|
293
|
+
SELECT duration_ms FROM prev
|
|
294
|
+
WHERE rn = MAX(1, (99 * n + 99) / 100)
|
|
295
|
+
LIMIT 1
|
|
296
|
+
),
|
|
297
|
+
rates AS (
|
|
298
|
+
SELECT
|
|
299
|
+
CAST((SELECT n FROM cur_n) AS REAL) / 30.0 AS current_rpm,
|
|
300
|
+
CAST((SELECT n FROM prev_n) AS REAL) / 30.0 AS prior_rpm
|
|
301
|
+
),
|
|
302
|
+
slope_calc AS (
|
|
303
|
+
SELECT
|
|
304
|
+
current_rpm,
|
|
305
|
+
prior_rpm,
|
|
306
|
+
CASE WHEN prior_rpm = 0 THEN NULL
|
|
307
|
+
ELSE current_rpm / prior_rpm END AS slope
|
|
308
|
+
FROM rates
|
|
309
|
+
)
|
|
310
|
+
SELECT
|
|
311
|
+
CASE
|
|
312
|
+
WHEN (SELECT n FROM cur_n) = 0 AND (SELECT n FROM prev_n) = 0 THEN 'unknown'
|
|
313
|
+
WHEN (SELECT slope FROM slope_calc) IS NOT NULL
|
|
314
|
+
AND (SELECT slope FROM slope_calc) > 1.5
|
|
315
|
+
AND COALESCE((SELECT duration_ms FROM cur_p99), 0)
|
|
316
|
+
> COALESCE((SELECT duration_ms FROM prev_p99), 0)
|
|
317
|
+
THEN 'warn'
|
|
318
|
+
ELSE 'ok'
|
|
319
|
+
END AS status,
|
|
320
|
+
(SELECT current_rpm FROM rates) AS primary_value,
|
|
321
|
+
(SELECT prior_rpm FROM rates) AS baseline_value,
|
|
322
|
+
(SELECT json_object(
|
|
323
|
+
'currentRpm', (SELECT current_rpm FROM rates),
|
|
324
|
+
'priorRpm', (SELECT prior_rpm FROM rates),
|
|
325
|
+
'slope', (SELECT slope FROM slope_calc),
|
|
326
|
+
'currentP99Ms', (SELECT duration_ms FROM cur_p99),
|
|
327
|
+
'priorP99Ms', (SELECT duration_ms FROM prev_p99),
|
|
328
|
+
'window', '30m',
|
|
329
|
+
'baselineWindow', 'prior 30m'
|
|
330
|
+
)) AS payload
|
|
331
|
+
`,
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
// ── active_sessions ─────────────────────────────────────────────────────────
|
|
335
|
+
// Distinct frontend sessions in usage_events for the last 15 minutes plus
|
|
336
|
+
// per-hour breakdown across the trailing 24h. Always status: 'ok' — this is
|
|
337
|
+
// informational. unknown only if the table is missing data entirely.
|
|
338
|
+
const activeSessions: AnalysisDefinition = {
|
|
339
|
+
id: "active_sessions",
|
|
340
|
+
title: "Active sessions",
|
|
341
|
+
group: "Frontend",
|
|
342
|
+
source: "tier0",
|
|
343
|
+
view: "tile",
|
|
344
|
+
refreshSeconds: 60,
|
|
345
|
+
sql: `
|
|
346
|
+
WITH active AS (
|
|
347
|
+
SELECT COUNT(DISTINCT session_id) AS n
|
|
348
|
+
FROM usage_events
|
|
349
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
350
|
+
AND received_at >= datetime('now', '-15 minutes')
|
|
351
|
+
),
|
|
352
|
+
hourly AS (
|
|
353
|
+
SELECT
|
|
354
|
+
strftime('%Y-%m-%dT%H:00:00Z', received_at) AS hour,
|
|
355
|
+
COUNT(DISTINCT session_id) AS sessions
|
|
356
|
+
FROM usage_events
|
|
357
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
358
|
+
AND received_at >= datetime('now', '-24 hours')
|
|
359
|
+
GROUP BY hour
|
|
360
|
+
ORDER BY hour ASC
|
|
361
|
+
)
|
|
362
|
+
SELECT
|
|
363
|
+
'ok' AS status,
|
|
364
|
+
CAST((SELECT n FROM active) AS REAL) AS primary_value,
|
|
365
|
+
NULL AS baseline_value,
|
|
366
|
+
(SELECT json_object(
|
|
367
|
+
'count', (SELECT n FROM active),
|
|
368
|
+
'window', '15m',
|
|
369
|
+
'hourlyBreakdown', (
|
|
370
|
+
SELECT json_group_array(json_object(
|
|
371
|
+
'hour', hour,
|
|
372
|
+
'sessions', sessions
|
|
373
|
+
)) FROM hourly
|
|
374
|
+
)
|
|
375
|
+
)) AS payload
|
|
376
|
+
`,
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// ── log_error_rate ──────────────────────────────────────────────────────────
|
|
380
|
+
// Error+fatal logs in the last 5 minutes vs. the trailing 1h baseline rate.
|
|
381
|
+
// severity_number follows OTel: ERROR=17-20, FATAL=21-24.
|
|
382
|
+
// Status: critical if rate>5%, warn if rate>1%, ok otherwise. unknown if
|
|
383
|
+
// no logs in either window.
|
|
384
|
+
const logErrorRate: AnalysisDefinition = {
|
|
385
|
+
id: "log_error_rate",
|
|
386
|
+
narrate: {
|
|
387
|
+
prompt:
|
|
388
|
+
"Log error rate is {{primary}} (was {{baseline}}, {{delta_pct}}). If a logger or message pattern dominates the payload, name it. Time anchor.",
|
|
389
|
+
only_when: "status_changed || delta_pct>25",
|
|
390
|
+
},
|
|
391
|
+
title: "Log error rate",
|
|
392
|
+
group: "Health",
|
|
393
|
+
source: "tier0",
|
|
394
|
+
view: "tile",
|
|
395
|
+
refreshSeconds: 60,
|
|
396
|
+
sql: `
|
|
397
|
+
WITH now_window AS (
|
|
398
|
+
SELECT
|
|
399
|
+
COUNT(*) AS total,
|
|
400
|
+
SUM(CASE WHEN severity_number >= 17 THEN 1 ELSE 0 END) AS errors
|
|
401
|
+
FROM logs
|
|
402
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
403
|
+
AND received_at >= datetime('now', '-5 minutes')
|
|
404
|
+
),
|
|
405
|
+
base_window AS (
|
|
406
|
+
SELECT
|
|
407
|
+
COUNT(*) AS total,
|
|
408
|
+
SUM(CASE WHEN severity_number >= 17 THEN 1 ELSE 0 END) AS errors
|
|
409
|
+
FROM logs
|
|
410
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
411
|
+
AND received_at >= datetime('now', '-1 hour')
|
|
412
|
+
AND received_at < datetime('now', '-5 minutes')
|
|
413
|
+
),
|
|
414
|
+
spark AS (
|
|
415
|
+
SELECT
|
|
416
|
+
strftime('%Y-%m-%dT%H:%M:00Z', received_at) AS minute,
|
|
417
|
+
COUNT(*) AS total,
|
|
418
|
+
SUM(CASE WHEN severity_number >= 17 THEN 1 ELSE 0 END) AS errors
|
|
419
|
+
FROM logs
|
|
420
|
+
WHERE project_id = '{{PROJECT_ID}}'
|
|
421
|
+
AND received_at >= datetime('now', '-30 minutes')
|
|
422
|
+
GROUP BY minute
|
|
423
|
+
ORDER BY minute ASC
|
|
424
|
+
)
|
|
425
|
+
SELECT
|
|
426
|
+
CASE
|
|
427
|
+
WHEN (SELECT total FROM now_window) = 0 THEN 'unknown'
|
|
428
|
+
WHEN (CAST((SELECT errors FROM now_window) AS REAL)
|
|
429
|
+
/ (SELECT total FROM now_window)) > 0.05 THEN 'critical'
|
|
430
|
+
WHEN (CAST((SELECT errors FROM now_window) AS REAL)
|
|
431
|
+
/ (SELECT total FROM now_window)) > 0.01 THEN 'warn'
|
|
432
|
+
ELSE 'ok'
|
|
433
|
+
END AS status,
|
|
434
|
+
CASE WHEN (SELECT total FROM now_window) = 0 THEN NULL
|
|
435
|
+
ELSE CAST((SELECT errors FROM now_window) AS REAL)
|
|
436
|
+
/ (SELECT total FROM now_window) END AS primary_value,
|
|
437
|
+
CASE WHEN (SELECT total FROM base_window) = 0 THEN NULL
|
|
438
|
+
ELSE CAST((SELECT errors FROM base_window) AS REAL)
|
|
439
|
+
/ (SELECT total FROM base_window) END AS baseline_value,
|
|
440
|
+
(SELECT json_object(
|
|
441
|
+
'window', '5m',
|
|
442
|
+
'baselineWindow', '1h',
|
|
443
|
+
'currentErrors', (SELECT errors FROM now_window),
|
|
444
|
+
'currentTotal', (SELECT total FROM now_window),
|
|
445
|
+
'baselineErrors',(SELECT errors FROM base_window),
|
|
446
|
+
'baselineTotal', (SELECT total FROM base_window),
|
|
447
|
+
'sparkline', (
|
|
448
|
+
SELECT json_group_array(json_object(
|
|
449
|
+
'minute', minute,
|
|
450
|
+
'total', total,
|
|
451
|
+
'errors', errors,
|
|
452
|
+
'rate', CASE WHEN total = 0 THEN 0
|
|
453
|
+
ELSE CAST(errors AS REAL) / total END
|
|
454
|
+
)) FROM spark
|
|
455
|
+
)
|
|
456
|
+
)) AS payload
|
|
457
|
+
`,
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
// ── service_cpu_utilization ─────────────────────────────────────────────────
|
|
461
|
+
// RFC 0005 Phase 2.6 — fleet-wide process CPU utilization tile.
|
|
462
|
+
// Reads `process.cpu.utilization` gauge points emitted by
|
|
463
|
+
// @obsunified/telemetry-sdk's enableProcessMetrics() helper (or any other OTel
|
|
464
|
+
// runtime-metrics exporter using the standard semconv).
|
|
465
|
+
//
|
|
466
|
+
// Status: critical if any service averaged >0.9 over the last 5 min,
|
|
467
|
+
// warn if >0.7, ok otherwise. unknown if no process.cpu.* series at all
|
|
468
|
+
// (the typical state on a fresh install before enableProcessMetrics
|
|
469
|
+
// is wired into the user's services).
|
|
470
|
+
const serviceCpuUtilization: AnalysisDefinition = {
|
|
471
|
+
id: "service_cpu_utilization",
|
|
472
|
+
title: "Service CPU utilization",
|
|
473
|
+
group: "Services",
|
|
474
|
+
source: "tier0",
|
|
475
|
+
view: "tile",
|
|
476
|
+
refreshSeconds: 60,
|
|
477
|
+
narrate: {
|
|
478
|
+
prompt:
|
|
479
|
+
"Name the busiest service and its average utilization over the last 5 minutes. Mention if it crossed a critical (>0.9) or warn (>0.7) threshold.",
|
|
480
|
+
only_when: "status_changed",
|
|
481
|
+
},
|
|
482
|
+
sql: `
|
|
483
|
+
WITH cpu_points AS (
|
|
484
|
+
SELECT
|
|
485
|
+
s.service_name,
|
|
486
|
+
p.value,
|
|
487
|
+
p.received_at
|
|
488
|
+
FROM metric_point p
|
|
489
|
+
JOIN metric_series s ON s.id = p.series_id
|
|
490
|
+
WHERE s.project_id = '{{PROJECT_ID}}'
|
|
491
|
+
AND s.name = 'process.cpu.utilization'
|
|
492
|
+
AND s.service_name IS NOT NULL
|
|
493
|
+
AND p.received_at >= datetime('now', '-30 minutes')
|
|
494
|
+
),
|
|
495
|
+
now_window AS (
|
|
496
|
+
SELECT service_name, AVG(value) AS avg_util
|
|
497
|
+
FROM cpu_points
|
|
498
|
+
WHERE received_at >= datetime('now', '-5 minutes')
|
|
499
|
+
GROUP BY service_name
|
|
500
|
+
),
|
|
501
|
+
base_window AS (
|
|
502
|
+
SELECT service_name, AVG(value) AS avg_util
|
|
503
|
+
FROM cpu_points
|
|
504
|
+
WHERE received_at >= datetime('now', '-30 minutes')
|
|
505
|
+
AND received_at < datetime('now', '-5 minutes')
|
|
506
|
+
GROUP BY service_name
|
|
507
|
+
),
|
|
508
|
+
top_now AS (
|
|
509
|
+
SELECT service_name, avg_util
|
|
510
|
+
FROM now_window
|
|
511
|
+
ORDER BY avg_util DESC
|
|
512
|
+
LIMIT 5
|
|
513
|
+
),
|
|
514
|
+
fleet_max AS (
|
|
515
|
+
SELECT COALESCE(MAX(avg_util), 0) AS m FROM now_window
|
|
516
|
+
),
|
|
517
|
+
top_service AS (
|
|
518
|
+
SELECT service_name
|
|
519
|
+
FROM now_window
|
|
520
|
+
ORDER BY avg_util DESC
|
|
521
|
+
LIMIT 1
|
|
522
|
+
),
|
|
523
|
+
spark AS (
|
|
524
|
+
SELECT
|
|
525
|
+
strftime('%Y-%m-%dT%H:%M:00Z', received_at) AS minute,
|
|
526
|
+
AVG(value) AS avg_util
|
|
527
|
+
FROM cpu_points
|
|
528
|
+
WHERE service_name = (SELECT service_name FROM top_service)
|
|
529
|
+
GROUP BY minute
|
|
530
|
+
ORDER BY minute ASC
|
|
531
|
+
)
|
|
532
|
+
SELECT
|
|
533
|
+
CASE
|
|
534
|
+
WHEN NOT EXISTS (SELECT 1 FROM cpu_points) THEN 'unknown'
|
|
535
|
+
WHEN (SELECT m FROM fleet_max) > 0.9 THEN 'critical'
|
|
536
|
+
WHEN (SELECT m FROM fleet_max) > 0.7 THEN 'warn'
|
|
537
|
+
ELSE 'ok'
|
|
538
|
+
END AS status,
|
|
539
|
+
(SELECT m FROM fleet_max) AS primary_value,
|
|
540
|
+
(SELECT AVG(avg_util) FROM base_window) AS baseline_value,
|
|
541
|
+
(SELECT json_object(
|
|
542
|
+
'window', '5m',
|
|
543
|
+
'baselineWindow', '25m',
|
|
544
|
+
'topServices', (
|
|
545
|
+
SELECT json_group_array(json_object(
|
|
546
|
+
'service', service_name,
|
|
547
|
+
'avgUtilization', avg_util
|
|
548
|
+
)) FROM top_now
|
|
549
|
+
),
|
|
550
|
+
'sparkline', (
|
|
551
|
+
SELECT json_group_array(json_object(
|
|
552
|
+
'minute', minute,
|
|
553
|
+
'avgUtilization', avg_util
|
|
554
|
+
)) FROM spark
|
|
555
|
+
)
|
|
556
|
+
)) AS payload
|
|
557
|
+
`,
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
export const TIER0_ANALYSES: AnalysisDefinition[] = [
|
|
561
|
+
overallErrorRate,
|
|
562
|
+
topErrorServices,
|
|
563
|
+
latencyP95Overall,
|
|
564
|
+
throughputSlope,
|
|
565
|
+
activeSessions,
|
|
566
|
+
logErrorRate,
|
|
567
|
+
serviceCpuUtilization,
|
|
568
|
+
];
|