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

Commit

Permalink
Introduce ApplicationSupport to parse application tags on agent startup
Browse files Browse the repository at this point in the history
and also make every Invocation support method static.
  • Loading branch information
İbrahim Gürses committed Nov 14, 2018
1 parent f7462d7 commit e5c1037
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 126 deletions.
3 changes: 3 additions & 0 deletions src/index.ts
Expand Up @@ -24,6 +24,7 @@ import Logger from './plugins/Logger';
import Log from './plugins/Log';
import AwsXRayConfig from './plugins/config/AwsXRayConfig';
import InvocationSupport from './plugins/support/InvocationSupport';
import ApplicationSupport from './plugins/support/ApplicationSupport';

const ThundraWarmup = require('@thundra/warmup');

Expand Down Expand Up @@ -65,6 +66,8 @@ module.exports = (options: any) => {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
}

ApplicationSupport.parseApplicationTags();

const logStreamName = Utils.getConfiguration(envVariableKeys.AWS_LAMBDA_LOG_STREAM_NAME);
const region = Utils.getConfiguration(envVariableKeys.AWS_REGION);
const functionVersion = Utils.getConfiguration(envVariableKeys.AWS_LAMBDA_FUNCTION_VERSION);
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/Invocation.ts
Expand Up @@ -37,7 +37,7 @@ class Invocation {
}

beforeInvocation = (data: any) => {
InvocationSupport.getInstance().removeTags();
InvocationSupport.removeTags();
const { originalContext, reporter } = data;
this.reporter = reporter;
this.finishTimestamp = null;
Expand Down Expand Up @@ -100,13 +100,13 @@ class Invocation {
}
}

this.invocationData.setTags(InvocationSupport.getInstance().getTags());
this.invocationData.setTags(InvocationSupport.tags);
this.finishTimestamp = Date.now();
this.invocationData.finishTimestamp = this.finishTimestamp;
this.invocationData.duration = this.finishTimestamp - this.startTimestamp;
const reportData = Utils.generateReport(this.invocationData, this.apiKey);
this.report(reportData);
InvocationSupport.getInstance().removeTags();
InvocationSupport.removeTags();
}
}

Expand Down
25 changes: 2 additions & 23 deletions src/plugins/Utils.ts
Expand Up @@ -18,6 +18,7 @@ import TraceData from './data/trace/TraceData';
import SpanData from './data/trace/SpanData';
import LogData from './data/log/LogData';
import ThundraLogger from '../ThundraLogger';
import ApplicationSupport from './support/ApplicationSupport';

class Utils {
static generateId(): string {
Expand Down Expand Up @@ -213,7 +214,7 @@ class Utils {
monitoringData.applicationStage = stage ? stage : '';
monitoringData.applicationRuntimeVersion = process.version;

Utils.addApplicationTags(monitoringData.applicationTags);
monitoringData.applicationTags = {...monitoringData.applicationTags, ...ApplicationSupport.applicationTags};

return monitoringData;
}
Expand Down Expand Up @@ -241,28 +242,6 @@ class Utils {

return monitoringData;
}

static addApplicationTags(applicationTags: any): void {
for (const key of Object.keys(process.env)) {
if (key.startsWith(envVariableKeys.THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX)) {
try {
const propsKey = key.substring(envVariableKeys.THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX.length);
const propsValue = process.env[key];
if (isNaN(parseInt(propsValue, 10))) {
if (propsValue === 'true' || propsValue === 'false') {
applicationTags[propsKey] = propsValue === 'true' ? true : false;
} else {
applicationTags[propsKey] = propsValue;
}
} else {
applicationTags[propsKey] = parseInt(propsValue, 10);
}
} catch (ex) {
ThundraLogger.getInstance().error(`Cannot parse application tag ${key}`);
}
}
}
}
}

export default Utils;
32 changes: 32 additions & 0 deletions src/plugins/support/ApplicationSupport.ts
@@ -0,0 +1,32 @@
import { envVariableKeys } from '../../Constants';

import ThundraLogger from '../../ThundraLogger';

class ApplicationSupport {
static applicationTags: any = {};

static parseApplicationTags(): void {
ApplicationSupport.applicationTags = {};
for (const key of Object.keys(process.env)) {
if (key.startsWith(envVariableKeys.THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX)) {
try {
const propsKey = key.substring(envVariableKeys.THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX.length);
const propsValue = process.env[key];
if (isNaN(parseFloat(propsValue))) {
if (propsValue === 'true' || propsValue === 'false') {
ApplicationSupport.applicationTags[propsKey] = propsValue === 'true' ? true : false;
} else {
ApplicationSupport.applicationTags[propsKey] = propsValue;
}
} else {
ApplicationSupport.applicationTags[propsKey] = parseFloat(propsValue);
}
} catch (ex) {
ThundraLogger.getInstance().error(`Cannot parse application tag ${key}`);
}
}
}
}
}

export default ApplicationSupport;
33 changes: 9 additions & 24 deletions src/plugins/support/InvocationSupport.ts
@@ -1,47 +1,32 @@
import ThundraLogger from '../../ThundraLogger';

class InvocationSupport {
static instance: InvocationSupport;
static tags: any = {};

tags: Map<string, any>;

constructor() {
this.tags = new Map<string, any>();
InvocationSupport.instance = this;
}

static getInstance(): InvocationSupport {
return InvocationSupport.instance ? InvocationSupport.instance : new InvocationSupport();
}

setTag(key: string, value: any): void {
static setTag(key: string, value: any): void {
try {
this.tags.set(key, value);
InvocationSupport.tags[key] = value;
} catch (e) {
ThundraLogger.getInstance().error(e);
}
}

getTag(key: string): any {
return this.tags.get(key);
static getTag(key: string): any {
return InvocationSupport.tags[key];
}

setTags(keyValuePairs: {[key: string]: any }): void {
static setTags(keyValuePairs: {[key: string]: any }): void {
try {
Object.keys(keyValuePairs).forEach((key) => {
this.tags.set(key, keyValuePairs[key]);
InvocationSupport.tags[key] = keyValuePairs[key];
});
} catch (e) {
ThundraLogger.getInstance().error(e);
}
}

getTags(): Map<string, any> {
return this.tags;
}

removeTags(): void {
this.tags.clear();
static removeTags(): void {
InvocationSupport.tags = {};
}
}

Expand Down
27 changes: 27 additions & 0 deletions test/plugins/application.support.test.js
@@ -0,0 +1,27 @@

import ApplicationSupport from '../../dist/plugins/support/ApplicationSupport';

describe('addApplicationTags', () => {
const THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX = 'thundra_agent_lambda_application_tag_';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag1'] = '5';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag2'] = 'true';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag3'] = 'false';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag4'] = 'test value';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag5'] = '3.5';

ApplicationSupport.parseApplicationTags();

it('should parse application tags from environment variables', () => {
expect(ApplicationSupport.applicationTags['tag1']).toBe(5);
expect(ApplicationSupport.applicationTags['tag2']).toBe(true);
expect(ApplicationSupport.applicationTags['tag3']).toBe(false);
expect(ApplicationSupport.applicationTags['tag4']).toBe('test value');
expect(ApplicationSupport.applicationTags['tag5']).toBe(3.5);
});

process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag1'] = null;
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag2'] = null;
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag3'] = null;
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag4'] = null;
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag5'] = null;
});
82 changes: 33 additions & 49 deletions test/plugins/invocation.support.test.js
Expand Up @@ -3,70 +3,54 @@ import InvocationSupport from '../../dist/plugins/support/InvocationSupport';
describe('Invocation Support', () => {

beforeEach(() => {
InvocationSupport.instance = null;
InvocationSupport.removeTags();
});

describe('should return singleton', () => {
new InvocationSupport();

test('getInstance called', () => {
expect(InvocationSupport.getInstance()).toBeTruthy();
});
});


describe('should set tag', () => {
const invocationSupport = new InvocationSupport();

invocationSupport.setTag('number', 5);
invocationSupport.setTag('string', 'value');
invocationSupport.setTag('boolean', true);
const object = {
name: 'ibrahim',
age: 15,
};

invocationSupport.setTag('object', object);

test('tags', () => {
expect(invocationSupport.tags.get('number')).toBe(5);
expect(invocationSupport.tags.get('string')).toBe('value');
expect(invocationSupport.tags.get('boolean')).toBe(true);
expect(invocationSupport.tags.get('object')).toBe(object);
InvocationSupport.setTag('number', 5);
InvocationSupport.setTag('string', 'value');
InvocationSupport.setTag('boolean', true);
const object = {
name: 'ibrahim',
age: 15,
};

InvocationSupport.setTag('object', object);

expect(InvocationSupport.tags['number']).toBe(5);
expect(InvocationSupport.tags['string']).toBe('value');
expect(InvocationSupport.tags['boolean']).toBe(true);
expect(InvocationSupport.tags['object']).toBe(object);
});
});


describe('should get tag', () => {
const invocationSupport = new InvocationSupport();

invocationSupport.setTag('string', 'value');
invocationSupport.setTag('boolean', true);
invocationSupport.setTag('number', 5);
const object = {
name: 'ibrahim',
age: 15,
};
invocationSupport.setTag('object', object);

test('tags', () => {
expect(invocationSupport.getTag('number')).toBe(5);
expect(invocationSupport.getTag('string')).toBe('value');
expect(invocationSupport.getTag('boolean')).toBe(true);
expect(invocationSupport.getTag('object')).toBe(object);
InvocationSupport.setTag('string', 'value');
InvocationSupport.setTag('boolean', true);
InvocationSupport.setTag('number', 5);
const object = {
name: 'ibrahim',
age: 15,
};
InvocationSupport.setTag('object', object);

expect(InvocationSupport.getTag('number')).toBe(5);
expect(InvocationSupport.getTag('string')).toBe('value');
expect(InvocationSupport.getTag('boolean')).toBe(true);
expect(InvocationSupport.getTag('object')).toBe(object);
});
});

describe('should remove tags', () => {
const invocationSupport = new InvocationSupport();

invocationSupport.setTag('number', 5);
invocationSupport.setTag('string', 'value');

invocationSupport.removeTags();

test('tags', () => {
expect(invocationSupport.tags.size).toBe(0);
InvocationSupport.setTag('number', 5);
InvocationSupport.setTag('string', 'value');

InvocationSupport.removeTags();
expect(InvocationSupport.tags).toEqual({});
});
});
});
28 changes: 1 addition & 27 deletions test/plugins/utils.test.js
Expand Up @@ -20,10 +20,7 @@ jest.mock('os', () => ({

jest.mock('../../dist/Constants', () => ({
PROC_STAT_PATH: './test/mocks/mock-proc-stat',
PROC_IO_PATH: './test/mocks/mock-proc-io',
envVariableKeys: {
THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX: 'thundra_agent_lambda_application_tag_'
}
PROC_IO_PATH: './test/mocks/mock-proc-io'
}));

describe('getCpuUsage', () => {
Expand Down Expand Up @@ -90,29 +87,6 @@ describe('generateReport', () => {
});
});

describe('addApplicationTags', () => {
const THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX = 'thundra_agent_lambda_application_tag_';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag1'] = '5';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag2'] = 'true';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag3'] = 'false';
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag4'] = 'test value';

const applicationTags = {};
Utils.addApplicationTags(applicationTags);

it('should parse application tags from environment variables', () => {
expect(applicationTags['tag1']).toBe(5);
expect(applicationTags['tag2']).toBe(true);
expect(applicationTags['tag3']).toBe(false);
expect(applicationTags['tag4']).toBe('test value');
});

process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag1'] = null;
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag2'] = null;
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag3'] = null;
process.env[THUNDRA_APPLICATION_TAG_PROP_NAME_PREFIX + 'tag4'] = null;
});

describe('parseError', () => {
describe('Error typed error data', () => {
const error = Error('error message');
Expand Down

0 comments on commit e5c1037

Please sign in to comment.