| 
 | 1 | +import type { MeasurementUnit, Span } from '@sentry/types';  | 
 | 2 | +import type { MetricSummary } from '@sentry/types';  | 
 | 3 | +import type { Primitive } from '@sentry/types';  | 
 | 4 | +import { dropUndefinedKeys } from '@sentry/utils';  | 
 | 5 | +import { getActiveSpan } from '../tracing';  | 
 | 6 | +import type { MetricType } from './types';  | 
 | 7 | + | 
 | 8 | +/**  | 
 | 9 | + * key: bucketKey  | 
 | 10 | + * value: [exportKey, MetricSummary]  | 
 | 11 | + */  | 
 | 12 | +type MetricSummaryStorage = Map<string, [string, MetricSummary]>;  | 
 | 13 | + | 
 | 14 | +let SPAN_METRIC_SUMMARY: WeakMap<Span, MetricSummaryStorage> | undefined;  | 
 | 15 | + | 
 | 16 | +function getMetricStorageForSpan(span: Span): MetricSummaryStorage | undefined {  | 
 | 17 | +  return SPAN_METRIC_SUMMARY ? SPAN_METRIC_SUMMARY.get(span) : undefined;  | 
 | 18 | +}  | 
 | 19 | + | 
 | 20 | +/**  | 
 | 21 | + * Fetches the metric summary if it exists for the passed span  | 
 | 22 | + */  | 
 | 23 | +export function getMetricSummaryJsonForSpan(span: Span): Record<string, MetricSummary> | undefined {  | 
 | 24 | +  const storage = getMetricStorageForSpan(span);  | 
 | 25 | + | 
 | 26 | +  if (!storage) {  | 
 | 27 | +    return undefined;  | 
 | 28 | +  }  | 
 | 29 | +  const output: Record<string, MetricSummary> = {};  | 
 | 30 | + | 
 | 31 | +  for (const [, [exportKey, summary]] of storage) {  | 
 | 32 | +    output[exportKey] = dropUndefinedKeys(summary);  | 
 | 33 | +  }  | 
 | 34 | + | 
 | 35 | +  return output;  | 
 | 36 | +}  | 
 | 37 | + | 
 | 38 | +/**  | 
 | 39 | + * Updates the metric summary on the currently active span  | 
 | 40 | + */  | 
 | 41 | +export function updateMetricSummaryOnActiveSpan(  | 
 | 42 | +  metricType: MetricType,  | 
 | 43 | +  sanitizedName: string,  | 
 | 44 | +  value: number,  | 
 | 45 | +  unit: MeasurementUnit,  | 
 | 46 | +  tags: Record<string, Primitive>,  | 
 | 47 | +  bucketKey: string,  | 
 | 48 | +): void {  | 
 | 49 | +  const span = getActiveSpan();  | 
 | 50 | +  if (span) {  | 
 | 51 | +    const storage = getMetricStorageForSpan(span) || new Map<string, [string, MetricSummary]>();  | 
 | 52 | + | 
 | 53 | +    const exportKey = `${metricType}:${sanitizedName}@${unit}`;  | 
 | 54 | +    const bucketItem = storage.get(bucketKey);  | 
 | 55 | + | 
 | 56 | +    if (bucketItem) {  | 
 | 57 | +      const [, summary] = bucketItem;  | 
 | 58 | +      storage.set(bucketKey, [  | 
 | 59 | +        exportKey,  | 
 | 60 | +        {  | 
 | 61 | +          min: Math.min(summary.min, value),  | 
 | 62 | +          max: Math.max(summary.max, value),  | 
 | 63 | +          count: (summary.count += 1),  | 
 | 64 | +          sum: (summary.sum += value),  | 
 | 65 | +          tags: summary.tags,  | 
 | 66 | +        },  | 
 | 67 | +      ]);  | 
 | 68 | +    } else {  | 
 | 69 | +      storage.set(bucketKey, [  | 
 | 70 | +        exportKey,  | 
 | 71 | +        {  | 
 | 72 | +          min: value,  | 
 | 73 | +          max: value,  | 
 | 74 | +          count: 1,  | 
 | 75 | +          sum: value,  | 
 | 76 | +          tags,  | 
 | 77 | +        },  | 
 | 78 | +      ]);  | 
 | 79 | +    }  | 
 | 80 | + | 
 | 81 | +    if (!SPAN_METRIC_SUMMARY) {  | 
 | 82 | +      SPAN_METRIC_SUMMARY = new WeakMap();  | 
 | 83 | +    }  | 
 | 84 | + | 
 | 85 | +    SPAN_METRIC_SUMMARY.set(span, storage);  | 
 | 86 | +  }  | 
 | 87 | +}  | 
0 commit comments