Skip to content
This repository was archived by the owner on Oct 3, 2023. It is now read-only.

Commit 7a37197

Browse files
authored
[core] Add Tags API (#295)
* [core] Add Tags API * fix review comments 1. removed redundant param comments. 2. removed empty constructor. 3. removed unnecessary map.has check. 4. renamed invalidString -> nonPrintableCharsRegex, MAX_LENGTH -> TAG_KEY_MAX_LENGTH * combine insert and update -> set method * export tags types and class
1 parent 2f5d8be commit 7a37197

7 files changed

Lines changed: 275 additions & 4 deletions

File tree

.gitignore

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ bin
2121
#VScode
2222
.vscode/
2323

24-
# Other
25-
TAGS
26-
2724
# nodejs
2825
node_modules/
2926
!packages/opencensus-nodejs/test/instrumentation/node_modules
@@ -40,4 +37,3 @@ build/
4037

4138
#istanbul files
4239
coverage/
43-

packages/opencensus-core/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,11 @@ export * from './stats/view';
7171
export * from './stats/recorder';
7272
export * from './stats/bucket-boundaries';
7373
export * from './stats/metric-utils';
74+
export * from './tags/tag-map';
7475

7576
// interfaces
7677
export * from './stats/types';
78+
export * from './tags/types';
7779

7880
// logger
7981
import * as logger from './common/console-logger';
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Copyright 2019, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {TagKey, TagValue} from './types';
18+
import {isValidTagKey, isValidTagValue} from './validation';
19+
20+
/** TagMap is maps of TagKey -> TagValue */
21+
export class TagMap {
22+
// A map mapping TagKey to to its respective TagValue.
23+
private readonly registeredTags: Map<TagKey, TagValue> = new Map();
24+
25+
/** Adds the key/value pair regardless of whether the key is present. */
26+
set(tagKey: TagKey, tagValue: TagValue): void {
27+
if (!isValidTagKey(tagKey)) {
28+
throw Error(`Invalid TagKey name: ${tagKey.name}`);
29+
}
30+
31+
if (!isValidTagValue(tagValue)) {
32+
throw Error(`Invalid TagValue: ${tagValue.value}`);
33+
}
34+
this.registeredTags.set(tagKey, tagValue);
35+
}
36+
37+
/** Deletes a tag from the map if the key is in the map. */
38+
delete(tagKey: TagKey): void {
39+
this.registeredTags.delete(tagKey);
40+
}
41+
42+
/** Gets the tags map. */
43+
get tags() {
44+
return this.registeredTags;
45+
}
46+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Copyright 2019, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/** TagKey represents a tag key */
18+
export interface TagKey {
19+
/** The name of the key. */
20+
readonly name: string;
21+
}
22+
23+
/** TagValue represents a tag value */
24+
export interface TagValue {
25+
/** The value of a tag. */
26+
readonly value: string;
27+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright 2019, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {TagKey, TagValue} from './types';
18+
19+
const nonPrintableCharsRegex = /[^\u0020-\u007e]/;
20+
const TAG_KEY_MAX_LENGTH = 255;
21+
22+
/** Determines whether the given String is a valid tag key. */
23+
export function isValidTagKey(tagKey: TagKey): boolean {
24+
if (!tagKey) {
25+
return false;
26+
}
27+
return isPrintableString(tagKey.name) && tagKey.name.length > 0 &&
28+
tagKey.name.length <= TAG_KEY_MAX_LENGTH;
29+
}
30+
31+
/** Determines whether the given String is a valid tag value. */
32+
export function isValidTagValue(tagValue: TagValue): boolean {
33+
if (!tagValue) {
34+
return false;
35+
}
36+
return isPrintableString(tagValue.value) &&
37+
tagValue.value.length <= TAG_KEY_MAX_LENGTH;
38+
}
39+
40+
function isPrintableString(name: string): boolean {
41+
return !nonPrintableCharsRegex.test(name);
42+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* Copyright 2019, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as assert from 'assert';
18+
import {TagMap} from '../src/tags/tag-map';
19+
20+
describe('TagMap()', () => {
21+
let tagMap: TagMap;
22+
const key1 = {name: 'key1'};
23+
const key2 = {name: 'key2'};
24+
const invalidKey1 = {name: 'a'.repeat(256)};
25+
const value1 = {value: 'value1'};
26+
const value2 = {value: 'value2'};
27+
const invalidValue1 = {value: 'a'.repeat(256)};
28+
29+
beforeEach(() => {
30+
tagMap = new TagMap();
31+
});
32+
33+
describe('set()', () => {
34+
it('should set tagkey and tagvalue', () => {
35+
tagMap.set(key1, value1);
36+
const tags = tagMap.tags;
37+
assert.equal(tags.size, 1);
38+
assert.deepStrictEqual(tags.get(key1), value1);
39+
});
40+
41+
it('should throw an error when invalid tagKey', () => {
42+
assert.throws(() => {
43+
tagMap.set(invalidKey1, value1);
44+
}, /^Error: Invalid TagKey name:/);
45+
});
46+
47+
it('should throw an error when invalid tagValue', () => {
48+
assert.throws(() => {
49+
tagMap.set(key1, invalidValue1);
50+
}, /^Error: Invalid TagValue:/);
51+
});
52+
53+
it('should not set duplicate tagkey and tagvalue', () => {
54+
tagMap.set(key1, value1);
55+
const tags = tagMap.tags;
56+
assert.equal(tags.size, 1);
57+
assert.deepStrictEqual(tags.get(key1), value1);
58+
tagMap.set(key1, value1);
59+
assert.equal(tags.size, 1);
60+
});
61+
62+
it('should update existing tagkey', () => {
63+
tagMap.set(key1, value1);
64+
const tags = tagMap.tags;
65+
assert.equal(tags.size, 1);
66+
assert.deepStrictEqual(tags.get(key1), value1);
67+
tagMap.set(key1, value2);
68+
assert.equal(tags.size, 1);
69+
assert.deepStrictEqual(tags.get(key1), value2);
70+
});
71+
});
72+
describe('delete()', () => {
73+
it('should delete tagkey', () => {
74+
tagMap.set(key1, value1);
75+
const tags = tagMap.tags;
76+
assert.equal(tags.size, 1);
77+
tagMap.delete(key1);
78+
assert.equal(tags.size, 0);
79+
});
80+
it('should delete missing tagkey1', () => {
81+
tagMap.set(key1, value1);
82+
const tags = tagMap.tags;
83+
assert.equal(tags.size, 1);
84+
tagMap.delete(key2);
85+
assert.equal(tags.size, 1);
86+
});
87+
});
88+
});
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Copyright 2019, OpenCensus Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as assert from 'assert';
18+
import {isValidTagKey, isValidTagValue} from '../src/tags/validation';
19+
20+
describe('isValidTagKey()', () => {
21+
it('should return true when tag key is valid', () => {
22+
const tagKey = {name: 'key1'};
23+
assert.ok(isValidTagKey(tagKey));
24+
});
25+
26+
it('should return false when tag key is 0 character long', () => {
27+
const tagKey = {name: ''};
28+
assert.equal(isValidTagKey(tagKey), false);
29+
});
30+
31+
it('should return false when tag key is null', () => {
32+
assert.equal(isValidTagKey(null), false);
33+
});
34+
35+
it('should return false when tag key is undefined', () => {
36+
assert.equal(isValidTagKey(undefined), false);
37+
});
38+
39+
it('should return false when the tag key length is longer than 255 characters ',
40+
() => {
41+
const tagKey = {name: 'a'.repeat(256)};
42+
assert.equal(isValidTagKey(tagKey), false);
43+
});
44+
});
45+
46+
describe('isValidTagValue()', () => {
47+
it('should return true when tag value is valid', () => {
48+
const tagValue = {value: 'value1'};
49+
assert.ok(isValidTagValue(tagValue));
50+
});
51+
52+
it('should not throw an error when tag value is 0 character long', () => {
53+
const tagValue = {value: ''};
54+
assert.ok(isValidTagValue(tagValue));
55+
});
56+
57+
it('should return false when tag value is null', () => {
58+
assert.equal(isValidTagValue(null), false);
59+
});
60+
61+
it('should return false when tag value is undefined', () => {
62+
assert.equal(isValidTagValue(undefined), false);
63+
});
64+
65+
it('should return false when the tag value length is longer than 255 characters ',
66+
() => {
67+
const tagValue = {value: 'a'.repeat(256)};
68+
assert.equal(isValidTagValue(tagValue), false);
69+
});
70+
});

0 commit comments

Comments
 (0)