UNPKG

@opentelemetry/core

Version:

OpenTelemetry Core provides constants and utilities shared by all OpenTelemetry SDK packages.

1 lines • 7.64 kB
{"version":3,"file":"TraceState.cjs","names":["validateKey","validateValue"],"sources":["../../src/trace/TraceState.ts"],"sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { TraceState as TraceStateApi } from '@opentelemetry/api';\nimport { validateKey, validateValue } from '../internal/validators';\n\nconst MAX_TRACE_STATE_ITEMS = 32;\nconst MAX_TRACE_STATE_LEN = 512;\nconst LIST_MEMBERS_SEPARATOR = ',';\nconst LIST_MEMBER_KEY_VALUE_SPLITTER = '=';\n\n/**\n * TraceState must be a class and not a simple object type because of the spec\n * requirement (https://www.w3.org/TR/trace-context/#tracestate-field).\n *\n * Here is the list of allowed mutations:\n * - New key-value pair should be added into the beginning of the list\n * - The value of any key can be updated. Modified keys MUST be moved to the\n * beginning of the list.\n */\nexport class TraceState implements TraceStateApi {\n private _length: number;\n private _rawTraceState: string;\n private _internalState: Map<string, string> | undefined;\n\n constructor(rawTraceState?: string) {\n this._rawTraceState =\n typeof rawTraceState === 'string' ? rawTraceState : '';\n this._length = this._rawTraceState.length;\n }\n\n set(key: string, value: string): TraceState {\n if (!validateKey(key) || !validateValue(value)) {\n return this;\n }\n\n const currState = this._getState();\n const currValue = currState.get(key);\n // Get the new length depending if we already have a value or not\n // - for existing keys we add the difference between the length of the values\n // - for new keys is the key & value lenght plus\n // - +1 for the key/value splitter\n // - +1 for the separator if there are other keys\n let newLength = this._length;\n if (typeof currValue === 'string') {\n newLength += value.length - currValue.length;\n } else {\n // A list can hold at most 32 list-members, so a new key is only\n // accepted while there is room for it. Updating an existing key does\n // not change the count and is always allowed.\n if (currState.size >= MAX_TRACE_STATE_ITEMS) {\n return this;\n }\n newLength += key.length + value.length + (currState.size > 0 ? 2 : 1);\n }\n if (newLength > MAX_TRACE_STATE_LEN) {\n return this;\n }\n\n const newState = new Map(currState);\n newState.delete(key);\n newState.set(key, value);\n return this._fromState(newState, newLength);\n }\n\n unset(key: string): TraceState {\n const currState = this._getState();\n const currValue = currState.get(key);\n\n // No need to create a new instance if the key does not exist\n if (typeof currValue !== 'string') {\n return this;\n }\n\n // Get the new length depending if we already have a value or not\n // - for existing keys we substract key and value length plus\n // - +1 for the key/value splitter\n // - +1 for the separator if there are other keys\n let newLength = this._length - (key.length + currValue.length + 1);\n if (currState.size > 1) {\n // remove separator from length if there's no key or only one.\n newLength = newLength - 1;\n }\n\n const newState = new Map(currState);\n newState.delete(key);\n return this._fromState(newState, newLength);\n }\n\n get(key: string): string | undefined {\n const currState = this._getState();\n return currState.get(key);\n }\n\n serialize(): string {\n // Maps put new entries at the end. We prepend the seralized entry\n // to get the right order according to the spec (updated members go 1st)\n let serialized = '';\n let index = 0;\n for (const entry of this._getState()) {\n if (index > 0) {\n serialized = LIST_MEMBERS_SEPARATOR + serialized;\n }\n serialized =\n `${entry[0]}${LIST_MEMBER_KEY_VALUE_SPLITTER}${entry[1]}` + serialized;\n index++;\n }\n return serialized;\n }\n\n private _getState(): Map<string, string> {\n if (this._internalState) {\n return this._internalState;\n }\n\n // Not parsed yet, lets do it\n const vendorMembers = this._rawTraceState.split(LIST_MEMBERS_SEPARATOR);\n\n // This Map will have the order reversed\n const vendorEntries = new Map();\n let currentLength = 0;\n\n for (const member of vendorMembers) {\n const m = member.trim();\n const idx = m.indexOf(LIST_MEMBER_KEY_VALUE_SPLITTER);\n if (idx === -1) {\n continue;\n }\n\n const key = m.slice(0, idx);\n const value = m.slice(idx + 1);\n if (!validateKey(key) || !validateValue(value)) {\n continue;\n }\n\n // Skip if adding the new member exceeds the length\n const futureLength =\n currentLength + m.length + (vendorEntries.size > 0 ? 1 : 0);\n if (futureLength > MAX_TRACE_STATE_LEN) {\n continue;\n }\n\n // All good, add it\n vendorEntries.set(key, value);\n currentLength = futureLength;\n\n // Check if we reached the max items\n if (vendorEntries.size >= MAX_TRACE_STATE_ITEMS) {\n break;\n }\n }\n\n // Now we set the length & the Map in the right order\n this._length = currentLength;\n this._internalState = new Map(\n Array.from(vendorEntries.entries()).reverse()\n );\n return this._internalState;\n }\n\n private _fromState(state: Map<string, string>, length: number): TraceState {\n const traceState = Object.create(TraceState.prototype) as TraceState;\n traceState._internalState = state;\n traceState._length = length;\n return traceState;\n }\n}\n"],"mappings":";;AAQA,MAAM,wBAAwB;AAC9B,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAC/B,MAAM,iCAAiC;;;;;;;;;;AAWvC,IAAa,aAAb,MAAa,WAAoC;CAC/C;CACA;CACA;CAEA,YAAY,eAAwB;EAClC,KAAK,iBACH,OAAO,kBAAkB,WAAW,gBAAgB;EACtD,KAAK,UAAU,KAAK,eAAe;CACrC;CAEA,IAAI,KAAa,OAA2B;EAC1C,IAAI,CAACA,mBAAAA,YAAY,GAAG,KAAK,CAACC,mBAAAA,cAAc,KAAK,GAC3C,OAAO;EAGT,MAAM,YAAY,KAAK,UAAU;EACjC,MAAM,YAAY,UAAU,IAAI,GAAG;EAMnC,IAAI,YAAY,KAAK;EACrB,IAAI,OAAO,cAAc,UACvB,aAAa,MAAM,SAAS,UAAU;OACjC;GAIL,IAAI,UAAU,QAAQ,uBACpB,OAAO;GAET,aAAa,IAAI,SAAS,MAAM,UAAU,UAAU,OAAO,IAAI,IAAI;EACrE;EACA,IAAI,YAAY,qBACd,OAAO;EAGT,MAAM,WAAW,IAAI,IAAI,SAAS;EAClC,SAAS,OAAO,GAAG;EACnB,SAAS,IAAI,KAAK,KAAK;EACvB,OAAO,KAAK,WAAW,UAAU,SAAS;CAC5C;CAEA,MAAM,KAAyB;EAC7B,MAAM,YAAY,KAAK,UAAU;EACjC,MAAM,YAAY,UAAU,IAAI,GAAG;EAGnC,IAAI,OAAO,cAAc,UACvB,OAAO;EAOT,IAAI,YAAY,KAAK,WAAW,IAAI,SAAS,UAAU,SAAS;EAChE,IAAI,UAAU,OAAO,GAEnB,YAAY,YAAY;EAG1B,MAAM,WAAW,IAAI,IAAI,SAAS;EAClC,SAAS,OAAO,GAAG;EACnB,OAAO,KAAK,WAAW,UAAU,SAAS;CAC5C;CAEA,IAAI,KAAiC;EAEnC,OADkB,KAAK,UACR,CAAC,CAAC,IAAI,GAAG;CAC1B;CAEA,YAAoB;EAGlB,IAAI,aAAa;EACjB,IAAI,QAAQ;EACZ,KAAK,MAAM,SAAS,KAAK,UAAU,GAAG;GACpC,IAAI,QAAQ,GACV,aAAa,yBAAyB;GAExC,aACE,GAAG,MAAM,KAAK,iCAAiC,MAAM,OAAO;GAC9D;EACF;EACA,OAAO;CACT;CAEA,YAAyC;EACvC,IAAI,KAAK,gBACP,OAAO,KAAK;EAId,MAAM,gBAAgB,KAAK,eAAe,MAAM,sBAAsB;EAGtE,MAAM,gCAAgB,IAAI,IAAI;EAC9B,IAAI,gBAAgB;EAEpB,KAAK,MAAM,UAAU,eAAe;GAClC,MAAM,IAAI,OAAO,KAAK;GACtB,MAAM,MAAM,EAAE,QAAQ,8BAA8B;GACpD,IAAI,QAAQ,IACV;GAGF,MAAM,MAAM,EAAE,MAAM,GAAG,GAAG;GAC1B,MAAM,QAAQ,EAAE,MAAM,MAAM,CAAC;GAC7B,IAAI,CAACD,mBAAAA,YAAY,GAAG,KAAK,CAACC,mBAAAA,cAAc,KAAK,GAC3C;GAIF,MAAM,eACJ,gBAAgB,EAAE,UAAU,cAAc,OAAO,IAAI,IAAI;GAC3D,IAAI,eAAe,qBACjB;GAIF,cAAc,IAAI,KAAK,KAAK;GAC5B,gBAAgB;GAGhB,IAAI,cAAc,QAAQ,uBACxB;EAEJ;EAGA,KAAK,UAAU;EACf,KAAK,iBAAiB,IAAI,IACxB,MAAM,KAAK,cAAc,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAC9C;EACA,OAAO,KAAK;CACd;CAEA,WAAmB,OAA4B,QAA4B;EACzE,MAAM,aAAa,OAAO,OAAO,WAAW,SAAS;EACrD,WAAW,iBAAiB;EAC5B,WAAW,UAAU;EACrB,OAAO;CACT;AACF"}