UNPKG

3.98 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright The OpenTelemetry Authors
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.TraceStateImpl = void 0;
19const tracestate_validators_1 = require("./tracestate-validators");
20const MAX_TRACE_STATE_ITEMS = 32;
21const MAX_TRACE_STATE_LEN = 512;
22const LIST_MEMBERS_SEPARATOR = ',';
23const LIST_MEMBER_KEY_VALUE_SPLITTER = '=';
24/**
25 * TraceState must be a class and not a simple object type because of the spec
26 * requirement (https://www.w3.org/TR/trace-context/#tracestate-field).
27 *
28 * Here is the list of allowed mutations:
29 * - New key-value pair should be added into the beginning of the list
30 * - The value of any key can be updated. Modified keys MUST be moved to the
31 * beginning of the list.
32 */
33class TraceStateImpl {
34 constructor(rawTraceState) {
35 this._internalState = new Map();
36 if (rawTraceState)
37 this._parse(rawTraceState);
38 }
39 set(key, value) {
40 // TODO: Benchmark the different approaches(map vs list) and
41 // use the faster one.
42 const traceState = this._clone();
43 if (traceState._internalState.has(key)) {
44 traceState._internalState.delete(key);
45 }
46 traceState._internalState.set(key, value);
47 return traceState;
48 }
49 unset(key) {
50 const traceState = this._clone();
51 traceState._internalState.delete(key);
52 return traceState;
53 }
54 get(key) {
55 return this._internalState.get(key);
56 }
57 serialize() {
58 return this._keys()
59 .reduce((agg, key) => {
60 agg.push(key + LIST_MEMBER_KEY_VALUE_SPLITTER + this.get(key));
61 return agg;
62 }, [])
63 .join(LIST_MEMBERS_SEPARATOR);
64 }
65 _parse(rawTraceState) {
66 if (rawTraceState.length > MAX_TRACE_STATE_LEN)
67 return;
68 this._internalState = rawTraceState
69 .split(LIST_MEMBERS_SEPARATOR)
70 .reverse() // Store in reverse so new keys (.set(...)) will be placed at the beginning
71 .reduce((agg, part) => {
72 const listMember = part.trim(); // Optional Whitespace (OWS) handling
73 const i = listMember.indexOf(LIST_MEMBER_KEY_VALUE_SPLITTER);
74 if (i !== -1) {
75 const key = listMember.slice(0, i);
76 const value = listMember.slice(i + 1, part.length);
77 if ((0, tracestate_validators_1.validateKey)(key) && (0, tracestate_validators_1.validateValue)(value)) {
78 agg.set(key, value);
79 }
80 else {
81 // TODO: Consider to add warning log
82 }
83 }
84 return agg;
85 }, new Map());
86 // Because of the reverse() requirement, trunc must be done after map is created
87 if (this._internalState.size > MAX_TRACE_STATE_ITEMS) {
88 this._internalState = new Map(Array.from(this._internalState.entries())
89 .reverse() // Use reverse same as original tracestate parse chain
90 .slice(0, MAX_TRACE_STATE_ITEMS));
91 }
92 }
93 _keys() {
94 return Array.from(this._internalState.keys()).reverse();
95 }
96 _clone() {
97 const traceState = new TraceStateImpl();
98 traceState._internalState = new Map(this._internalState);
99 return traceState;
100 }
101}
102exports.TraceStateImpl = TraceStateImpl;
103//# sourceMappingURL=tracestate-impl.js.map
\No newline at end of file