@sentry/utils
Version:
Utilities for all Sentry JavaScript SDKs
167 lines (146 loc) • 5.76 kB
JavaScript
import { logger } from './logger.js';
var BAGGAGE_HEADER_NAME = 'baggage';
var SENTRY_BAGGAGE_KEY_PREFIX = 'sentry-';
var SENTRY_BAGGAGE_KEY_PREFIX_REGEX = /^sentry-/;
/**
* Max length of a serialized baggage string
*
* https://www.w3.org/TR/baggage/#limits
*/
var MAX_BAGGAGE_STRING_LENGTH = 8192;
/** Create an instance of Baggage */
function createBaggage(initItems, baggageString = '', mutable = true) {
return [{ ...initItems }, baggageString, mutable];
}
/** Get a value from baggage */
function getBaggageValue(baggage, key) {
return baggage[0][key];
}
/** Add a value to baggage */
function setBaggageValue(baggage, key, value) {
if (isBaggageMutable(baggage)) {
baggage[0][key] = value;
}
}
/** Check if the Sentry part of the passed baggage (i.e. the first element in the tuple) is empty */
function isSentryBaggageEmpty(baggage) {
return Object.keys(baggage[0]).length === 0;
}
/** Check if the Sentry part of the passed baggage (i.e. the first element in the tuple) is empty */
function isBaggageEmpty(baggage) {
var thirdPartyBaggage = getThirdPartyBaggage(baggage);
return isSentryBaggageEmpty(baggage) && (thirdPartyBaggage == undefined || thirdPartyBaggage.length === 0);
}
/** Returns Sentry specific baggage values */
function getSentryBaggageItems(baggage) {
return baggage[0];
}
/**
* Returns 3rd party baggage string of @param baggage
* @param baggage
*/
function getThirdPartyBaggage(baggage) {
return baggage[1];
}
/**
* Checks if baggage is mutable
* @param baggage
* @returns true if baggage is mutable, else false
*/
function isBaggageMutable(baggage) {
return baggage[2];
}
/**
* Sets the passed baggage immutable
* @param baggage
*/
function setBaggageImmutable(baggage) {
baggage[2] = false;
}
/** Serialize a baggage object */
function serializeBaggage(baggage) {
return Object.keys(baggage[0]).reduce((prev, key) => {
var val = baggage[0][key] ;
var baggageEntry = `${SENTRY_BAGGAGE_KEY_PREFIX}${encodeURIComponent(key)}=${encodeURIComponent(val)}`;
var newVal = prev === '' ? baggageEntry : `${prev},${baggageEntry}`;
if (newVal.length > MAX_BAGGAGE_STRING_LENGTH) {
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
logger.warn(`Not adding key: ${key} with val: ${val} to baggage due to exceeding baggage size limits.`);
return prev;
} else {
return newVal;
}
}, baggage[1]);
}
/** Parse a baggage header from a string and return a Baggage object */
function parseBaggageString(inputBaggageString) {
return inputBaggageString.split(',').reduce(
([baggageObj, baggageString], curr) => {
const [key, val] = curr.split('=');
if (SENTRY_BAGGAGE_KEY_PREFIX_REGEX.test(key)) {
var baggageKey = decodeURIComponent(key.split('-')[1]);
return [
{
...baggageObj,
[baggageKey]: decodeURIComponent(val),
},
baggageString,
true,
];
} else {
return [baggageObj, baggageString === '' ? curr : `${baggageString},${curr}`, true];
}
},
[{}, '', true],
);
}
/**
* Merges the baggage header we saved from the incoming request (or meta tag) with
* a possibly created or modified baggage header by a third party that's been added
* to the outgoing request header.
*
* In case @param headerBaggageString exists, we can safely add the the 3rd party part of @param headerBaggage
* with our @param incomingBaggage. This is possible because if we modified anything beforehand,
* it would only affect parts of the sentry baggage (@see Baggage interface).
*
* @param incomingBaggage the baggage header of the incoming request that might contain sentry entries
* @param headerBaggageString possibly existing baggage header string added from a third party to request headers
*
* @return a merged and serialized baggage string to be propagated with the outgoing request
*/
function mergeAndSerializeBaggage(incomingBaggage, headerBaggageString) {
if (!incomingBaggage && !headerBaggageString) {
return '';
}
var headerBaggage = (headerBaggageString && parseBaggageString(headerBaggageString)) || undefined;
var thirdPartyHeaderBaggage = headerBaggage && getThirdPartyBaggage(headerBaggage);
var finalBaggage = createBaggage(
(incomingBaggage && incomingBaggage[0]) || {},
thirdPartyHeaderBaggage || (incomingBaggage && incomingBaggage[1]) || '',
);
return serializeBaggage(finalBaggage);
}
/**
* Helper function that takes a raw baggage string (if available) and the processed sentry-trace header
* data (if available), parses the baggage string and creates a Baggage object
* If there is no baggage string, it will create an empty Baggage object.
* In a second step, this functions determines if the created Baggage object should be set immutable
* to prevent mutation of the Sentry data.
*
* Extracted this logic to a function because it's duplicated in a lot of places.
*
* @param rawBaggageString
* @param sentryTraceHeader
*/
function parseBaggageSetMutability(
rawBaggageString,
sentryTraceHeader,
) {
var baggage = parseBaggageString(rawBaggageString || '');
if (!isSentryBaggageEmpty(baggage) || (sentryTraceHeader && isSentryBaggageEmpty(baggage))) {
setBaggageImmutable(baggage);
}
return baggage;
}
export { BAGGAGE_HEADER_NAME, MAX_BAGGAGE_STRING_LENGTH, SENTRY_BAGGAGE_KEY_PREFIX, SENTRY_BAGGAGE_KEY_PREFIX_REGEX, createBaggage, getBaggageValue, getSentryBaggageItems, getThirdPartyBaggage, isBaggageEmpty, isBaggageMutable, isSentryBaggageEmpty, mergeAndSerializeBaggage, parseBaggageSetMutability, parseBaggageString, serializeBaggage, setBaggageImmutable, setBaggageValue };
//# sourceMappingURL=baggage.js.map