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

Commit

Permalink
[core] Add Tags API (#295)
Browse files Browse the repository at this point in the history
* [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
  • Loading branch information
mayurkale22 authored Jan 18, 2019
1 parent 2f5d8be commit 7a37197
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 4 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ bin
#VScode
.vscode/

# Other
TAGS

# nodejs
node_modules/
!packages/opencensus-nodejs/test/instrumentation/node_modules
Expand All @@ -40,4 +37,3 @@ build/

#istanbul files
coverage/

2 changes: 2 additions & 0 deletions packages/opencensus-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@ export * from './stats/view';
export * from './stats/recorder';
export * from './stats/bucket-boundaries';
export * from './stats/metric-utils';
export * from './tags/tag-map';

// interfaces
export * from './stats/types';
export * from './tags/types';

// logger
import * as logger from './common/console-logger';
Expand Down
46 changes: 46 additions & 0 deletions packages/opencensus-core/src/tags/tag-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Copyright 2019, OpenCensus Authors
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {TagKey, TagValue} from './types';
import {isValidTagKey, isValidTagValue} from './validation';

/** TagMap is maps of TagKey -> TagValue */
export class TagMap {
// A map mapping TagKey to to its respective TagValue.
private readonly registeredTags: Map<TagKey, TagValue> = new Map();

/** Adds the key/value pair regardless of whether the key is present. */
set(tagKey: TagKey, tagValue: TagValue): void {
if (!isValidTagKey(tagKey)) {
throw Error(`Invalid TagKey name: ${tagKey.name}`);
}

if (!isValidTagValue(tagValue)) {
throw Error(`Invalid TagValue: ${tagValue.value}`);
}
this.registeredTags.set(tagKey, tagValue);
}

/** Deletes a tag from the map if the key is in the map. */
delete(tagKey: TagKey): void {
this.registeredTags.delete(tagKey);
}

/** Gets the tags map. */
get tags() {
return this.registeredTags;
}
}
27 changes: 27 additions & 0 deletions packages/opencensus-core/src/tags/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright 2019, OpenCensus Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/** TagKey represents a tag key */
export interface TagKey {
/** The name of the key. */
readonly name: string;
}

/** TagValue represents a tag value */
export interface TagValue {
/** The value of a tag. */
readonly value: string;
}
42 changes: 42 additions & 0 deletions packages/opencensus-core/src/tags/validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright 2019, OpenCensus Authors
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {TagKey, TagValue} from './types';

const nonPrintableCharsRegex = /[^\u0020-\u007e]/;
const TAG_KEY_MAX_LENGTH = 255;

/** Determines whether the given String is a valid tag key. */
export function isValidTagKey(tagKey: TagKey): boolean {
if (!tagKey) {
return false;
}
return isPrintableString(tagKey.name) && tagKey.name.length > 0 &&
tagKey.name.length <= TAG_KEY_MAX_LENGTH;
}

/** Determines whether the given String is a valid tag value. */
export function isValidTagValue(tagValue: TagValue): boolean {
if (!tagValue) {
return false;
}
return isPrintableString(tagValue.value) &&
tagValue.value.length <= TAG_KEY_MAX_LENGTH;
}

function isPrintableString(name: string): boolean {
return !nonPrintableCharsRegex.test(name);
}
88 changes: 88 additions & 0 deletions packages/opencensus-core/test/test-tag-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Copyright 2019, OpenCensus Authors
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as assert from 'assert';
import {TagMap} from '../src/tags/tag-map';

describe('TagMap()', () => {
let tagMap: TagMap;
const key1 = {name: 'key1'};
const key2 = {name: 'key2'};
const invalidKey1 = {name: 'a'.repeat(256)};
const value1 = {value: 'value1'};
const value2 = {value: 'value2'};
const invalidValue1 = {value: 'a'.repeat(256)};

beforeEach(() => {
tagMap = new TagMap();
});

describe('set()', () => {
it('should set tagkey and tagvalue', () => {
tagMap.set(key1, value1);
const tags = tagMap.tags;
assert.equal(tags.size, 1);
assert.deepStrictEqual(tags.get(key1), value1);
});

it('should throw an error when invalid tagKey', () => {
assert.throws(() => {
tagMap.set(invalidKey1, value1);
}, /^Error: Invalid TagKey name:/);
});

it('should throw an error when invalid tagValue', () => {
assert.throws(() => {
tagMap.set(key1, invalidValue1);
}, /^Error: Invalid TagValue:/);
});

it('should not set duplicate tagkey and tagvalue', () => {
tagMap.set(key1, value1);
const tags = tagMap.tags;
assert.equal(tags.size, 1);
assert.deepStrictEqual(tags.get(key1), value1);
tagMap.set(key1, value1);
assert.equal(tags.size, 1);
});

it('should update existing tagkey', () => {
tagMap.set(key1, value1);
const tags = tagMap.tags;
assert.equal(tags.size, 1);
assert.deepStrictEqual(tags.get(key1), value1);
tagMap.set(key1, value2);
assert.equal(tags.size, 1);
assert.deepStrictEqual(tags.get(key1), value2);
});
});
describe('delete()', () => {
it('should delete tagkey', () => {
tagMap.set(key1, value1);
const tags = tagMap.tags;
assert.equal(tags.size, 1);
tagMap.delete(key1);
assert.equal(tags.size, 0);
});
it('should delete missing tagkey1', () => {
tagMap.set(key1, value1);
const tags = tagMap.tags;
assert.equal(tags.size, 1);
tagMap.delete(key2);
assert.equal(tags.size, 1);
});
});
});
70 changes: 70 additions & 0 deletions packages/opencensus-core/test/test-validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright 2019, OpenCensus Authors
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as assert from 'assert';
import {isValidTagKey, isValidTagValue} from '../src/tags/validation';

describe('isValidTagKey()', () => {
it('should return true when tag key is valid', () => {
const tagKey = {name: 'key1'};
assert.ok(isValidTagKey(tagKey));
});

it('should return false when tag key is 0 character long', () => {
const tagKey = {name: ''};
assert.equal(isValidTagKey(tagKey), false);
});

it('should return false when tag key is null', () => {
assert.equal(isValidTagKey(null), false);
});

it('should return false when tag key is undefined', () => {
assert.equal(isValidTagKey(undefined), false);
});

it('should return false when the tag key length is longer than 255 characters ',
() => {
const tagKey = {name: 'a'.repeat(256)};
assert.equal(isValidTagKey(tagKey), false);
});
});

describe('isValidTagValue()', () => {
it('should return true when tag value is valid', () => {
const tagValue = {value: 'value1'};
assert.ok(isValidTagValue(tagValue));
});

it('should not throw an error when tag value is 0 character long', () => {
const tagValue = {value: ''};
assert.ok(isValidTagValue(tagValue));
});

it('should return false when tag value is null', () => {
assert.equal(isValidTagValue(null), false);
});

it('should return false when tag value is undefined', () => {
assert.equal(isValidTagValue(undefined), false);
});

it('should return false when the tag value length is longer than 255 characters ',
() => {
const tagValue = {value: 'a'.repeat(256)};
assert.equal(isValidTagValue(tagValue), false);
});
});

0 comments on commit 7a37197

Please sign in to comment.