-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): Add metric summaries to spans (#10554)
Co-authored-by: Abhijeet Prasad <[email protected]>
- Loading branch information
1 parent
ac7cb33
commit 7b3a22d
Showing
12 changed files
with
286 additions
and
17 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
dev-packages/node-integration-tests/suites/tracing/metric-summaries/scenario.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
const { loggingTransport } = require('@sentry-internal/node-integration-tests'); | ||
const Sentry = require('@sentry/node'); | ||
|
||
Sentry.init({ | ||
dsn: 'https://[email protected]/1337', | ||
release: '1.0', | ||
tracesSampleRate: 1.0, | ||
transport: loggingTransport, | ||
_experiments: { | ||
metricsAggregator: true, | ||
}, | ||
}); | ||
|
||
// Stop the process from exiting before the transaction is sent | ||
setInterval(() => {}, 1000); | ||
|
||
Sentry.startSpan( | ||
{ | ||
name: 'Test Transaction', | ||
op: 'transaction', | ||
}, | ||
() => { | ||
Sentry.metrics.increment('root-counter', 1, { | ||
tags: { | ||
email: '[email protected]', | ||
}, | ||
}); | ||
Sentry.metrics.increment('root-counter', 1, { | ||
tags: { | ||
email: '[email protected]', | ||
}, | ||
}); | ||
|
||
Sentry.startSpan( | ||
{ | ||
name: 'Some other span', | ||
op: 'transaction', | ||
}, | ||
() => { | ||
Sentry.metrics.increment('root-counter'); | ||
Sentry.metrics.increment('root-counter'); | ||
Sentry.metrics.increment('root-counter', 2); | ||
|
||
Sentry.metrics.set('root-set', 'some-value'); | ||
Sentry.metrics.set('root-set', 'another-value'); | ||
Sentry.metrics.set('root-set', 'another-value'); | ||
|
||
Sentry.metrics.gauge('root-gauge', 42); | ||
Sentry.metrics.gauge('root-gauge', 20); | ||
|
||
Sentry.metrics.distribution('root-distribution', 42); | ||
Sentry.metrics.distribution('root-distribution', 20); | ||
}, | ||
); | ||
}, | ||
); |
91 changes: 91 additions & 0 deletions
91
dev-packages/node-integration-tests/suites/tracing/metric-summaries/test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { createRunner } from '../../../utils/runner'; | ||
|
||
const EXPECTED_TRANSACTION = { | ||
transaction: 'Test Transaction', | ||
_metrics_summary: { | ||
'c:root-counter@none': [ | ||
{ | ||
min: 1, | ||
max: 1, | ||
count: 1, | ||
sum: 1, | ||
tags: { | ||
release: '1.0', | ||
transaction: 'Test Transaction', | ||
email: '[email protected]', | ||
}, | ||
}, | ||
{ | ||
min: 1, | ||
max: 1, | ||
count: 1, | ||
sum: 1, | ||
tags: { | ||
release: '1.0', | ||
transaction: 'Test Transaction', | ||
email: '[email protected]', | ||
}, | ||
}, | ||
], | ||
}, | ||
spans: expect.arrayContaining([ | ||
expect.objectContaining({ | ||
description: 'Some other span', | ||
op: 'transaction', | ||
_metrics_summary: { | ||
'c:root-counter@none': [ | ||
{ | ||
min: 1, | ||
max: 2, | ||
count: 3, | ||
sum: 4, | ||
tags: { | ||
release: '1.0', | ||
transaction: 'Test Transaction', | ||
}, | ||
}, | ||
], | ||
's:root-set@none': [ | ||
{ | ||
min: 0, | ||
max: 1, | ||
count: 3, | ||
sum: 2, | ||
tags: { | ||
release: '1.0', | ||
transaction: 'Test Transaction', | ||
}, | ||
}, | ||
], | ||
'g:root-gauge@none': [ | ||
{ | ||
min: 20, | ||
max: 42, | ||
count: 2, | ||
sum: 62, | ||
tags: { | ||
release: '1.0', | ||
transaction: 'Test Transaction', | ||
}, | ||
}, | ||
], | ||
'd:root-distribution@none': [ | ||
{ | ||
min: 20, | ||
max: 42, | ||
count: 2, | ||
sum: 62, | ||
tags: { | ||
release: '1.0', | ||
transaction: 'Test Transaction', | ||
}, | ||
}, | ||
], | ||
}, | ||
}), | ||
]), | ||
}; | ||
|
||
test('Should add metric summaries to spans', done => { | ||
createRunner(__dirname, 'scenario.js').expect({ transaction: EXPECTED_TRANSACTION }).start(done); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import type { MeasurementUnit, Span } from '@sentry/types'; | ||
import type { MetricSummary } from '@sentry/types'; | ||
import type { Primitive } from '@sentry/types'; | ||
import { dropUndefinedKeys } from '@sentry/utils'; | ||
import { getActiveSpan } from '../tracing'; | ||
import type { MetricType } from './types'; | ||
|
||
/** | ||
* key: bucketKey | ||
* value: [exportKey, MetricSummary] | ||
*/ | ||
type MetricSummaryStorage = Map<string, [string, MetricSummary]>; | ||
|
||
let SPAN_METRIC_SUMMARY: WeakMap<Span, MetricSummaryStorage> | undefined; | ||
|
||
function getMetricStorageForSpan(span: Span): MetricSummaryStorage | undefined { | ||
return SPAN_METRIC_SUMMARY ? SPAN_METRIC_SUMMARY.get(span) : undefined; | ||
} | ||
|
||
/** | ||
* Fetches the metric summary if it exists for the passed span | ||
*/ | ||
export function getMetricSummaryJsonForSpan(span: Span): Record<string, Array<MetricSummary>> | undefined { | ||
const storage = getMetricStorageForSpan(span); | ||
|
||
if (!storage) { | ||
return undefined; | ||
} | ||
const output: Record<string, Array<MetricSummary>> = {}; | ||
|
||
for (const [, [exportKey, summary]] of storage) { | ||
if (!output[exportKey]) { | ||
output[exportKey] = []; | ||
} | ||
|
||
output[exportKey].push(dropUndefinedKeys(summary)); | ||
} | ||
|
||
return output; | ||
} | ||
|
||
/** | ||
* Updates the metric summary on the currently active span | ||
*/ | ||
export function updateMetricSummaryOnActiveSpan( | ||
metricType: MetricType, | ||
sanitizedName: string, | ||
value: number, | ||
unit: MeasurementUnit, | ||
tags: Record<string, Primitive>, | ||
bucketKey: string, | ||
): void { | ||
const span = getActiveSpan(); | ||
if (span) { | ||
const storage = getMetricStorageForSpan(span) || new Map<string, [string, MetricSummary]>(); | ||
|
||
const exportKey = `${metricType}:${sanitizedName}@${unit}`; | ||
const bucketItem = storage.get(bucketKey); | ||
|
||
if (bucketItem) { | ||
const [, summary] = bucketItem; | ||
storage.set(bucketKey, [ | ||
exportKey, | ||
{ | ||
min: Math.min(summary.min, value), | ||
max: Math.max(summary.max, value), | ||
count: (summary.count += 1), | ||
sum: (summary.sum += value), | ||
tags: summary.tags, | ||
}, | ||
]); | ||
} else { | ||
storage.set(bucketKey, [ | ||
exportKey, | ||
{ | ||
min: value, | ||
max: value, | ||
count: 1, | ||
sum: value, | ||
tags, | ||
}, | ||
]); | ||
} | ||
|
||
if (!SPAN_METRIC_SUMMARY) { | ||
SPAN_METRIC_SUMMARY = new WeakMap(); | ||
} | ||
|
||
SPAN_METRIC_SUMMARY.set(span, storage); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.