Skip to content

Commit 53dda64

Browse files
OlivierAlbertinidyladan
authored andcommitted
feat(plugin-http): sync. specs for statuscode (open-telemetry#719)
test: fix and add tests closes open-telemetry#642 Signed-off-by: Olivier Albertini <olivier.albertini@montreal.ca>
1 parent 69947da commit 53dda64

5 files changed

Lines changed: 79 additions & 34 deletions

File tree

packages/opentelemetry-plugin-http/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Http plugin has few options available to choose from. You can set the following:
5555
| [`ignoreIncomingPaths`](https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-plugin-http/src/types.ts#L28) | `IgnoreMatcher[]` | Http plugin will not trace all incoming requests that match paths |
5656
| [`ignoreOutgoingUrls`](https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-plugin-http/src/types.ts#L28) | `IgnoreMatcher[]` | Http plugin will not trace all outgoing requests that match urls |
5757
| [`serverName`](https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-plugin-http/src/types.ts#L28) | `string` | The primary server name of the matched virtual host. |
58+
5859
## Useful links
5960
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
6061
- For more about OpenTelemetry JavaScript: <https://github.com/open-telemetry/opentelemetry-js>

packages/opentelemetry-plugin-http/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,7 @@ export interface Err extends Error {
7878
syscall?: string;
7979
stack?: string;
8080
}
81+
82+
export interface SpecialHttpStatusCodeMapping {
83+
[custom: number]: number;
84+
}

packages/opentelemetry-plugin-http/src/utils.ts

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,30 @@ import {
2323
OutgoingHttpHeaders,
2424
ServerResponse,
2525
} from 'http';
26-
import { IgnoreMatcher, Err, ParsedRequestOptions } from './types';
26+
import {
27+
IgnoreMatcher,
28+
Err,
29+
ParsedRequestOptions,
30+
SpecialHttpStatusCodeMapping,
31+
} from './types';
2732
import { AttributeNames } from './enums/AttributeNames';
2833
import * as url from 'url';
2934
import { Socket } from 'net';
3035

3136
export const OT_REQUEST_HEADER = 'x-opentelemetry-outgoing-request';
37+
38+
export const HTTP_STATUS_SPECIAL_CASES: SpecialHttpStatusCodeMapping = {
39+
401: CanonicalCode.UNAUTHENTICATED,
40+
403: CanonicalCode.PERMISSION_DENIED,
41+
404: CanonicalCode.NOT_FOUND,
42+
429: CanonicalCode.RESOURCE_EXHAUSTED,
43+
501: CanonicalCode.UNIMPLEMENTED,
44+
503: CanonicalCode.UNAVAILABLE,
45+
504: CanonicalCode.DEADLINE_EXCEEDED,
46+
598: CanonicalCode.INTERNAL,
47+
599: CanonicalCode.INTERNAL,
48+
};
49+
3250
/**
3351
* Get an absolute url
3452
*/
@@ -58,37 +76,40 @@ export const getAbsoluteUrl = (
5876
return `${protocol}//${host}${path}`;
5977
};
6078
/**
61-
* Parse status code from HTTP response.
79+
* Parse status code from HTTP response. [More details](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-http.md#status)
6280
*/
6381
export const parseResponseStatus = (
6482
statusCode: number
6583
): Omit<Status, 'message'> => {
66-
if (statusCode < 200 || statusCode > 504) {
84+
// search for special case
85+
const code: number | undefined = HTTP_STATUS_SPECIAL_CASES[statusCode];
86+
87+
if (code !== undefined) {
88+
return { code };
89+
}
90+
91+
// 0xx are unknown
92+
if (statusCode < 100) {
6793
return { code: CanonicalCode.UNKNOWN };
68-
} else if (statusCode >= 200 && statusCode < 400) {
94+
}
95+
96+
// 1xx, 2xx, 3xx are OK
97+
if (statusCode < 400) {
6998
return { code: CanonicalCode.OK };
70-
} else {
71-
switch (statusCode) {
72-
case 400:
73-
return { code: CanonicalCode.INVALID_ARGUMENT };
74-
case 504:
75-
return { code: CanonicalCode.DEADLINE_EXCEEDED };
76-
case 404:
77-
return { code: CanonicalCode.NOT_FOUND };
78-
case 403:
79-
return { code: CanonicalCode.PERMISSION_DENIED };
80-
case 401:
81-
return { code: CanonicalCode.UNAUTHENTICATED };
82-
case 429:
83-
return { code: CanonicalCode.RESOURCE_EXHAUSTED };
84-
case 501:
85-
return { code: CanonicalCode.UNIMPLEMENTED };
86-
case 503:
87-
return { code: CanonicalCode.UNAVAILABLE };
88-
default:
89-
return { code: CanonicalCode.UNKNOWN };
90-
}
9199
}
100+
101+
// 4xx are client errors
102+
if (statusCode < 500) {
103+
return { code: CanonicalCode.INVALID_ARGUMENT };
104+
}
105+
106+
// 5xx are internal errors
107+
if (statusCode < 512) {
108+
return { code: CanonicalCode.INTERNAL };
109+
}
110+
111+
// All other codes are unknown
112+
return { code: CanonicalCode.UNKNOWN };
92113
};
93114

94115
/**

packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,19 @@ describe('HttpPlugin', () => {
280280
assert.strictEqual(spans.length, 0);
281281
});
282282

283-
const httpErrorCodes = [400, 401, 403, 404, 429, 501, 503, 504, 500, 505];
283+
const httpErrorCodes = [
284+
400,
285+
401,
286+
403,
287+
404,
288+
429,
289+
501,
290+
503,
291+
504,
292+
500,
293+
505,
294+
597,
295+
];
284296

285297
for (let i = 0; i < httpErrorCodes.length; i++) {
286298
it(`should test span for GET requests with http error ${httpErrorCodes[i]}`, async () => {

packages/opentelemetry-plugin-http/test/functionals/utils.test.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { NoopLogger } from '@opentelemetry/core';
18+
import { NoopScopeManager } from '@opentelemetry/scope-base';
19+
import { BasicTracerRegistry, Span } from '@opentelemetry/tracing';
20+
import { CanonicalCode, SpanKind } from '@opentelemetry/types';
1721
import * as assert from 'assert';
22+
import * as http from 'http';
1823
import * as sinon from 'sinon';
1924
import * as url from 'url';
20-
import { CanonicalCode, SpanKind } from '@opentelemetry/types';
21-
import { NoopScopeManager } from '@opentelemetry/scope-base';
25+
import { AttributeNames } from '../../src';
2226
import { IgnoreMatcher } from '../../src/types';
2327
import * as utils from '../../src/utils';
24-
import * as http from 'http';
25-
import { Span, BasicTracerRegistry } from '@opentelemetry/tracing';
26-
import { AttributeNames } from '../../src';
27-
import { NoopLogger } from '@opentelemetry/core';
2828

2929
describe('Utility', () => {
3030
describe('parseResponseStatus()', () => {
@@ -36,18 +36,25 @@ describe('Utility', () => {
3636
});
3737

3838
it('should return OK for Success HTTP status code', () => {
39-
for (let index = 200; index < 400; index++) {
39+
for (let index = 100; index < 400; index++) {
4040
const status = utils.parseResponseStatus(index);
4141
assert.deepStrictEqual(status, { code: CanonicalCode.OK });
4242
}
4343
});
4444

4545
it('should not return OK for Bad HTTP status code', () => {
46-
for (let index = 400; index <= 504; index++) {
46+
for (let index = 400; index <= 600; index++) {
4747
const status = utils.parseResponseStatus(index);
4848
assert.notStrictEqual(status.code, CanonicalCode.OK);
4949
}
5050
});
51+
it('should handle special HTTP status codes', () => {
52+
for (const key in utils.HTTP_STATUS_SPECIAL_CASES) {
53+
const status = utils.parseResponseStatus(key as any);
54+
const canonicalCode = utils.HTTP_STATUS_SPECIAL_CASES[key];
55+
assert.deepStrictEqual(status.code, canonicalCode);
56+
}
57+
});
5158
});
5259
describe('hasExpectHeader()', () => {
5360
it('should throw if no option', () => {

0 commit comments

Comments
 (0)