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

Commit

Permalink
Merge pull request #95 from thundra-io/fix/span-http-error
Browse files Browse the repository at this point in the history
Fix/span http error
  • Loading branch information
hamitb committed Aug 8, 2019
2 parents c61ba93 + 97b71f0 commit a44622c
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/Constants.ts
Expand Up @@ -80,6 +80,11 @@ export const envVariableKeys = {
THUNDRA_AGENT_COUNT_AWARE_SAMPLER_COUNT_FREQ: 'thundra_agent_lambda_sampler_countAware_countFreq',

THUNDRA_AWS_INSTRUMENT_ON_LOAD: 'thundra_agent_lambda_trace_integrations_aws_instrument_onLoad',

THUNDRA_AGENT_TRACE_INTEGRATION_HTTP_ERROR_ON_4XX:
'thundra_agent_trace_integrations_http_set_error_on_4xx_response_code_disable',
THUNDRA_AGENT_TRACE_INTEGRATION_HTTP_ERROR_ON_5XX:
'thundra_agent_trace_integrations_http_set_error_on_5xx_response_code_disable',
};

export function getTimeoutMargin(region: string) {
Expand Down
10 changes: 10 additions & 0 deletions src/plugins/config/TraceConfig.ts
Expand Up @@ -18,6 +18,8 @@ class TraceConfig extends BasePluginConfig {
maskResponse: (response: any) => any;
disabledIntegrations: IntegrationConfig[];
disableInstrumentation: boolean;
disableHttp4xxError: boolean;
disableHttp5xxError: boolean;
integrationsMap: Map<string, Integration>;
instrumenter: Instrumenter;
maskRedisStatement: boolean;
Expand Down Expand Up @@ -57,6 +59,14 @@ class TraceConfig extends BasePluginConfig {
envVariableKeys.THUNDRA_LAMBDA_TRACE_INSTRUMENT_DISABLE) ? Utils.getConfiguration(
envVariableKeys.THUNDRA_LAMBDA_TRACE_INSTRUMENT_DISABLE) === 'true' : options.disableInstrumentation;

this.disableHttp4xxError = Utils.getConfiguration(
envVariableKeys.THUNDRA_AGENT_TRACE_INTEGRATION_HTTP_ERROR_ON_4XX) ? Utils.getConfiguration(
envVariableKeys.THUNDRA_AGENT_TRACE_INTEGRATION_HTTP_ERROR_ON_4XX) === 'true' : options.disableHttp4xxError;

this.disableHttp5xxError = Utils.getConfiguration(
envVariableKeys.THUNDRA_AGENT_TRACE_INTEGRATION_HTTP_ERROR_ON_5XX) ? Utils.getConfiguration(
envVariableKeys.THUNDRA_AGENT_TRACE_INTEGRATION_HTTP_ERROR_ON_5XX) === 'true' : options.disableHttp5xxError;

this.maskRedisStatement = Utils.getConfiguration(
envVariableKeys.THUNDRA_MASK_REDIS_STATEMENT) ? Utils.getConfiguration(
envVariableKeys.THUNDRA_MASK_REDIS_STATEMENT) === 'true' : options.maskRedisStatement;
Expand Down
9 changes: 9 additions & 0 deletions src/plugins/integrations/HttpIntegration.ts
Expand Up @@ -9,6 +9,7 @@ import Utils from '../utils/Utils';
import * as url from 'url';
import ThundraLogger from '../../ThundraLogger';
import InvocationSupport from '../support/InvocationSupport';
import HttpError from '../error/HttpError';

const shimmer = require('shimmer');
const has = require('lodash.has');
Expand Down Expand Up @@ -61,6 +62,7 @@ class HttpIntegration implements Integration {
const libHTTPS = lib[1];
const nodeVersion = process.version;
const plugin = this;

function wrapper(request: any) {
return function requestWrapper(options: any, callback: any) {
try {
Expand Down Expand Up @@ -136,6 +138,13 @@ class HttpIntegration implements Integration {
const resourceName: string = res.headers[TriggerHeaderTags.RESOURCE_NAME];
span._setOperationName(resourceName);
}
const statusCode = res.statusCode.toString();
if (!config.disableHttp5xxError && statusCode.startsWith('5')) {
span.setErrorTag(new HttpError(res.statusMessage));
}
if (!config.disableHttp4xxError && statusCode.startsWith('4')) {
span.setErrorTag(new HttpError(res.statusMessage));
}
span.setTag(HttpTags.HTTP_STATUS, res.statusCode);
});

Expand Down
68 changes: 67 additions & 1 deletion test/integration/http.integration.test.js
Expand Up @@ -16,7 +16,7 @@ describe('HTTP integration', () => {
return Http.get(sdk).then(() => {
const span = tracer.getRecorder().spanList[0];

expect(span.operationName).toBe('jsonplaceholder.typicode.com/users/1')
expect(span.operationName).toBe('jsonplaceholder.typicode.com/users/1');
expect(span.className).toBe('HTTP');
expect(span.domainName).toBe('API');

Expand All @@ -35,6 +35,72 @@ describe('HTTP integration', () => {
});
});

test('should set 4XX 5XX errors on HTTP calls', () => {
const integration = new HttpIntegration({
httpPathDepth: 2,
});
const sdk = require('http');

const tracer = new ThundraTracer();
InvocationSupport.setFunctionName('functionName');

return Http.getError(sdk).then(() => {
const span = tracer.getRecorder().spanList[0];
expect(span.operationName).toBe('httpstat.us/404');
expect(span.className).toBe('HTTP');
expect(span.domainName).toBe('API');

expect(span.tags['operation.type']).toBe('GET');
expect(span.tags['http.method']).toBe('GET');
expect(span.tags['http.host']).toBe('httpstat.us');
expect(span.tags['http.path']).toBe('/404');
expect(span.tags['http.url']).toBe('httpstat.us/404');
expect(span.tags['http.status_code']).toBe(404);
expect(span.tags['error']).toBe(true);
expect(span.tags['error.kind']).toBe('HttpError');
expect(span.tags['error.message']).toBe('Not Found');
expect(span.tags['topology.vertex']).toEqual(true);
expect(span.tags['trigger.domainName']).toEqual('API');
expect(span.tags['trigger.className']).toEqual('AWS-Lambda');
expect(span.tags['trigger.operationNames']).toEqual(['functionName']);
expect(span.tags['http.body']).not.toBeTruthy();
});
});

test('should disable 4XX 5XX errors on HTTP calls', () => {
const integration = new HttpIntegration({
httpPathDepth: 2,
disableHttp4xxError:true

});
const sdk = require('http');

const tracer = new ThundraTracer();
InvocationSupport.setFunctionName('functionName');

return Http.getError(sdk).then(() => {
const span = tracer.getRecorder().spanList[0];
expect(span.operationName).toBe('httpstat.us/404');
expect(span.className).toBe('HTTP');
expect(span.domainName).toBe('API');

expect(span.tags['operation.type']).toBe('GET');
expect(span.tags['http.method']).toBe('GET');
expect(span.tags['http.host']).toBe('httpstat.us');
expect(span.tags['http.path']).toBe('/404');
expect(span.tags['http.url']).toBe('httpstat.us/404');
expect(span.tags['http.status_code']).toBe(404);
expect(span.tags['error']).toBe(undefined);
expect(span.tags['error.kind']).toBe(undefined);
expect(span.tags['error.message']).toBe(undefined);
expect(span.tags['topology.vertex']).toEqual(true);
expect(span.tags['trigger.domainName']).toEqual('API');
expect(span.tags['trigger.className']).toEqual('AWS-Lambda');
expect(span.tags['trigger.operationNames']).toEqual(['functionName']);
expect(span.tags['http.body']).not.toBeTruthy();
});
});

test('should instrument HTTPS POST calls', () => {
const integration = new HttpIntegration({
httpPathDepth: 0,
Expand Down
18 changes: 18 additions & 0 deletions test/integration/utils/http.integration.utils.js
Expand Up @@ -16,6 +16,24 @@ module.exports.get = (http) => {
});
};

module.exports.getError = (http) => {
return new Promise((resolve) => {
const url = 'http://httpstat.us/404';
http.get(url, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
resolve(data);
});
}).on('error', (err) => {
// We resolve with error.
resolve(err);
});
});
};

module.exports.post = (https) => {
return new Promise((resolve) => {
const data = JSON.stringify({
Expand Down

0 comments on commit a44622c

Please sign in to comment.