Skip to content

Commit 504d1ff

Browse files
Add a status label to metrics so that they can be filtered by success state (#491)
1 parent f844cd5 commit 504d1ff

File tree

4 files changed

+84
-8
lines changed

4 files changed

+84
-8
lines changed

js/ai/src/telemetry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ type SharedDimensions = {
138138
temperature?: number;
139139
topK?: number;
140140
topP?: number;
141+
status?: string;
141142
source?: string;
142143
sourceVersion?: string;
143144
};
@@ -340,6 +341,7 @@ function doRecordGenerateActionMetrics(
340341
topP: dimensions.topP,
341342
source: dimensions.source,
342343
sourceVersion: dimensions.sourceVersion,
344+
status: dimensions.err ? 'failure' : 'success',
343345
};
344346

345347
generateActionCounter.add(1, {

js/core/src/telemetry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export function writeActionSuccess(actionName: string, latencyMs: number) {
4747
name: actionName,
4848
flowName: traceMetadataAls?.getStore()?.flowName,
4949
path: spanMetadataAls?.getStore()?.path,
50+
status: 'success',
5051
source: 'ts',
5152
sourceVersion: GENKIT_VERSION,
5253
};
@@ -65,6 +66,7 @@ export function writeActionFailure(
6566
path: spanMetadataAls?.getStore()?.path,
6667
source: 'ts',
6768
sourceVersion: GENKIT_VERSION,
69+
status: 'failure',
6870
error: err?.name,
6971
};
7072
actionCounter.add(1, dimensions);

js/flow/src/telemetry.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export function recordError(err: any) {
7171
export function writeFlowSuccess(flowName: string, latencyMs: number) {
7272
const dimensions = {
7373
name: flowName,
74+
status: 'success',
7475
source: 'ts',
7576
sourceVersion: GENKIT_VERSION,
7677
};
@@ -81,6 +82,7 @@ export function writeFlowSuccess(flowName: string, latencyMs: number) {
8182
if (paths) {
8283
const pathDimensions = {
8384
flowName: flowName,
85+
status: 'success',
8486
source: 'ts',
8587
sourceVersion: GENKIT_VERSION,
8688
};
@@ -96,7 +98,6 @@ export function writeFlowSuccess(flowName: string, latencyMs: number) {
9698
relevantPaths.forEach((p) => {
9799
pathCounter.add(1, {
98100
...pathDimensions,
99-
success: 'success',
100101
path: p.path,
101102
});
102103

@@ -115,6 +116,7 @@ export function writeFlowFailure(
115116
) {
116117
const dimensions = {
117118
name: flowName,
119+
status: 'failure',
118120
source: 'ts',
119121
sourceVersion: GENKIT_VERSION,
120122
error: err.name,
@@ -144,19 +146,27 @@ export function writeFlowFailure(
144146
relevantPaths.forEach((p) => {
145147
pathCounter.add(1, {
146148
...pathDimensions,
147-
success: 'success',
149+
status: 'success',
148150
path: p.path,
149151
});
150152

151153
pathLatencies.record(p.latency, {
152154
...pathDimensions,
155+
status: 'success',
153156
path: p.path,
154157
});
155158
});
156159

157160
pathCounter.add(1, {
158161
...pathDimensions,
159-
success: 'failure',
162+
status: 'failure',
163+
error: err.name,
164+
path: failPath,
165+
});
166+
167+
pathLatencies.record(latencyMs, {
168+
...pathDimensions,
169+
status: 'failure',
160170
error: err.name,
161171
path: failPath,
162172
});

js/plugins/google-cloud/tests/metrics_test.ts

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,12 @@ describe('GoogleCloudMetrics', () => {
8080
assert.equal(requestCounter.value, 2);
8181
assert.equal(requestCounter.attributes.name, 'testFlow');
8282
assert.equal(requestCounter.attributes.source, 'ts');
83+
assert.equal(requestCounter.attributes.status, 'success');
8384
assert.ok(requestCounter.attributes.sourceVersion);
8485
assert.equal(latencyHistogram.value.count, 2);
8586
assert.equal(latencyHistogram.attributes.name, 'testFlow');
8687
assert.equal(latencyHistogram.attributes.source, 'ts');
88+
assert.equal(latencyHistogram.attributes.status, 'success');
8789
assert.ok(latencyHistogram.attributes.sourceVersion);
8890
});
8991

@@ -102,6 +104,7 @@ describe('GoogleCloudMetrics', () => {
102104
assert.equal(requestCounter.attributes.name, 'testFlow');
103105
assert.equal(requestCounter.attributes.source, 'ts');
104106
assert.equal(requestCounter.attributes.error, 'TypeError');
107+
assert.equal(requestCounter.attributes.status, 'failure');
105108
});
106109

107110
it('writes action metrics', async () => {
@@ -122,10 +125,12 @@ describe('GoogleCloudMetrics', () => {
122125
assert.equal(requestCounter.value, 6);
123126
assert.equal(requestCounter.attributes.name, 'testAction');
124127
assert.equal(requestCounter.attributes.source, 'ts');
128+
assert.equal(requestCounter.attributes.status, 'success');
125129
assert.ok(requestCounter.attributes.sourceVersion);
126130
assert.equal(latencyHistogram.value.count, 6);
127131
assert.equal(latencyHistogram.attributes.name, 'testAction');
128132
assert.equal(latencyHistogram.attributes.source, 'ts');
133+
assert.equal(latencyHistogram.attributes.status, 'success');
129134
assert.ok(latencyHistogram.attributes.sourceVersion);
130135
});
131136

@@ -163,6 +168,7 @@ describe('GoogleCloudMetrics', () => {
163168
assert.equal(requestCounter.value, 1);
164169
assert.equal(requestCounter.attributes.name, 'testActionWithFailure');
165170
assert.equal(requestCounter.attributes.source, 'ts');
171+
assert.equal(requestCounter.attributes.status, 'failure');
166172
assert.equal(requestCounter.attributes.error, 'TypeError');
167173
});
168174

@@ -253,6 +259,7 @@ describe('GoogleCloudMetrics', () => {
253259
assert.equal(metric.attributes.topK, 3);
254260
assert.equal(metric.attributes.topP, 5);
255261
assert.equal(metric.attributes.source, 'ts');
262+
assert.equal(metric.attributes.status, 'success');
256263
assert.ok(metric.attributes.sourceVersion);
257264
}
258265
});
@@ -285,6 +292,7 @@ describe('GoogleCloudMetrics', () => {
285292
assert.equal(requestCounter.attributes.topK, 3);
286293
assert.equal(requestCounter.attributes.topP, 5);
287294
assert.equal(requestCounter.attributes.source, 'ts');
295+
assert.equal(requestCounter.attributes.status, 'failure');
288296
assert.equal(requestCounter.attributes.error, 'TypeError');
289297
assert.ok(requestCounter.attributes.sourceVersion);
290298
});
@@ -374,6 +382,9 @@ describe('GoogleCloudMetrics', () => {
374382
const pathCounterPoints = await getCounterDataPoints(
375383
'genkit/flow/path/requests'
376384
);
385+
const pathLatencyPoints = await getHistogramDataPoints(
386+
'genkit/flow/path/latency'
387+
);
377388
const paths = new Set(
378389
pathCounterPoints.map((point) => point.attributes.path)
379390
);
@@ -382,9 +393,50 @@ describe('GoogleCloudMetrics', () => {
382393
assert.equal(point.value, 1);
383394
assert.equal(point.attributes.flowName, 'pathTestFlow');
384395
assert.equal(point.attributes.source, 'ts');
385-
assert.equal(point.attributes.success, 'success');
396+
assert.equal(point.attributes.status, 'success');
386397
assert.ok(point.attributes.sourceVersion);
387398
});
399+
pathLatencyPoints.forEach((point) => {
400+
assert.equal(point.value.count, 1);
401+
assert.equal(point.attributes.flowName, 'pathTestFlow');
402+
assert.equal(point.attributes.source, 'ts');
403+
assert.equal(point.attributes.status, 'success');
404+
assert.ok(point.attributes.sourceVersion);
405+
});
406+
});
407+
408+
it('writes flow path failure metrics', async () => {
409+
const flow = createFlow('testFlow', async () => {
410+
const subPath = await run('sub-action', async () => {
411+
return 'done';
412+
});
413+
return Promise.reject(new Error('failed'));
414+
});
415+
416+
assert.rejects(async () => {
417+
await runFlow(flow);
418+
});
419+
420+
const reqPoints = await getCounterDataPoints('genkit/flow/path/requests');
421+
const reqStatuses = reqPoints.map((p) => [
422+
p.attributes.path,
423+
p.attributes.status,
424+
]);
425+
assert.deepEqual(reqStatuses, [
426+
['/{testFlow,t:flow}/{sub-action,t:flowStep}', 'success'],
427+
['/{testFlow,t:flow}', 'failure'],
428+
]);
429+
const latencyPoints = await getHistogramDataPoints(
430+
'genkit/flow/path/latency'
431+
);
432+
const latencyStatuses = latencyPoints.map((p) => [
433+
p.attributes.path,
434+
p.attributes.status,
435+
]);
436+
assert.deepEqual(latencyStatuses, [
437+
['/{testFlow,t:flow}/{sub-action,t:flowStep}', 'success'],
438+
['/{testFlow,t:flow}', 'failure'],
439+
]);
388440
});
389441

390442
describe('Configuration', () => {
@@ -453,23 +505,33 @@ describe('GoogleCloudMetrics', () => {
453505
return getCounterDataPoints(metricName).then((points) => points.at(-1));
454506
}
455507

456-
/** Finds a histogram metric with the given name in the in memory exporter */
457-
async function getHistogramMetric(
508+
/**
509+
* Finds all datapoints for a histogram metric with the given name in the in
510+
* memory exporter.
511+
*/
512+
async function getHistogramDataPoints(
458513
metricName: string
459-
): Promise<DataPoint<Histogram>> {
514+
): Promise<List<DataPoint<Histogram>>> {
460515
const genkitMetrics = await getGenkitMetrics();
461516
const histogramMetric: HistogramMetricData = genkitMetrics.metrics.find(
462517
(e) =>
463518
e.descriptor.name === metricName && e.descriptor.type === 'HISTOGRAM'
464519
);
465520
if (histogramMetric) {
466-
return histogramMetric.dataPoints.at(-1);
521+
return histogramMetric.dataPoints;
467522
}
468523
assert.fail(
469524
`No histogram metric named ${metricName} was found. Only found: ${genkitMetrics.metrics.map((e) => e.descriptor.name)}`
470525
);
471526
}
472527

528+
/** Finds a histogram metric with the given name in the in memory exporter */
529+
async function getHistogramMetric(
530+
metricName: string
531+
): Promise<DataPoint<Histogram>> {
532+
return getHistogramDataPoints(metricName).then((points) => points.at(-1));
533+
}
534+
473535
/** Helper to create a flow with no inputs or outputs */
474536
function createFlow(name: string, fn: () => Promise<void> = async () => {}) {
475537
return defineFlow(

0 commit comments

Comments
 (0)