@adonis-agora/telescope 0.26.1 → 0.27.0
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/CHANGELOG.md +23 -0
- package/dist/providers/telescope_provider.d.ts +10 -0
- package/dist/providers/telescope_provider.d.ts.map +1 -1
- package/dist/providers/telescope_provider.js +37 -1
- package/dist/providers/telescope_provider.js.map +1 -1
- package/dist/providers/telescope_ui_provider.d.ts.map +1 -1
- package/dist/providers/telescope_ui_provider.js +29 -0
- package/dist/providers/telescope_ui_provider.js.map +1 -1
- package/dist/src/ai/factory.d.ts.map +1 -1
- package/dist/src/ai/factory.js +26 -3
- package/dist/src/ai/factory.js.map +1 -1
- package/dist/src/ai/index.d.ts +1 -1
- package/dist/src/ai/index.js +1 -1
- package/dist/src/ai_metrics/agent_events.d.ts +106 -0
- package/dist/src/ai_metrics/agent_events.d.ts.map +1 -0
- package/dist/src/ai_metrics/agent_events.js +170 -0
- package/dist/src/ai_metrics/agent_events.js.map +1 -0
- package/dist/src/ai_metrics/agent_metrics.d.ts +103 -0
- package/dist/src/ai_metrics/agent_metrics.d.ts.map +1 -0
- package/dist/src/ai_metrics/agent_metrics.js +255 -0
- package/dist/src/ai_metrics/agent_metrics.js.map +1 -0
- package/dist/src/ai_metrics/ai_usage.d.ts +123 -0
- package/dist/src/ai_metrics/ai_usage.d.ts.map +1 -0
- package/dist/src/ai_metrics/ai_usage.js +207 -0
- package/dist/src/ai_metrics/ai_usage.js.map +1 -0
- package/dist/src/ai_metrics/index.d.ts +11 -0
- package/dist/src/ai_metrics/index.d.ts.map +1 -0
- package/dist/src/ai_metrics/index.js +11 -0
- package/dist/src/ai_metrics/index.js.map +1 -0
- package/dist/src/ai_metrics/otel_metrics_exporter.d.ts +60 -0
- package/dist/src/ai_metrics/otel_metrics_exporter.d.ts.map +1 -0
- package/dist/src/ai_metrics/otel_metrics_exporter.js +66 -0
- package/dist/src/ai_metrics/otel_metrics_exporter.js.map +1 -0
- package/dist/src/ai_metrics/subscribe.d.ts +17 -0
- package/dist/src/ai_metrics/subscribe.d.ts.map +1 -0
- package/dist/src/ai_metrics/subscribe.js +38 -0
- package/dist/src/ai_metrics/subscribe.js.map +1 -0
- package/dist/src/alerts/index.d.ts +1 -1
- package/dist/src/alerts/index.js +1 -1
- package/dist/src/client_errors/ingestor.d.ts.map +1 -1
- package/dist/src/client_errors/ingestor.js +3 -2
- package/dist/src/client_errors/ingestor.js.map +1 -1
- package/dist/src/define_config.d.ts +72 -0
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js +24 -4
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/diagnostics_watcher.d.ts.map +1 -1
- package/dist/src/diagnostics_watcher.js +12 -4
- package/dist/src/diagnostics_watcher.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/index.d.ts +1 -1
- package/dist/src/mcp/index.js +1 -1
- package/dist/src/metrics/metrics_service.d.ts +22 -0
- package/dist/src/metrics/metrics_service.d.ts.map +1 -1
- package/dist/src/metrics/metrics_service.js +49 -0
- package/dist/src/metrics/metrics_service.js.map +1 -1
- package/dist/src/profiling/index.d.ts +1 -1
- package/dist/src/profiling/index.js +1 -1
- package/dist/src/registry.d.ts +9 -0
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +6 -0
- package/dist/src/registry.js.map +1 -1
- package/dist/src/report_failure.d.ts +31 -0
- package/dist/src/report_failure.d.ts.map +1 -0
- package/dist/src/report_failure.js +70 -0
- package/dist/src/report_failure.js.map +1 -0
- package/dist/src/stores/lucid.d.ts +13 -2
- package/dist/src/stores/lucid.d.ts.map +1 -1
- package/dist/src/stores/lucid.js +85 -12
- package/dist/src/stores/lucid.js.map +1 -1
- package/dist/src/telescope_middleware.d.ts.map +1 -1
- package/dist/src/telescope_middleware.js +3 -2
- package/dist/src/telescope_middleware.js.map +1 -1
- package/dist/src/ui/api.d.ts +6 -0
- package/dist/src/ui/api.d.ts.map +1 -1
- package/dist/src/ui/api.js +23 -0
- package/dist/src/ui/api.js.map +1 -1
- package/dist/src/ui/index.d.ts +1 -1
- package/dist/src/ui/index.js +1 -1
- package/dist/src/watchers/index.d.ts +1 -1
- package/dist/src/watchers/index.js +1 -1
- package/dist/src/watchers/record.d.ts.map +1 -1
- package/dist/src/watchers/record.js +4 -2
- package/dist/src/watchers/record.js.map +1 -1
- package/grafana/agora-ai-dashboard.json +813 -0
- package/package.json +14 -2
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { Entry } from '../entry.js';
|
|
2
|
+
import { type RunStatus, type StepTiming } from './agent_events.js';
|
|
3
|
+
/** One row of a spend breakdown (by feature, model or actor). */
|
|
4
|
+
export interface AiSpendRow {
|
|
5
|
+
key: string;
|
|
6
|
+
costUsd: number;
|
|
7
|
+
calls: number;
|
|
8
|
+
/** Calls in this group that had no cost. */
|
|
9
|
+
unpricedCalls: number;
|
|
10
|
+
inputTokens: number;
|
|
11
|
+
outputTokens: number;
|
|
12
|
+
}
|
|
13
|
+
/** One time bucket of spend. */
|
|
14
|
+
export interface AiSpendBucket {
|
|
15
|
+
/** Bucket start, ISO. */
|
|
16
|
+
start: string;
|
|
17
|
+
costUsd: number;
|
|
18
|
+
platformUsd: number;
|
|
19
|
+
estimatedUsd: number;
|
|
20
|
+
calls: number;
|
|
21
|
+
}
|
|
22
|
+
/** The spend half of the AI screen. */
|
|
23
|
+
export interface AiSpend {
|
|
24
|
+
totalUsd: number;
|
|
25
|
+
/** Paid by the platform (`actorRef === '@platform'`). */
|
|
26
|
+
platformUsd: number;
|
|
27
|
+
/** Priced by an estimate rather than the provider's own figure. */
|
|
28
|
+
estimatedUsd: number;
|
|
29
|
+
calls: number;
|
|
30
|
+
unpricedCalls: number;
|
|
31
|
+
inputTokens: number;
|
|
32
|
+
outputTokens: number;
|
|
33
|
+
cacheReadTokens: number;
|
|
34
|
+
cacheWriteTokens: number;
|
|
35
|
+
audioSeconds: number;
|
|
36
|
+
byFeature: AiSpendRow[];
|
|
37
|
+
byModel: AiSpendRow[];
|
|
38
|
+
/** Top N payers. `@platform` is the platform itself. */
|
|
39
|
+
byActor: AiSpendRow[];
|
|
40
|
+
buckets: AiSpendBucket[];
|
|
41
|
+
}
|
|
42
|
+
/** One agent run, as the runs table shows it. */
|
|
43
|
+
export interface AiRunRow {
|
|
44
|
+
/** The Telescope entry the run's terminal event was recorded as. */
|
|
45
|
+
entryId: string;
|
|
46
|
+
/** The entry's trace — the link to the existing trace/waterfall view; `null` when none. */
|
|
47
|
+
traceId: string | null;
|
|
48
|
+
at: string;
|
|
49
|
+
status: RunStatus;
|
|
50
|
+
agent: string;
|
|
51
|
+
runId: string | null;
|
|
52
|
+
threadId: string | null;
|
|
53
|
+
modelId: string | null;
|
|
54
|
+
durationMs: number | null;
|
|
55
|
+
ttftMs: number | null;
|
|
56
|
+
queueMs: number | null;
|
|
57
|
+
modelMs: number | null;
|
|
58
|
+
toolsMs: number | null;
|
|
59
|
+
steps: number | null;
|
|
60
|
+
modelCalls: number | null;
|
|
61
|
+
toolCalls: number | null;
|
|
62
|
+
inputTokens: number | null;
|
|
63
|
+
outputTokens: number | null;
|
|
64
|
+
costUsd: number | null;
|
|
65
|
+
/** Failure slug on a failed run. */
|
|
66
|
+
code: string | null;
|
|
67
|
+
stepTimings: StepTiming[];
|
|
68
|
+
}
|
|
69
|
+
/** Calls with no cost, grouped. */
|
|
70
|
+
export interface AiUnpricedRow {
|
|
71
|
+
feature: string;
|
|
72
|
+
model: string;
|
|
73
|
+
provider: string;
|
|
74
|
+
calls: number;
|
|
75
|
+
inputTokens: number;
|
|
76
|
+
outputTokens: number;
|
|
77
|
+
audioSeconds: number;
|
|
78
|
+
characters: number;
|
|
79
|
+
lastAt: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* What the window held, so the screen can tell "nothing happened" from "this app's agent lib does
|
|
83
|
+
* not publish these events yet".
|
|
84
|
+
*/
|
|
85
|
+
export interface AiCoverage {
|
|
86
|
+
usageEvents: number;
|
|
87
|
+
runEvents: number;
|
|
88
|
+
/** Every agent event seen, of any kind (`run.started`, `tool-call`, …). */
|
|
89
|
+
agentEvents: number;
|
|
90
|
+
/** Agent events exist but none is `usage.recorded`: the agent lib predates the ledger event. */
|
|
91
|
+
legacyAgentLib: boolean;
|
|
92
|
+
/** Runs whose terminal event carried no timing breakdown (queue/model/tools). */
|
|
93
|
+
runsWithoutTimings: number;
|
|
94
|
+
}
|
|
95
|
+
export interface AiUsageSummary {
|
|
96
|
+
windowStart: string;
|
|
97
|
+
windowEnd: string;
|
|
98
|
+
spend: AiSpend;
|
|
99
|
+
/** Most recent first. */
|
|
100
|
+
runs: AiRunRow[];
|
|
101
|
+
slowest: AiRunRow[];
|
|
102
|
+
mostExpensive: AiRunRow[];
|
|
103
|
+
unpriced: AiUnpricedRow[];
|
|
104
|
+
coverage: AiCoverage;
|
|
105
|
+
}
|
|
106
|
+
export interface SummarizeAiUsageOptions {
|
|
107
|
+
windowStart: Date;
|
|
108
|
+
windowEnd: Date;
|
|
109
|
+
/** Spend time buckets. Default 24. */
|
|
110
|
+
buckets?: number;
|
|
111
|
+
/** Rows per breakdown and per runs table. Default 10 for breakdowns, 50 for runs. */
|
|
112
|
+
top?: number;
|
|
113
|
+
runsLimit?: number;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Summarize the agent entries of a window into the AI screen: spend (total, platform and estimated
|
|
117
|
+
* shares, by feature / model / actor, over time), runs (recent, slowest, most expensive, each with
|
|
118
|
+
* its step breakdown) and the unpriced calls, from the `diagnostic` entries the generic watcher
|
|
119
|
+
* records for `agora:agent:*` (see {@link agentEventOfEntry}). Entries outside the window are
|
|
120
|
+
* ignored. Pure.
|
|
121
|
+
*/
|
|
122
|
+
export declare function summarizeAiUsage(entries: readonly Entry[], options: SummarizeAiUsageOptions): AiUsageSummary;
|
|
123
|
+
//# sourceMappingURL=ai_usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai_usage.d.ts","sourceRoot":"","sources":["../../../src/ai_metrics/ai_usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { agentEventOfEntry, readAgentEvent, } from './agent_events.js';
|
|
2
|
+
function emptyRow(key) {
|
|
3
|
+
return { key, costUsd: 0, calls: 0, unpricedCalls: 0, inputTokens: 0, outputTokens: 0 };
|
|
4
|
+
}
|
|
5
|
+
function addTo(map, key, u) {
|
|
6
|
+
let row = map.get(key);
|
|
7
|
+
if (row === undefined) {
|
|
8
|
+
row = emptyRow(key);
|
|
9
|
+
map.set(key, row);
|
|
10
|
+
}
|
|
11
|
+
row.costUsd += u.costUsd ?? 0;
|
|
12
|
+
row.calls += u.requests;
|
|
13
|
+
if (u.costUsd === undefined)
|
|
14
|
+
row.unpricedCalls += u.requests;
|
|
15
|
+
row.inputTokens += u.inputTokens;
|
|
16
|
+
row.outputTokens += u.outputTokens;
|
|
17
|
+
}
|
|
18
|
+
function ranked(map, top) {
|
|
19
|
+
return [...map.values()]
|
|
20
|
+
.sort((a, b) => b.costUsd - a.costUsd || b.calls - a.calls || a.key.localeCompare(b.key))
|
|
21
|
+
.slice(0, top)
|
|
22
|
+
.map((r) => ({ ...r, costUsd: round(r.costUsd) }));
|
|
23
|
+
}
|
|
24
|
+
function round(value) {
|
|
25
|
+
return Math.round(value * 1e8) / 1e8;
|
|
26
|
+
}
|
|
27
|
+
function toRunRow(entry, r) {
|
|
28
|
+
return {
|
|
29
|
+
entryId: entry.id,
|
|
30
|
+
traceId: entry.traceId,
|
|
31
|
+
at: new Date(entry.createdAt).toISOString(),
|
|
32
|
+
status: r.status,
|
|
33
|
+
agent: r.agent,
|
|
34
|
+
runId: r.runId ?? null,
|
|
35
|
+
threadId: r.threadId ?? null,
|
|
36
|
+
modelId: r.modelId ?? null,
|
|
37
|
+
durationMs: r.durationMs ?? null,
|
|
38
|
+
ttftMs: r.ttftMs ?? null,
|
|
39
|
+
queueMs: r.queueMs ?? null,
|
|
40
|
+
modelMs: r.modelMs ?? null,
|
|
41
|
+
toolsMs: r.toolsMs ?? null,
|
|
42
|
+
steps: r.steps ?? (r.stepTimings.length > 0 ? r.stepTimings.length : null),
|
|
43
|
+
modelCalls: r.modelCalls ?? null,
|
|
44
|
+
toolCalls: r.toolCalls ?? null,
|
|
45
|
+
inputTokens: r.inputTokens ?? null,
|
|
46
|
+
outputTokens: r.outputTokens ?? null,
|
|
47
|
+
costUsd: r.costUsd ?? null,
|
|
48
|
+
code: r.code ?? null,
|
|
49
|
+
stepTimings: r.stepTimings,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Summarize the agent entries of a window into the AI screen: spend (total, platform and estimated
|
|
54
|
+
* shares, by feature / model / actor, over time), runs (recent, slowest, most expensive, each with
|
|
55
|
+
* its step breakdown) and the unpriced calls, from the `diagnostic` entries the generic watcher
|
|
56
|
+
* records for `agora:agent:*` (see {@link agentEventOfEntry}). Entries outside the window are
|
|
57
|
+
* ignored. Pure.
|
|
58
|
+
*/
|
|
59
|
+
export function summarizeAiUsage(entries, options) {
|
|
60
|
+
const start = options.windowStart.getTime();
|
|
61
|
+
const end = options.windowEnd.getTime();
|
|
62
|
+
const bucketCount = Math.max(1, Math.min(500, Math.floor(options.buckets ?? 24)));
|
|
63
|
+
const top = Math.max(1, Math.floor(options.top ?? 10));
|
|
64
|
+
const runsLimit = Math.max(1, Math.floor(options.runsLimit ?? 50));
|
|
65
|
+
const bucketMs = Math.max(1, (end - start) / bucketCount);
|
|
66
|
+
const buckets = Array.from({ length: bucketCount }, (_, i) => ({
|
|
67
|
+
start: new Date(start + i * bucketMs).toISOString(),
|
|
68
|
+
costUsd: 0,
|
|
69
|
+
platformUsd: 0,
|
|
70
|
+
estimatedUsd: 0,
|
|
71
|
+
calls: 0,
|
|
72
|
+
}));
|
|
73
|
+
const spend = {
|
|
74
|
+
totalUsd: 0,
|
|
75
|
+
platformUsd: 0,
|
|
76
|
+
estimatedUsd: 0,
|
|
77
|
+
calls: 0,
|
|
78
|
+
unpricedCalls: 0,
|
|
79
|
+
inputTokens: 0,
|
|
80
|
+
outputTokens: 0,
|
|
81
|
+
cacheReadTokens: 0,
|
|
82
|
+
cacheWriteTokens: 0,
|
|
83
|
+
audioSeconds: 0,
|
|
84
|
+
byFeature: [],
|
|
85
|
+
byModel: [],
|
|
86
|
+
byActor: [],
|
|
87
|
+
buckets,
|
|
88
|
+
};
|
|
89
|
+
const byFeature = new Map();
|
|
90
|
+
const byModel = new Map();
|
|
91
|
+
const byActor = new Map();
|
|
92
|
+
const unpriced = new Map();
|
|
93
|
+
const runs = [];
|
|
94
|
+
const coverage = {
|
|
95
|
+
usageEvents: 0,
|
|
96
|
+
runEvents: 0,
|
|
97
|
+
agentEvents: 0,
|
|
98
|
+
legacyAgentLib: false,
|
|
99
|
+
runsWithoutTimings: 0,
|
|
100
|
+
};
|
|
101
|
+
for (const entry of entries) {
|
|
102
|
+
const at = new Date(entry.createdAt).getTime();
|
|
103
|
+
if (at < start || at > end)
|
|
104
|
+
continue;
|
|
105
|
+
const event = agentEventOfEntry(entry);
|
|
106
|
+
if (event === null)
|
|
107
|
+
continue;
|
|
108
|
+
coverage.agentEvents += 1;
|
|
109
|
+
const observation = readAgentEvent(event.event, event.payload);
|
|
110
|
+
if (observation === null)
|
|
111
|
+
continue;
|
|
112
|
+
if (observation.kind === 'run') {
|
|
113
|
+
coverage.runEvents += 1;
|
|
114
|
+
if (observation.queueMs === undefined &&
|
|
115
|
+
observation.modelMs === undefined &&
|
|
116
|
+
observation.toolsMs === undefined) {
|
|
117
|
+
coverage.runsWithoutTimings += 1;
|
|
118
|
+
}
|
|
119
|
+
runs.push(toRunRow(entry, observation));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const u = observation;
|
|
123
|
+
coverage.usageEvents += 1;
|
|
124
|
+
const cost = u.costUsd ?? 0;
|
|
125
|
+
spend.totalUsd += cost;
|
|
126
|
+
if (u.platform)
|
|
127
|
+
spend.platformUsd += cost;
|
|
128
|
+
if (u.costSource === 'estimate')
|
|
129
|
+
spend.estimatedUsd += cost;
|
|
130
|
+
spend.calls += u.requests;
|
|
131
|
+
spend.inputTokens += u.inputTokens;
|
|
132
|
+
spend.outputTokens += u.outputTokens;
|
|
133
|
+
spend.cacheReadTokens += u.cacheReadTokens;
|
|
134
|
+
spend.cacheWriteTokens += u.cacheWriteTokens;
|
|
135
|
+
spend.audioSeconds += u.audioSeconds;
|
|
136
|
+
addTo(byFeature, u.feature, u);
|
|
137
|
+
addTo(byModel, u.model, u);
|
|
138
|
+
addTo(byActor, u.actorRef, u);
|
|
139
|
+
const bucket = buckets[Math.min(bucketCount - 1, Math.floor((at - start) / bucketMs))];
|
|
140
|
+
if (bucket !== undefined) {
|
|
141
|
+
bucket.costUsd += cost;
|
|
142
|
+
if (u.platform)
|
|
143
|
+
bucket.platformUsd += cost;
|
|
144
|
+
if (u.costSource === 'estimate')
|
|
145
|
+
bucket.estimatedUsd += cost;
|
|
146
|
+
bucket.calls += u.requests;
|
|
147
|
+
}
|
|
148
|
+
if (u.costUsd === undefined) {
|
|
149
|
+
spend.unpricedCalls += u.requests;
|
|
150
|
+
const key = `${u.feature}\u0000${u.model}\u0000${u.provider}`;
|
|
151
|
+
let row = unpriced.get(key);
|
|
152
|
+
if (row === undefined) {
|
|
153
|
+
row = {
|
|
154
|
+
feature: u.feature,
|
|
155
|
+
model: u.model,
|
|
156
|
+
provider: u.provider,
|
|
157
|
+
calls: 0,
|
|
158
|
+
inputTokens: 0,
|
|
159
|
+
outputTokens: 0,
|
|
160
|
+
audioSeconds: 0,
|
|
161
|
+
characters: 0,
|
|
162
|
+
lastAt: new Date(at).toISOString(),
|
|
163
|
+
};
|
|
164
|
+
unpriced.set(key, row);
|
|
165
|
+
}
|
|
166
|
+
row.calls += u.requests;
|
|
167
|
+
row.inputTokens += u.inputTokens;
|
|
168
|
+
row.outputTokens += u.outputTokens;
|
|
169
|
+
row.audioSeconds += u.audioSeconds;
|
|
170
|
+
row.characters += u.characters;
|
|
171
|
+
if (new Date(at).toISOString() > row.lastAt)
|
|
172
|
+
row.lastAt = new Date(at).toISOString();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
coverage.legacyAgentLib = coverage.agentEvents > 0 && coverage.usageEvents === 0;
|
|
176
|
+
spend.totalUsd = round(spend.totalUsd);
|
|
177
|
+
spend.platformUsd = round(spend.platformUsd);
|
|
178
|
+
spend.estimatedUsd = round(spend.estimatedUsd);
|
|
179
|
+
spend.byFeature = ranked(byFeature, top);
|
|
180
|
+
spend.byModel = ranked(byModel, top);
|
|
181
|
+
spend.byActor = ranked(byActor, top);
|
|
182
|
+
for (const b of buckets) {
|
|
183
|
+
b.costUsd = round(b.costUsd);
|
|
184
|
+
b.platformUsd = round(b.platformUsd);
|
|
185
|
+
b.estimatedUsd = round(b.estimatedUsd);
|
|
186
|
+
}
|
|
187
|
+
runs.sort((a, b) => b.at.localeCompare(a.at));
|
|
188
|
+
const slowest = runs
|
|
189
|
+
.filter((r) => r.durationMs !== null)
|
|
190
|
+
.sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0))
|
|
191
|
+
.slice(0, 5);
|
|
192
|
+
const mostExpensive = runs
|
|
193
|
+
.filter((r) => r.costUsd !== null && r.costUsd > 0)
|
|
194
|
+
.sort((a, b) => (b.costUsd ?? 0) - (a.costUsd ?? 0))
|
|
195
|
+
.slice(0, 5);
|
|
196
|
+
return {
|
|
197
|
+
windowStart: options.windowStart.toISOString(),
|
|
198
|
+
windowEnd: options.windowEnd.toISOString(),
|
|
199
|
+
spend,
|
|
200
|
+
runs: runs.slice(0, runsLimit),
|
|
201
|
+
slowest,
|
|
202
|
+
mostExpensive,
|
|
203
|
+
unpriced: [...unpriced.values()].sort((a, b) => b.calls - a.calls),
|
|
204
|
+
coverage,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=ai_usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai_usage.js","sourceRoot":"","sources":["../../../src/ai_metrics/ai_usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI usage and agent run observability: pure readers for the `agora:agent:*` events, the metric
|
|
3
|
+
* table both exporters (Prometheus scrape, OTLP) read, the in-process Prometheus registry, and the
|
|
4
|
+
* AI screen's summarizer. The OTLP exporter (`otel_metrics_exporter.ts`) is intentionally NOT
|
|
5
|
+
* re-exported: it is loaded lazily by the provider so importing this never pulls in OTel.
|
|
6
|
+
*/
|
|
7
|
+
export { AGENT_CHANNEL_PREFIX, AGENT_METRIC_EVENTS, type AgentMetricEvent, type AgentObservation, agentEventOfEntry, type CostSource, PLATFORM_ACTOR_REF, type RunObservation, type RunStatus, readAgentEvent, readRun, readUsage, type StepTiming, type ToolTiming, type UsageObservation, } from './agent_events.js';
|
|
8
|
+
export { AGENT_METRIC_BUCKETS_MS, AGENT_METRICS, type AgentMetricKey, AgentMetricsRegistry, type AgentMetricsRegistryOptions, agentMetricPoints, type MetricAttributes, type MetricPoint, } from './agent_metrics.js';
|
|
9
|
+
export { type AiCoverage, type AiRunRow, type AiSpend, type AiSpendBucket, type AiSpendRow, type AiUnpricedRow, type AiUsageSummary, type SummarizeAiUsageOptions, summarizeAiUsage, } from './ai_usage.js';
|
|
10
|
+
export { type AgentObservationListener, subscribeAgentObservations } from './subscribe.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ai_metrics/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,iBAAiB,EACjB,KAAK,UAAU,EACf,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,cAAc,EACd,OAAO,EACP,SAAS,EACT,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,KAAK,cAAc,EACnB,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI usage and agent run observability: pure readers for the `agora:agent:*` events, the metric
|
|
3
|
+
* table both exporters (Prometheus scrape, OTLP) read, the in-process Prometheus registry, and the
|
|
4
|
+
* AI screen's summarizer. The OTLP exporter (`otel_metrics_exporter.ts`) is intentionally NOT
|
|
5
|
+
* re-exported: it is loaded lazily by the provider so importing this never pulls in OTel.
|
|
6
|
+
*/
|
|
7
|
+
export { AGENT_CHANNEL_PREFIX, AGENT_METRIC_EVENTS, agentEventOfEntry, PLATFORM_ACTOR_REF, readAgentEvent, readRun, readUsage, } from './agent_events.js';
|
|
8
|
+
export { AGENT_METRIC_BUCKETS_MS, AGENT_METRICS, AgentMetricsRegistry, agentMetricPoints, } from './agent_metrics.js';
|
|
9
|
+
export { summarizeAiUsage, } from './ai_usage.js';
|
|
10
|
+
export { subscribeAgentObservations } from './subscribe.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ai_metrics/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EAGnB,iBAAiB,EAEjB,kBAAkB,EAGlB,cAAc,EACd,OAAO,EACP,SAAS,GAIV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,uBAAuB,EACvB,aAAa,EAEb,oBAAoB,EAEpB,iBAAiB,GAGlB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EASL,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAiC,0BAA0B,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Counter, Histogram } from '@opentelemetry/api';
|
|
2
|
+
import type { ResolvedOtelMetricsConfig } from '../define_config.js';
|
|
3
|
+
import type { AgentObservation } from './agent_events.js';
|
|
4
|
+
/**
|
|
5
|
+
* The OTLP METRICS signal: the AI-usage and agent-run instruments of {@link AGENT_METRICS}, pushed
|
|
6
|
+
* over OTLP/HTTP by a periodic reader.
|
|
7
|
+
*
|
|
8
|
+
* Loaded ONLY through the dynamic `import()` in `telescope_provider.ts`, and only when
|
|
9
|
+
* `otel.metrics.enabled` is `true`; the `@opentelemetry/*` metrics packages are imported lazily
|
|
10
|
+
* inside {@link loadOtelMetricsSdk}, so a host that never opts in never needs them installed.
|
|
11
|
+
*
|
|
12
|
+
* Like the traces/logs bridge it owns a PRIVATE `MeterProvider` and never calls
|
|
13
|
+
* `metrics.setGlobalMeterProvider`, so it cannot clash with a host's own OTel setup.
|
|
14
|
+
*
|
|
15
|
+
* Fed from the `agora:agent:*` diagnostics channels directly (see `subscribe.ts`), not from stored
|
|
16
|
+
* entries: sampling, retention and the overload guard never change a count.
|
|
17
|
+
*
|
|
18
|
+
* Instruments are created with an EMPTY unit on purpose (the unit is in the name): Prometheus'
|
|
19
|
+
* OTLP translation appends a unit suffix (`ms` → `_milliseconds`), which would make a metric read
|
|
20
|
+
* `agora_agent_run_duration_ms_milliseconds` through a Collector but `agora_agent_run_duration_ms`
|
|
21
|
+
* from the scrape endpoint. With no unit both paths expose the same series, so one Grafana
|
|
22
|
+
* dashboard serves both.
|
|
23
|
+
*/
|
|
24
|
+
/** The meter-provider surface this exporter uses. */
|
|
25
|
+
export interface MeterProviderLike {
|
|
26
|
+
getMeter(name: string): {
|
|
27
|
+
createCounter(name: string, options?: {
|
|
28
|
+
description?: string;
|
|
29
|
+
unit?: string;
|
|
30
|
+
}): Counter;
|
|
31
|
+
createHistogram(name: string, options?: {
|
|
32
|
+
description?: string;
|
|
33
|
+
unit?: string;
|
|
34
|
+
advice?: {
|
|
35
|
+
explicitBucketBoundaries?: number[];
|
|
36
|
+
};
|
|
37
|
+
}): Histogram;
|
|
38
|
+
};
|
|
39
|
+
forceFlush(): Promise<void>;
|
|
40
|
+
shutdown(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
/** Builds the provider from the resolved config. Injectable for tests. */
|
|
43
|
+
export type MeterProviderFactory = (config: ResolvedOtelMetricsConfig) => Promise<MeterProviderLike>;
|
|
44
|
+
/** Import the OTel metrics SDK and build a provider exporting to `config.url`. */
|
|
45
|
+
export declare const loadOtelMetricsSdk: MeterProviderFactory;
|
|
46
|
+
/** A running OTLP metrics export; stop it with {@link OtelMetricsExporter.shutdown}. */
|
|
47
|
+
export interface OtelMetricsExporter {
|
|
48
|
+
/** Record one observation (exposed for tests and for hosts that read the events themselves). */
|
|
49
|
+
observe(observation: AgentObservation): void;
|
|
50
|
+
/** Push whatever is pending now. */
|
|
51
|
+
flush(): Promise<void>;
|
|
52
|
+
/** Unsubscribe, flush the tail and shut the provider down. */
|
|
53
|
+
shutdown(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build the provider and its instruments, then subscribe to the agent channels. Rejects when the
|
|
57
|
+
* OTel packages cannot be loaded; the provider logs that and leaves metrics export off.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createOtelMetricsExporter(config: ResolvedOtelMetricsConfig, factory?: MeterProviderFactory): Promise<OtelMetricsExporter>;
|
|
60
|
+
//# sourceMappingURL=otel_metrics_exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel_metrics_exporter.d.ts","sourceRoot":"","sources":["../../../src/ai_metrics/otel_metrics_exporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAS1D;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,qDAAqD;AACrD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG;QACtB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;YAAE,WAAW,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC;QACxF,eAAe,CACb,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;YACR,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,MAAM,CAAC,EAAE;gBAAE,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAA;aAAE,CAAC;SAClD,GACA,SAAS,CAAC;KACd,CAAC;IACF,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB,GAAG,CACjC,MAAM,EAAE,yBAAyB,KAC9B,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEhC,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,EAAE,oBAoBhC,CAAC;AAEF,wFAAwF;AACxF,MAAM,WAAW,mBAAmB;IAClC,gGAAgG;IAChG,OAAO,CAAC,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC7C,oCAAoC;IACpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,yBAAyB,EACjC,OAAO,GAAE,oBAAyC,GACjD,OAAO,CAAC,mBAAmB,CAAC,CAwC9B"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { AGENT_METRIC_BUCKETS_MS, AGENT_METRICS, agentMetricPoints, } from './agent_metrics.js';
|
|
2
|
+
import { subscribeAgentObservations } from './subscribe.js';
|
|
3
|
+
/** Import the OTel metrics SDK and build a provider exporting to `config.url`. */
|
|
4
|
+
export const loadOtelMetricsSdk = async (config) => {
|
|
5
|
+
const [sdk, exporterPkg, resources] = await Promise.all([
|
|
6
|
+
import('@opentelemetry/sdk-metrics'),
|
|
7
|
+
import('@opentelemetry/exporter-metrics-otlp-http'),
|
|
8
|
+
import('@opentelemetry/resources'),
|
|
9
|
+
]);
|
|
10
|
+
const exporter = new exporterPkg.OTLPMetricExporter({
|
|
11
|
+
url: config.url,
|
|
12
|
+
headers: config.headers,
|
|
13
|
+
timeoutMillis: config.timeoutMs,
|
|
14
|
+
});
|
|
15
|
+
const reader = new sdk.PeriodicExportingMetricReader({
|
|
16
|
+
exporter,
|
|
17
|
+
exportIntervalMillis: config.exportIntervalMs,
|
|
18
|
+
exportTimeoutMillis: Math.min(config.timeoutMs, config.exportIntervalMs),
|
|
19
|
+
});
|
|
20
|
+
return new sdk.MeterProvider({
|
|
21
|
+
resource: resources.resourceFromAttributes({ 'service.name': config.serviceName }),
|
|
22
|
+
readers: [reader],
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Build the provider and its instruments, then subscribe to the agent channels. Rejects when the
|
|
27
|
+
* OTel packages cannot be loaded; the provider logs that and leaves metrics export off.
|
|
28
|
+
*/
|
|
29
|
+
export async function createOtelMetricsExporter(config, factory = loadOtelMetricsSdk) {
|
|
30
|
+
const provider = await factory(config);
|
|
31
|
+
const meter = provider.getMeter('@adonis-agora/telescope');
|
|
32
|
+
const instruments = new Map();
|
|
33
|
+
for (const key of Object.keys(AGENT_METRICS)) {
|
|
34
|
+
const def = AGENT_METRICS[key];
|
|
35
|
+
instruments.set(key, def.type === 'counter'
|
|
36
|
+
? meter.createCounter(def.name, { description: def.help, unit: '' })
|
|
37
|
+
: meter.createHistogram(def.name, {
|
|
38
|
+
description: def.help,
|
|
39
|
+
unit: '',
|
|
40
|
+
advice: { explicitBucketBoundaries: [...AGENT_METRIC_BUCKETS_MS] },
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
const observe = (observation) => {
|
|
44
|
+
for (const point of agentMetricPoints(observation)) {
|
|
45
|
+
const instrument = instruments.get(point.metric);
|
|
46
|
+
if (instrument === undefined)
|
|
47
|
+
continue;
|
|
48
|
+
if (AGENT_METRICS[point.metric].type === 'counter') {
|
|
49
|
+
instrument.add(point.value, point.attributes);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
instrument.record(point.value, point.attributes);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const unsubscribe = subscribeAgentObservations(observe);
|
|
57
|
+
return {
|
|
58
|
+
observe,
|
|
59
|
+
flush: () => provider.forceFlush(),
|
|
60
|
+
async shutdown() {
|
|
61
|
+
unsubscribe();
|
|
62
|
+
await provider.shutdown().catch(() => undefined);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=otel_metrics_exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel_metrics_exporter.js","sourceRoot":"","sources":["../../../src/ai_metrics/otel_metrics_exporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type AgentObservation } from './agent_events.js';
|
|
2
|
+
/** A consumer of agent observations. A throw is swallowed — it never reaches the agent loop. */
|
|
3
|
+
export type AgentObservationListener = (observation: AgentObservation) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Subscribe to the agent's `usage.recorded` and terminal run channels DIRECTLY on
|
|
6
|
+
* `node:diagnostics_channel` and hand each event, parsed, to `listener`.
|
|
7
|
+
*
|
|
8
|
+
* Direct, and not through recorded Telescope entries, on purpose: entries are sampled, pruned and
|
|
9
|
+
* may not be recorded at all (the `diagnostics` watcher is off, or the event is excluded). A metric must count every event exactly
|
|
10
|
+
* once, so it reads the source. Subscribing is also what makes `emit()` publish at all
|
|
11
|
+
* (`channel.hasSubscribers`), so this works with the
|
|
12
|
+
* `diagnostics` watcher off.
|
|
13
|
+
*
|
|
14
|
+
* Returns the unsubscribe function.
|
|
15
|
+
*/
|
|
16
|
+
export declare function subscribeAgentObservations(listener: AgentObservationListener): () => void;
|
|
17
|
+
//# sourceMappingURL=subscribe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../../src/ai_metrics/subscribe.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AAE3B,gGAAgG;AAChG,MAAM,MAAM,wBAAwB,GAAG,CAAC,WAAW,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAE/E;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,IAAI,CAmBzF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import diagnostics_channel from 'node:diagnostics_channel';
|
|
2
|
+
import { AGENT_CHANNEL_PREFIX, AGENT_METRIC_EVENTS, readAgentEvent, } from './agent_events.js';
|
|
3
|
+
/**
|
|
4
|
+
* Subscribe to the agent's `usage.recorded` and terminal run channels DIRECTLY on
|
|
5
|
+
* `node:diagnostics_channel` and hand each event, parsed, to `listener`.
|
|
6
|
+
*
|
|
7
|
+
* Direct, and not through recorded Telescope entries, on purpose: entries are sampled, pruned and
|
|
8
|
+
* may not be recorded at all (the `diagnostics` watcher is off, or the event is excluded). A metric must count every event exactly
|
|
9
|
+
* once, so it reads the source. Subscribing is also what makes `emit()` publish at all
|
|
10
|
+
* (`channel.hasSubscribers`), so this works with the
|
|
11
|
+
* `diagnostics` watcher off.
|
|
12
|
+
*
|
|
13
|
+
* Returns the unsubscribe function.
|
|
14
|
+
*/
|
|
15
|
+
export function subscribeAgentObservations(listener) {
|
|
16
|
+
const handlers = [];
|
|
17
|
+
for (const event of AGENT_METRIC_EVENTS) {
|
|
18
|
+
const name = `${AGENT_CHANNEL_PREFIX}${event}`;
|
|
19
|
+
const handler = (message) => {
|
|
20
|
+
try {
|
|
21
|
+
const envelope = message;
|
|
22
|
+
const observation = readAgentEvent(event, envelope?.payload);
|
|
23
|
+
if (observation !== null)
|
|
24
|
+
listener(observation);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Observability must never break the agent run that published the event.
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
diagnostics_channel.subscribe(name, handler);
|
|
31
|
+
handlers.push([name, handler]);
|
|
32
|
+
}
|
|
33
|
+
return () => {
|
|
34
|
+
for (const [name, handler] of handlers)
|
|
35
|
+
diagnostics_channel.unsubscribe(name, handler);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=subscribe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../../src/ai_metrics/subscribe.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EAEnB,cAAc,GACf,MAAM,mBAAmB,CAAC;AAK3B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,0BAA0B,CAAC,QAAkC;IAC3E,MAAM,QAAQ,GAA2C,EAAE,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,mBAAmB,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,GAAG,oBAAoB,GAAG,KAAK,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,CAAC,OAAgB,EAAQ,EAAE;YACzC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,OAAwD,CAAC;gBAC1E,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC7D,IAAI,WAAW,KAAK,IAAI;oBAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;YAClD,CAAC;YAAC,MAAM,CAAC;gBACP,yEAAyE;YAC3E,CAAC;QACH,CAAC,CAAC;QACF,mBAAmB,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,GAAG,EAAE;QACV,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,QAAQ;YAAE,mBAAmB,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzF,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.27.0";
|
|
3
3
|
export type { AlertChannel, ChannelFetch, ConsoleSink } from './alert_channel.js';
|
|
4
4
|
export { consoleChannel, customChannel, slackChannel, webhookChannel, } from './alert_channel.js';
|
|
5
5
|
export type { AlertDiagnosis, AlertGeoLocation, AlertMetric, AlertPayload, AlertRule, ExceptionAlertContext, GeoLookup, ResolvedAlerts, } from './alert_rule.js';
|
package/dist/src/alerts/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Keep in sync with this package's `version` in package.json. */
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.27.0';
|
|
3
3
|
// — channels —
|
|
4
4
|
export { consoleChannel, customChannel, slackChannel, webhookChannel, } from './alert_channel.js';
|
|
5
5
|
// — alerter (exception source → tracker → channels) —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingestor.d.ts","sourceRoot":"","sources":["../../../src/client_errors/ingestor.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ingestor.d.ts","sourceRoot":"","sources":["../../../src/client_errors/ingestor.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EACL,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,IAAI,IAAI,OAAO,CAAC;IAChB,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,kFAAkF;IAClF,EAAE,IAAI,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAAC;IAC1C,6DAA6D;IAC7D,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CAC9B;AAED,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AAED,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,0BAA0B,CAAC;IACnC;;;;OAIG;IACH,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAAC;IAC7D,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,cAAc,GACpB,CAAC,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAQtD;AAOD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAGjE;AAED;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuD;IAC9E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,6EAA6E;IAC7E,OAAO,CAAC,eAAe,CAAS;IAEhC,YAAY,IAAI,EAAE,uBAAuB,EAQxC;IAEK,MAAM,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CA4E1D;IAED;;;;OAIG;YACW,YAAY;IAmB1B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAQpB,2EAA2E;IAC3E,OAAO,CAAC,QAAQ;CAIjB"}
|
|
@@ -2,6 +2,7 @@ import { currentUserRef } from '../context_accessor.js';
|
|
|
2
2
|
import { EntryType } from '../entry.js';
|
|
3
3
|
import { exceptionFamilyHash } from '../exception_family_hash.js';
|
|
4
4
|
import { getTelescopeRuntime } from '../registry.js';
|
|
5
|
+
import { failureMessage, reportFailure } from '../report_failure.js';
|
|
5
6
|
import { ClientErrorRateLimiter } from './rate_limiter.js';
|
|
6
7
|
import { userIdentityTag, validateClientErrorBody, } from './validation.js';
|
|
7
8
|
/**
|
|
@@ -20,8 +21,8 @@ export function storeRecorder(store) {
|
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
23
|
function reportError(err) {
|
|
23
|
-
const
|
|
24
|
-
|
|
24
|
+
const line = `telescope client-errors: failed to record entry: ${failureMessage(err)}`;
|
|
25
|
+
reportFailure(line, line);
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
27
28
|
* The user to attribute a browser-reported error to.
|