123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- Object.defineProperty(exports, '__esModule', { value: true });
- const debugBuild = require('./debug-build.js');
- const is = require('./is.js');
- const logger = require('./logger.js');
- const BAGGAGE_HEADER_NAME = 'baggage';
- const SENTRY_BAGGAGE_KEY_PREFIX = 'sentry-';
- const SENTRY_BAGGAGE_KEY_PREFIX_REGEX = /^sentry-/;
- /**
- * Max length of a serialized baggage string
- *
- * https://www.w3.org/TR/baggage/#limits
- */
- const MAX_BAGGAGE_STRING_LENGTH = 8192;
- /**
- * Takes a baggage header and turns it into Dynamic Sampling Context, by extracting all the "sentry-" prefixed values
- * from it.
- *
- * @param baggageHeader A very bread definition of a baggage header as it might appear in various frameworks.
- * @returns The Dynamic Sampling Context that was found on `baggageHeader`, if there was any, `undefined` otherwise.
- */
- function baggageHeaderToDynamicSamplingContext(
- // Very liberal definition of what any incoming header might look like
- baggageHeader,
- ) {
- if (!is.isString(baggageHeader) && !Array.isArray(baggageHeader)) {
- return undefined;
- }
- // Intermediary object to store baggage key value pairs of incoming baggage headers on.
- // It is later used to read Sentry-DSC-values from.
- let baggageObject = {};
- if (Array.isArray(baggageHeader)) {
- // Combine all baggage headers into one object containing the baggage values so we can later read the Sentry-DSC-values from it
- baggageObject = baggageHeader.reduce((acc, curr) => {
- const currBaggageObject = baggageHeaderToObject(curr);
- for (const key of Object.keys(currBaggageObject)) {
- acc[key] = currBaggageObject[key];
- }
- return acc;
- }, {});
- } else {
- // Return undefined if baggage header is an empty string (technically an empty baggage header is not spec conform but
- // this is how we choose to handle it)
- if (!baggageHeader) {
- return undefined;
- }
- baggageObject = baggageHeaderToObject(baggageHeader);
- }
- // Read all "sentry-" prefixed values out of the baggage object and put it onto a dynamic sampling context object.
- const dynamicSamplingContext = Object.entries(baggageObject).reduce((acc, [key, value]) => {
- if (key.match(SENTRY_BAGGAGE_KEY_PREFIX_REGEX)) {
- const nonPrefixedKey = key.slice(SENTRY_BAGGAGE_KEY_PREFIX.length);
- acc[nonPrefixedKey] = value;
- }
- return acc;
- }, {});
- // Only return a dynamic sampling context object if there are keys in it.
- // A keyless object means there were no sentry values on the header, which means that there is no DSC.
- if (Object.keys(dynamicSamplingContext).length > 0) {
- return dynamicSamplingContext ;
- } else {
- return undefined;
- }
- }
- /**
- * Turns a Dynamic Sampling Object into a baggage header by prefixing all the keys on the object with "sentry-".
- *
- * @param dynamicSamplingContext The Dynamic Sampling Context to turn into a header. For convenience and compatibility
- * with the `getDynamicSamplingContext` method on the Transaction class ,this argument can also be `undefined`. If it is
- * `undefined` the function will return `undefined`.
- * @returns a baggage header, created from `dynamicSamplingContext`, or `undefined` either if `dynamicSamplingContext`
- * was `undefined`, or if `dynamicSamplingContext` didn't contain any values.
- */
- function dynamicSamplingContextToSentryBaggageHeader(
- // this also takes undefined for convenience and bundle size in other places
- dynamicSamplingContext,
- ) {
- if (!dynamicSamplingContext) {
- return undefined;
- }
- // Prefix all DSC keys with "sentry-" and put them into a new object
- const sentryPrefixedDSC = Object.entries(dynamicSamplingContext).reduce(
- (acc, [dscKey, dscValue]) => {
- if (dscValue) {
- acc[`${SENTRY_BAGGAGE_KEY_PREFIX}${dscKey}`] = dscValue;
- }
- return acc;
- },
- {},
- );
- return objectToBaggageHeader(sentryPrefixedDSC);
- }
- /**
- * Will parse a baggage header, which is a simple key-value map, into a flat object.
- *
- * @param baggageHeader The baggage header to parse.
- * @returns a flat object containing all the key-value pairs from `baggageHeader`.
- */
- function baggageHeaderToObject(baggageHeader) {
- return baggageHeader
- .split(',')
- .map(baggageEntry => baggageEntry.split('=').map(keyOrValue => decodeURIComponent(keyOrValue.trim())))
- .reduce((acc, [key, value]) => {
- acc[key] = value;
- return acc;
- }, {});
- }
- /**
- * Turns a flat object (key-value pairs) into a baggage header, which is also just key-value pairs.
- *
- * @param object The object to turn into a baggage header.
- * @returns a baggage header string, or `undefined` if the object didn't have any values, since an empty baggage header
- * is not spec compliant.
- */
- function objectToBaggageHeader(object) {
- if (Object.keys(object).length === 0) {
- // An empty baggage header is not spec compliant: We return undefined.
- return undefined;
- }
- return Object.entries(object).reduce((baggageHeader, [objectKey, objectValue], currentIndex) => {
- const baggageEntry = `${encodeURIComponent(objectKey)}=${encodeURIComponent(objectValue)}`;
- const newBaggageHeader = currentIndex === 0 ? baggageEntry : `${baggageHeader},${baggageEntry}`;
- if (newBaggageHeader.length > MAX_BAGGAGE_STRING_LENGTH) {
- debugBuild.DEBUG_BUILD &&
- logger.logger.warn(
- `Not adding key: ${objectKey} with val: ${objectValue} to baggage header due to exceeding baggage size limits.`,
- );
- return baggageHeader;
- } else {
- return newBaggageHeader;
- }
- }, '');
- }
- exports.BAGGAGE_HEADER_NAME = BAGGAGE_HEADER_NAME;
- exports.MAX_BAGGAGE_STRING_LENGTH = MAX_BAGGAGE_STRING_LENGTH;
- exports.SENTRY_BAGGAGE_KEY_PREFIX = SENTRY_BAGGAGE_KEY_PREFIX;
- exports.SENTRY_BAGGAGE_KEY_PREFIX_REGEX = SENTRY_BAGGAGE_KEY_PREFIX_REGEX;
- exports.baggageHeaderToDynamicSamplingContext = baggageHeaderToDynamicSamplingContext;
- exports.dynamicSamplingContextToSentryBaggageHeader = dynamicSamplingContextToSentryBaggageHeader;
- //# sourceMappingURL=baggage.js.map
|