@sentry/core
Version:
Base implementation for all Sentry JavaScript SDKs
123 lines (105 loc) • 3.51 kB
JavaScript
import { getGlobalSingleton, logger } from '@sentry/utils';
import { getClient } from '../currentScopes.js';
import { DEBUG_BUILD } from '../debug-build.js';
import { getActiveSpan, getRootSpan, spanToJSON } from '../utils/spanUtils.js';
import { COUNTER_METRIC_TYPE, DISTRIBUTION_METRIC_TYPE, SET_METRIC_TYPE, GAUGE_METRIC_TYPE } from './constants.js';
/**
* Gets the metrics aggregator for a given client.
* @param client The client for which to get the metrics aggregator.
* @param Aggregator Optional metrics aggregator class to use to create an aggregator if one does not exist.
*/
function getMetricsAggregatorForClient(
client,
Aggregator,
) {
const globalMetricsAggregators = getGlobalSingleton(
'globalMetricsAggregators',
() => new WeakMap(),
);
const aggregator = globalMetricsAggregators.get(client);
if (aggregator) {
return aggregator;
}
const newAggregator = new Aggregator(client);
client.on('flush', () => newAggregator.flush());
client.on('close', () => newAggregator.close());
globalMetricsAggregators.set(client, newAggregator);
return newAggregator;
}
function addToMetricsAggregator(
Aggregator,
metricType,
name,
value,
data = {},
) {
const client = data.client || getClient();
if (!client) {
return;
}
const span = getActiveSpan();
const rootSpan = span ? getRootSpan(span) : undefined;
const { unit, tags, timestamp } = data;
const { release, environment } = client.getOptions();
const metricTags = {};
if (release) {
metricTags.release = release;
}
if (environment) {
metricTags.environment = environment;
}
if (rootSpan) {
metricTags.transaction = spanToJSON(rootSpan).description || '';
}
DEBUG_BUILD && logger.log(`Adding value of ${value} to ${metricType} metric ${name}`);
const aggregator = getMetricsAggregatorForClient(client, Aggregator);
aggregator.add(metricType, name, value, unit, { ...metricTags, ...tags }, timestamp);
}
/**
* Adds a value to a counter metric
*
* @experimental This API is experimental and might have breaking changes in the future.
*/
function increment(aggregator, name, value = 1, data) {
addToMetricsAggregator(aggregator, COUNTER_METRIC_TYPE, name, ensureNumber(value), data);
}
/**
* Adds a value to a distribution metric
*
* @experimental This API is experimental and might have breaking changes in the future.
*/
function distribution(aggregator, name, value, data) {
addToMetricsAggregator(aggregator, DISTRIBUTION_METRIC_TYPE, name, ensureNumber(value), data);
}
/**
* Adds a value to a set metric. Value must be a string or integer.
*
* @experimental This API is experimental and might have breaking changes in the future.
*/
function set(aggregator, name, value, data) {
addToMetricsAggregator(aggregator, SET_METRIC_TYPE, name, value, data);
}
/**
* Adds a value to a gauge metric
*
* @experimental This API is experimental and might have breaking changes in the future.
*/
function gauge(aggregator, name, value, data) {
addToMetricsAggregator(aggregator, GAUGE_METRIC_TYPE, name, ensureNumber(value), data);
}
const metrics = {
increment,
distribution,
set,
gauge,
/**
* @ignore This is for internal use only.
*/
getMetricsAggregatorForClient,
};
// Although this is typed to be a number, we try to handle strings as well here
function ensureNumber(number) {
return typeof number === 'string' ? parseInt(number) : number;
}
export { metrics };
//# sourceMappingURL=exports.js.map