UNPKG

5.13 kBJavaScriptView Raw
1"use strict";
2/**
3 * Copyright 2019, OpenCensus 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 * http://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.deserializeBinary = exports.serializeBinary = exports.TAG_MAP_SERIALIZED_SIZE_LIMIT = void 0;
19/**
20 * This module contains the functions for serializing and deserializing
21 * TagMap (TagContext) with the binary format. It allows tags to propagate
22 * across requests.
23 *
24 * <p>OpenCensus tag context encoding:
25 *
26 * <ul>
27 * <li>Tags are encoded in single byte sequence. The version 0 format is:
28 * <li>{@code <version_id><encoded_tags>}
29 * <li>{@code <version_id> -> a single byte, value 0}
30 * <li>{@code <encoded_tags> -> (<tag_field_id><tag_encoding>)*}
31 * <ul>
32 * <li>{@code <tag_field_id>} -> a single byte, value 0
33 * <li>{@code <tag_encoding>}:
34 * <ul>
35 * <li>{@code <tag_key_len><tag_key><tag_val_len><tag_val>}
36 * <ul>
37 * <li>{@code <tag_key_len>} -> varint encoded integer
38 * <li>{@code <tag_key>} -> tag_key_len bytes comprising tag name
39 * <li>{@code <tag_val_len>} -> varint encoded integer
40 * <li>{@code <tag_val>} -> tag_val_len bytes comprising tag value
41 * </ul>
42 * </li>
43 * </ul>
44 * </li>
45 * </ul>
46 * </ul>
47 */
48const tag_map_1 = require("../tag-map");
49const variant_encoding_1 = require("./variant-encoding");
50// This size limit only applies to the bytes representing tag keys and values.
51exports.TAG_MAP_SERIALIZED_SIZE_LIMIT = 8192;
52const ENCODING = 'utf8';
53const VERSION_ID = 0;
54const TAG_FIELD_ID = 0;
55const VERSION_ID_INDEX = 0;
56/**
57 * Serializes a given TagMap to the on-the-wire format.
58 * @param tagMap The TagMap to serialize.
59 */
60function serializeBinary(tagMap) {
61 const byteArray = [];
62 byteArray.push(VERSION_ID);
63 let totalChars = 0;
64 const tags = tagMap.tags;
65 tags.forEach((tagValue, tagKey) => {
66 totalChars += tagKey.name.length;
67 totalChars += tagValue.value.length;
68 encodeTag(tagKey, tagValue, byteArray);
69 });
70 if (totalChars > exports.TAG_MAP_SERIALIZED_SIZE_LIMIT) {
71 throw new Error(`Size of TagMap exceeds the maximum serialized size ${exports.TAG_MAP_SERIALIZED_SIZE_LIMIT}`);
72 }
73 return Buffer.from(byteArray);
74}
75exports.serializeBinary = serializeBinary;
76/**
77 * Deserializes input to TagMap based on the binary format standard.
78 * @param buffer The TagMap to deserialize.
79 */
80function deserializeBinary(buffer) {
81 if (buffer.length === 0) {
82 throw new Error('Input buffer can not be empty.');
83 }
84 const versionId = buffer.readInt8(VERSION_ID_INDEX);
85 if (versionId > VERSION_ID) {
86 throw new Error(`Wrong Version ID: ${versionId}. Currently supports version up to: ${VERSION_ID}`);
87 }
88 return parseTags(buffer);
89}
90exports.deserializeBinary = deserializeBinary;
91function encodeTag(tagKey, tagValue, byteArray) {
92 byteArray.push(TAG_FIELD_ID);
93 encodeString(tagKey.name, byteArray);
94 encodeString(tagValue.value, byteArray);
95}
96function encodeString(input, byteArray) {
97 byteArray.push(...variant_encoding_1.EncodeVarint(input.length));
98 byteArray.push(...input.split('').map(unicode));
99 return byteArray;
100}
101function parseTags(buffer) {
102 const tags = new tag_map_1.TagMap();
103 const limit = buffer.length;
104 let totalChars = 0;
105 let currentIndex = 1;
106 while (currentIndex < limit) {
107 const fieldId = buffer.readInt8(currentIndex);
108 if (fieldId > TAG_FIELD_ID) {
109 // Stop parsing at the first unknown field ID, since there is no way to
110 // know its length.
111 break;
112 }
113 currentIndex += 1;
114 const key = decodeString(buffer, currentIndex);
115 currentIndex += key.length;
116 totalChars += key.length;
117 currentIndex += 1;
118 const val = decodeString(buffer, currentIndex);
119 currentIndex += val.length;
120 totalChars += val.length;
121 currentIndex += 1;
122 if (totalChars > exports.TAG_MAP_SERIALIZED_SIZE_LIMIT) {
123 throw new Error(`Size of TagMap exceeds the maximum serialized size ${exports.TAG_MAP_SERIALIZED_SIZE_LIMIT}`);
124 }
125 else {
126 tags.set({ name: key }, { value: val });
127 }
128 }
129 return tags;
130}
131function decodeString(buffer, offset) {
132 const length = variant_encoding_1.DecodeVarint(buffer, offset);
133 return buffer.toString(ENCODING, offset + 1, offset + 1 + length);
134}
135function unicode(x) {
136 return x.charCodeAt(0);
137}
138//# sourceMappingURL=binary-serializer.js.map
\No newline at end of file