Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into safe_async
Browse files Browse the repository at this point in the history
obecny authored Jan 11, 2021
2 parents dfb2ef8 + a5ca32b commit a4ec0d1
Showing 9 changed files with 452 additions and 154 deletions.
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ LICENSE* text
## Non-text documentation
*.html text diff=html
*.pdf binary
*.json text
*.json text eol=lf
*.rtf binary

## Git Properties
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@
"lerna-changelog": "1.0.1",
"markdownlint-cli": "0.25.0",
"typescript": "3.9.7",
"update-ts-references": "^1.3.0"
"update-ts-references": "2.0.0"
},
"husky": {
"hooks": {
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ instrumentation.disable();
import * as http from 'http';
import { httpRequest } from '../utils/httpRequest';
import { DummyPropagation } from '../utils/DummyPropagation';
import { Socket } from 'net';

const protocol = 'http';
const serverPort = 32345;
@@ -56,6 +57,47 @@ const customAttributeFunction = (span: Span): void => {
};

describe('HttpInstrumentation Integration tests', () => {
let mockServerPort = 0;
let mockServer: http.Server;
const sockets: Array<Socket> = [];
before(done => {
mockServer = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('content-type', 'application/json');
res.write(
JSON.stringify({
success: true,
})
);
res.end();
});

mockServer.listen(0, () => {
const addr = mockServer.address();
if (addr == null) {
done(new Error('unexpected addr null'));
return;
}

if (typeof addr === 'string') {
done(new Error(`unexpected addr ${addr}`));
return;
}

if (addr.port <= 0) {
done(new Error('Could not get port'));
return;
}
mockServerPort = addr.port;
done();
});
});

after(done => {
sockets.forEach(s => s.destroy());
mockServer.close(done);
});

beforeEach(() => {
memoryExporter.reset();
context.setGlobalContextManager(new AsyncHooksContextManager().enable());
@@ -115,13 +157,14 @@ describe('HttpInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpRequest.get(
`${protocol}://google.fr/?query=test`
`${protocol}://localhost:${mockServerPort}/?query=test`
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -131,7 +174,7 @@ describe('HttpInstrumentation Integration tests', () => {
component: 'http',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -141,13 +184,14 @@ describe('HttpInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpRequest.get(
new url.URL(`${protocol}://google.fr/?query=test`)
new url.URL(`${protocol}://localhost:${mockServerPort}/?query=test`)
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -157,7 +201,7 @@ describe('HttpInstrumentation Integration tests', () => {
component: 'http',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -167,16 +211,17 @@ describe('HttpInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpRequest.get(
new url.URL(`${protocol}://google.fr/?query=test`),
new url.URL(`${protocol}://localhost:${mockServerPort}/?query=test`),
{
headers: { 'x-foo': 'foo' },
}
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -186,7 +231,7 @@ describe('HttpInstrumentation Integration tests', () => {
component: 'http',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.strictEqual(result.reqHeaders['x-foo'], 'foo');
assert.strictEqual(span.attributes[HttpAttribute.HTTP_FLAVOR], '1.1');
@@ -198,11 +243,14 @@ describe('HttpInstrumentation Integration tests', () => {
});

it('custom attributes should show up on client spans', async () => {
const result = await httpRequest.get(`${protocol}://google.fr/`);
const result = await httpRequest.get(
`${protocol}://localhost:${mockServerPort}/`
);
const spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -211,7 +259,7 @@ describe('HttpInstrumentation Integration tests', () => {
component: 'http',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.strictEqual(span.attributes['span kind'], SpanKind.CLIENT);
assertSpan(span, SpanKind.CLIENT, validations);
@@ -222,36 +270,30 @@ describe('HttpInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);
const options = Object.assign(
{ headers: { Expect: '100-continue' } },
url.parse(`${protocol}://google.fr/`)
url.parse(`${protocol}://localhost:${mockServerPort}/`)
);

const result = await httpRequest.get(options);
spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
httpStatusCode: 301,
hostname: 'localhost',
httpStatusCode: 200,
httpMethod: 'GET',
pathname: '/',
resHeaders: result.resHeaders,
reqHeaders: result.reqHeaders,
component: 'http',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');

try {
assertSpan(span, SpanKind.CLIENT, validations);
} catch (error) {
// temporary redirect is also correct
validations.httpStatusCode = 307;
assertSpan(span, SpanKind.CLIENT, validations);
}
assertSpan(span, SpanKind.CLIENT, validations);
});
for (const headers of [
{ Expect: '100-continue', 'user-agent': 'http-instrumentation-test' },
{ 'user-agent': 'http-instrumentation-test' },
{ Expect: '100-continue', 'user-agent': 'http-plugin-test' },
{ 'user-agent': 'http-plugin-test' },
]) {
it(`should create a span for GET requests and add propagation when using the following signature: get(url, options, callback) and following headers: ${JSON.stringify(
headers
@@ -269,7 +311,7 @@ describe('HttpInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);
const options = { headers };
const req = http.get(
`${protocol}://google.fr/`,
`${protocol}://localhost:${mockServerPort}/`,
options,
(resp: http.IncomingMessage) => {
const res = (resp as unknown) as http.IncomingMessage & {
@@ -281,7 +323,7 @@ describe('HttpInstrumentation Integration tests', () => {
});
resp.on('end', () => {
validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: 301,
httpMethod: 'GET',
pathname: '/',
@@ -298,8 +340,10 @@ describe('HttpInstrumentation Integration tests', () => {

req.on('close', () => {
const spans = memoryExporter.getFinishedSpans();
assert.strictEqual(spans.length, 1);
assert.strictEqual(spans[0].name, 'HTTP GET');
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.ok(data);
assert.ok(validations.reqHeaders[DummyPropagation.TRACE_CONTEXT_KEY]);
assert.ok(validations.reqHeaders[DummyPropagation.SPAN_CONTEXT_KEY]);
Original file line number Diff line number Diff line change
@@ -27,6 +27,9 @@ import {
} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import * as http from 'http';
import * as fs from 'fs';
import * as path from 'path';
import { Socket } from 'net';
import { assertSpan } from '../utils/assertSpan';
import * as url from 'url';
import * as utils from '../utils/utils';
@@ -57,6 +60,57 @@ export const customAttributeFunction = (span: Span): void => {
};

describe('HttpsInstrumentation Integration tests', () => {
let mockServerPort = 0;
let mockServer: https.Server;
const sockets: Array<Socket> = [];
before(done => {
mockServer = https.createServer(
{
key: fs.readFileSync(
path.join(__dirname, '..', 'fixtures', 'server-key.pem')
),
cert: fs.readFileSync(
path.join(__dirname, '..', 'fixtures', 'server-cert.pem')
),
},
(req, res) => {
res.statusCode = 200;
res.setHeader('content-type', 'application/json');
res.write(
JSON.stringify({
success: true,
})
);
res.end();
}
);

mockServer.listen(0, () => {
const addr = mockServer.address();
if (addr == null) {
done(new Error('unexpected addr null'));
return;
}

if (typeof addr === 'string') {
done(new Error(`unexpected addr ${addr}`));
return;
}

if (addr.port <= 0) {
done(new Error('Could not get port'));
return;
}
mockServerPort = addr.port;
done();
});
});

after(done => {
sockets.forEach(s => s.destroy());
mockServer.close(done);
});

beforeEach(() => {
memoryExporter.reset();
context.setGlobalContextManager(new AsyncHooksContextManager().enable());
@@ -116,13 +170,14 @@ describe('HttpsInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpsRequest.get(
`${protocol}://google.fr/?query=test`
`${protocol}://localhost:${mockServerPort}/?query=test`
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -132,7 +187,7 @@ describe('HttpsInstrumentation Integration tests', () => {
component: 'https',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTPS GET');
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -142,13 +197,14 @@ describe('HttpsInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpsRequest.get(
new url.URL(`${protocol}://google.fr/?query=test`)
new url.URL(`${protocol}://localhost:${mockServerPort}/?query=test`)
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -158,7 +214,7 @@ describe('HttpsInstrumentation Integration tests', () => {
component: 'https',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTPS GET');
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -168,14 +224,17 @@ describe('HttpsInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpsRequest.get(
new url.URL(`${protocol}://google.fr/?query=test`),
{ headers: { 'x-foo': 'foo' } }
new url.URL(`${protocol}://localhost:${mockServerPort}/?query=test`),
{
headers: { 'x-foo': 'foo' },
}
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -185,7 +244,7 @@ describe('HttpsInstrumentation Integration tests', () => {
component: 'https',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTPS GET');
assert.strictEqual(result.reqHeaders['x-foo'], 'foo');
assert.strictEqual(span.attributes[HttpAttribute.HTTP_FLAVOR], '1.1');
@@ -197,11 +256,14 @@ describe('HttpsInstrumentation Integration tests', () => {
});

it('custom attributes should show up on client spans', async () => {
const result = await httpsRequest.get(`${protocol}://google.fr/`);
const result = await httpsRequest.get(
`${protocol}://localhost:${mockServerPort}/`
);
const spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -210,7 +272,7 @@ describe('HttpsInstrumentation Integration tests', () => {
component: 'https',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTPS GET');
assert.strictEqual(span.attributes['span kind'], SpanKind.CLIENT);
assertSpan(span, SpanKind.CLIENT, validations);
@@ -221,36 +283,30 @@ describe('HttpsInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);
const options = Object.assign(
{ headers: { Expect: '100-continue' } },
url.parse(`${protocol}://google.fr/`)
url.parse(`${protocol}://localhost:${mockServerPort}/`)
);

const result = await httpsRequest.get(options);
spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
httpStatusCode: 301,
hostname: 'localhost',
httpStatusCode: 200,
httpMethod: 'GET',
pathname: '/',
resHeaders: result.resHeaders,
reqHeaders: result.reqHeaders,
component: 'https',
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTPS GET');

try {
assertSpan(span, SpanKind.CLIENT, validations);
} catch (error) {
// temporary redirect is also correct
validations.httpStatusCode = 307;
assertSpan(span, SpanKind.CLIENT, validations);
}
assertSpan(span, SpanKind.CLIENT, validations);
});
for (const headers of [
{ Expect: '100-continue', 'user-agent': 'https-instrumentation-test' },
{ 'user-agent': 'https-instrumentation-test' },
{ Expect: '100-continue', 'user-agent': 'http-plugin-test' },
{ 'user-agent': 'http-plugin-test' },
]) {
it(`should create a span for GET requests and add propagation when using the following signature: get(url, options, callback) and following headers: ${JSON.stringify(
headers
@@ -268,7 +324,7 @@ describe('HttpsInstrumentation Integration tests', () => {
assert.strictEqual(spans.length, 0);
const options = { headers };
const req = https.get(
`${protocol}://google.fr/`,
`${protocol}://localhost:${mockServerPort}/`,
options,
(resp: http.IncomingMessage) => {
const res = (resp as unknown) as http.IncomingMessage & {
@@ -280,7 +336,7 @@ describe('HttpsInstrumentation Integration tests', () => {
});
resp.on('end', () => {
validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: 301,
httpMethod: 'GET',
pathname: '/',
@@ -297,8 +353,10 @@ describe('HttpsInstrumentation Integration tests', () => {

req.on('close', () => {
const spans = memoryExporter.getFinishedSpans();
assert.strictEqual(spans.length, 1);
assert.strictEqual(spans[0].name, 'HTTPS GET');
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTPS GET');
assert.ok(data);
assert.ok(validations.reqHeaders[DummyPropagation.TRACE_CONTEXT_KEY]);
assert.ok(validations.reqHeaders[DummyPropagation.SPAN_CONTEXT_KEY]);
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ import * as assert from 'assert';
import axios, { AxiosResponse } from 'axios';
import * as got from 'got';
import * as http from 'http';
import { Socket } from 'net';
import * as nock from 'nock';
import * as path from 'path';
import * as request from 'request-promise-native';
@@ -40,6 +41,47 @@ const memoryExporter = new InMemorySpanExporter();
const protocol = 'http';

describe('Packages', () => {
let mockServerPort = 0;
let mockServer: http.Server;
const sockets: Array<Socket> = [];
before(done => {
mockServer = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('content-type', 'application/json');
res.write(
JSON.stringify({
success: true,
})
);
res.end();
});

mockServer.listen(0, () => {
const addr = mockServer.address();
if (addr == null) {
done(new Error('unexpected addr null'));
return;
}

if (typeof addr === 'string') {
done(new Error(`unexpected addr ${addr}`));
return;
}

if (addr.port <= 0) {
done(new Error('Could not get port'));
return;
}
mockServerPort = addr.port;
done();
});
});

after(done => {
sockets.forEach(s => s.destroy());
mockServer.close(done);
});

beforeEach(() => {
context.setGlobalContextManager(new AsyncHooksContextManager().enable());
});
@@ -92,15 +134,16 @@ describe('Packages', () => {
}

const urlparsed = url.parse(
`${protocol}://www.google.com/search?q=axios&oq=axios&aqs=chrome.0.69i59l2j0l3j69i60.811j0j7&sourceid=chrome&ie=UTF-8`
`${protocol}://localhost:${mockServerPort}/search?q=axios&oq=axios&aqs=chrome.0.69i59l2j0l3j69i60.811j0j7&sourceid=chrome&ie=UTF-8`
);
const result = await httpPackage.get(urlparsed.href!);
if (!resHeaders) {
const res = result as AxiosResponse<{}>;
resHeaders = res.headers;
}
const spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: urlparsed.hostname!,
httpStatusCode: 200,
@@ -111,7 +154,7 @@ describe('Packages', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');

switch (name) {
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ import {
} from '@opentelemetry/tracing';
import { HttpPluginConfig } from '../../src/types';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { Socket } from 'net';
const protocol = 'http';
const serverPort = 32345;
const hostname = 'localhost';
@@ -44,6 +45,47 @@ export const customAttributeFunction = (span: Span): void => {
};

describe('HttpPlugin Integration tests', () => {
let mockServerPort = 0;
let mockServer: http.Server;
const sockets: Array<Socket> = [];
before(done => {
mockServer = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('content-type', 'application/json');
res.write(
JSON.stringify({
success: true,
})
);
res.end();
});

mockServer.listen(0, () => {
const addr = mockServer.address();
if (addr == null) {
done(new Error('unexpected addr null'));
return;
}

if (typeof addr === 'string') {
done(new Error(`unexpected addr ${addr}`));
return;
}

if (addr.port <= 0) {
done(new Error('Could not get port'));
return;
}
mockServerPort = addr.port;
done();
});
});

after(done => {
sockets.forEach(s => s.destroy());
mockServer.close(done);
});

beforeEach(() => {
memoryExporter.reset();
context.setGlobalContextManager(new AsyncHooksContextManager().enable());
@@ -104,13 +146,14 @@ describe('HttpPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpRequest.get(
`${protocol}://google.fr/?query=test`
`${protocol}://localhost:${mockServerPort}/?query=test`
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -120,7 +163,7 @@ describe('HttpPlugin Integration tests', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -130,13 +173,14 @@ describe('HttpPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpRequest.get(
new url.URL(`${protocol}://google.fr/?query=test`)
new url.URL(`${protocol}://localhost:${mockServerPort}/?query=test`)
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -146,7 +190,7 @@ describe('HttpPlugin Integration tests', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -156,16 +200,17 @@ describe('HttpPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpRequest.get(
new url.URL(`${protocol}://google.fr/?query=test`),
new url.URL(`${protocol}://localhost:${mockServerPort}/?query=test`),
{
headers: { 'x-foo': 'foo' },
}
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -175,7 +220,7 @@ describe('HttpPlugin Integration tests', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.strictEqual(result.reqHeaders['x-foo'], 'foo');
assert.strictEqual(span.attributes[HttpAttribute.HTTP_FLAVOR], '1.1');
@@ -187,11 +232,14 @@ describe('HttpPlugin Integration tests', () => {
});

it('custom attributes should show up on client spans', async () => {
const result = await httpRequest.get(`${protocol}://google.fr/`);
const result = await httpRequest.get(
`${protocol}://localhost:${mockServerPort}/`
);
const spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -200,7 +248,7 @@ describe('HttpPlugin Integration tests', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.strictEqual(span.attributes['span kind'], SpanKind.CLIENT);
assertSpan(span, SpanKind.CLIENT, validations);
@@ -211,32 +259,26 @@ describe('HttpPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);
const options = Object.assign(
{ headers: { Expect: '100-continue' } },
url.parse(`${protocol}://google.fr/`)
url.parse(`${protocol}://localhost:${mockServerPort}/`)
);

const result = await httpRequest.get(options);
spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
httpStatusCode: 301,
hostname: 'localhost',
httpStatusCode: 200,
httpMethod: 'GET',
pathname: '/',
resHeaders: result.resHeaders,
reqHeaders: result.reqHeaders,
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');

try {
assertSpan(span, SpanKind.CLIENT, validations);
} catch (error) {
// temporary redirect is also correct
validations.httpStatusCode = 307;
assertSpan(span, SpanKind.CLIENT, validations);
}
assertSpan(span, SpanKind.CLIENT, validations);
});
for (const headers of [
{ Expect: '100-continue', 'user-agent': 'http-plugin-test' },
@@ -258,7 +300,7 @@ describe('HttpPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);
const options = { headers };
const req = http.get(
`${protocol}://google.fr/`,
`${protocol}://localhost:${mockServerPort}/`,
options,
(resp: http.IncomingMessage) => {
const res = (resp as unknown) as http.IncomingMessage & {
@@ -270,7 +312,7 @@ describe('HttpPlugin Integration tests', () => {
});
resp.on('end', () => {
validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: 301,
httpMethod: 'GET',
pathname: '/',
@@ -287,8 +329,10 @@ describe('HttpPlugin Integration tests', () => {

req.on('close', () => {
const spans = memoryExporter.getFinishedSpans();
assert.strictEqual(spans.length, 1);
assert.strictEqual(spans[0].name, 'HTTP GET');
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.ok(data);
assert.ok(validations.reqHeaders[DummyPropagation.TRACE_CONTEXT_KEY]);
assert.ok(validations.reqHeaders[DummyPropagation.SPAN_CONTEXT_KEY]);
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ import {
import * as assert from 'assert';
import axios, { AxiosResponse } from 'axios';
import * as got from 'got';
import * as fs from 'fs';
import * as http from 'http';
import * as https from 'https';
import * as nock from 'nock';
@@ -35,6 +36,7 @@ import * as url from 'url';
import { plugin } from '../../src/https';
import { assertSpan } from '../utils/assertSpan';
import { DummyPropagation } from '../utils/DummyPropagation';
import { Socket } from 'net';

const memoryExporter = new InMemorySpanExporter();

@@ -43,6 +45,57 @@ export const customAttributeFunction = (span: Span): void => {
};

describe('Packages', () => {
let mockServerPort = 0;
let mockServer: https.Server;
const sockets: Array<Socket> = [];
before(done => {
mockServer = https.createServer(
{
key: fs.readFileSync(
path.join(__dirname, '..', 'fixtures', 'server-key.pem')
),
cert: fs.readFileSync(
path.join(__dirname, '..', 'fixtures', 'server-cert.pem')
),
},
(req, res) => {
res.statusCode = 200;
res.setHeader('content-type', 'application/json');
res.write(
JSON.stringify({
success: true,
})
);
res.end();
}
);

mockServer.listen(0, () => {
const addr = mockServer.address();
if (addr == null) {
done(new Error('unexpected addr null'));
return;
}

if (typeof addr === 'string') {
done(new Error(`unexpected addr ${addr}`));
return;
}

if (addr.port <= 0) {
done(new Error('Could not get port'));
return;
}
mockServerPort = addr.port;
done();
});
});

after(done => {
sockets.forEach(s => s.destroy());
mockServer.close(done);
});

beforeEach(() => {
memoryExporter.reset();
context.setGlobalContextManager(new AsyncHooksContextManager().enable());
@@ -94,21 +147,16 @@ describe('Packages', () => {
}

const urlparsed = url.parse(
name === 'got' && process.versions.node.startsWith('12')
? // there is an issue with got 9.6 version and node 12 when redirecting so url above will not work
// https://github.com/nock/nock/pull/1551
// https://github.com/sindresorhus/got/commit/bf1aa5492ae2bc78cbbec6b7d764906fb156e6c2#diff-707a4781d57c42085155dcb27edb9ccbR258
// TODO: check if this is still the case when new version
'https://www.google.com'
: 'https://www.google.com/search?q=axios&oq=axios&aqs=chrome.0.69i59l2j0l3j69i60.811j0j7&sourceid=chrome&ie=UTF-8'
`https://localhost:${mockServerPort}/?query=test`
);
const result = await httpPackage.get(urlparsed.href!);
if (!resHeaders) {
const res = result as AxiosResponse<{}>;
resHeaders = res.headers;
}
const spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: urlparsed.hostname!,
httpStatusCode: 200,
@@ -119,7 +167,7 @@ describe('Packages', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');

switch (name) {
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@ import {
} from '@opentelemetry/semantic-conventions';
import * as assert from 'assert';
import * as http from 'http';
import * as fs from 'fs';
import * as path from 'path';
import * as https from 'https';
import { plugin } from '../../src/https';
import { assertSpan } from '../utils/assertSpan';
@@ -35,6 +37,7 @@ import {
SimpleSpanProcessor,
} from '@opentelemetry/tracing';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { Socket } from 'net';

const protocol = 'https';
const serverPort = 42345;
@@ -46,6 +49,57 @@ export const customAttributeFunction = (span: Span): void => {
};

describe('HttpsPlugin Integration tests', () => {
let mockServerPort = 0;
let mockServer: https.Server;
const sockets: Array<Socket> = [];
before(done => {
mockServer = https.createServer(
{
key: fs.readFileSync(
path.join(__dirname, '..', 'fixtures', 'server-key.pem')
),
cert: fs.readFileSync(
path.join(__dirname, '..', 'fixtures', 'server-cert.pem')
),
},
(req, res) => {
res.statusCode = 200;
res.setHeader('content-type', 'application/json');
res.write(
JSON.stringify({
success: true,
})
);
res.end();
}
);

mockServer.listen(0, () => {
const addr = mockServer.address();
if (addr == null) {
done(new Error('unexpected addr null'));
return;
}

if (typeof addr === 'string') {
done(new Error(`unexpected addr ${addr}`));
return;
}

if (addr.port <= 0) {
done(new Error('Could not get port'));
return;
}
mockServerPort = addr.port;
done();
});
});

after(done => {
sockets.forEach(s => s.destroy());
mockServer.close(done);
});

beforeEach(() => {
memoryExporter.reset();
context.setGlobalContextManager(new AsyncHooksContextManager().enable());
@@ -111,13 +165,14 @@ describe('HttpsPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpsRequest.get(
`${protocol}://google.fr/?query=test`
`${protocol}://localhost:${mockServerPort}/?query=test`
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -127,7 +182,7 @@ describe('HttpsPlugin Integration tests', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -137,13 +192,14 @@ describe('HttpsPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpsRequest.get(
new url.URL(`${protocol}://google.fr/?query=test`)
new url.URL(`${protocol}://localhost:${mockServerPort}/?query=test`)
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -153,7 +209,7 @@ describe('HttpsPlugin Integration tests', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assertSpan(span, SpanKind.CLIENT, validations);
});
@@ -163,14 +219,17 @@ describe('HttpsPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);

const result = await httpsRequest.get(
new url.URL(`${protocol}://google.fr/?query=test`),
{ headers: { 'x-foo': 'foo' } }
new url.URL(`${protocol}://localhost:${mockServerPort}/?query=test`),
{
headers: { 'x-foo': 'foo' },
}
);

spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -180,7 +239,7 @@ describe('HttpsPlugin Integration tests', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.strictEqual(result.reqHeaders['x-foo'], 'foo');
assert.strictEqual(span.attributes[HttpAttribute.HTTP_FLAVOR], '1.1');
@@ -192,11 +251,14 @@ describe('HttpsPlugin Integration tests', () => {
});

it('custom attributes should show up on client spans', async () => {
const result = await httpsRequest.get(`${protocol}://google.fr/`);
const result = await httpsRequest.get(
`${protocol}://localhost:${mockServerPort}/`
);
const spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: result.statusCode!,
httpMethod: 'GET',
pathname: '/',
@@ -205,7 +267,7 @@ describe('HttpsPlugin Integration tests', () => {
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.strictEqual(span.attributes['span kind'], SpanKind.CLIENT);
assertSpan(span, SpanKind.CLIENT, validations);
@@ -216,36 +278,30 @@ describe('HttpsPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);
const options = Object.assign(
{ headers: { Expect: '100-continue' } },
url.parse(`${protocol}://google.fr/`)
url.parse(`${protocol}://localhost:${mockServerPort}/`)
);

const result = await httpsRequest.get(options);
spans = memoryExporter.getFinishedSpans();
const span = spans[0];
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
const validations = {
hostname: 'google.fr',
httpStatusCode: 301,
hostname: 'localhost',
httpStatusCode: 200,
httpMethod: 'GET',
pathname: '/',
resHeaders: result.resHeaders,
reqHeaders: result.reqHeaders,
component: plugin.component,
};

assert.strictEqual(spans.length, 1);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');

try {
assertSpan(span, SpanKind.CLIENT, validations);
} catch (error) {
// temporary redirect is also correct
validations.httpStatusCode = 307;
assertSpan(span, SpanKind.CLIENT, validations);
}
assertSpan(span, SpanKind.CLIENT, validations);
});
for (const headers of [
{ Expect: '100-continue', 'user-agent': 'https-plugin-test' },
{ 'user-agent': 'https-plugin-test' },
{ Expect: '100-continue', 'user-agent': 'http-plugin-test' },
{ 'user-agent': 'http-plugin-test' },
]) {
it(`should create a span for GET requests and add propagation when using the following signature: get(url, options, callback) and following headers: ${JSON.stringify(
headers
@@ -263,7 +319,7 @@ describe('HttpsPlugin Integration tests', () => {
assert.strictEqual(spans.length, 0);
const options = { headers };
const req = https.get(
`${protocol}://google.fr/`,
`${protocol}://localhost:${mockServerPort}/`,
options,
(resp: http.IncomingMessage) => {
const res = (resp as unknown) as http.IncomingMessage & {
@@ -275,7 +331,7 @@ describe('HttpsPlugin Integration tests', () => {
});
resp.on('end', () => {
validations = {
hostname: 'google.fr',
hostname: 'localhost',
httpStatusCode: 301,
httpMethod: 'GET',
pathname: '/',
@@ -292,8 +348,10 @@ describe('HttpsPlugin Integration tests', () => {

req.on('close', () => {
const spans = memoryExporter.getFinishedSpans();
assert.strictEqual(spans.length, 1);
assert.strictEqual(spans[0].name, 'HTTP GET');
const span = spans.find(s => s.kind === SpanKind.CLIENT);
assert.ok(span);
assert.strictEqual(spans.length, 2);
assert.strictEqual(span.name, 'HTTP GET');
assert.ok(data);
assert.ok(validations.reqHeaders[DummyPropagation.TRACE_CONTEXT_KEY]);
assert.ok(validations.reqHeaders[DummyPropagation.SPAN_CONTEXT_KEY]);
3 changes: 3 additions & 0 deletions packages/opentelemetry-resource-detector-gcp/tsconfig.json
Original file line number Diff line number Diff line change
@@ -9,6 +9,9 @@
"test/**/*.ts"
],
"references": [
{
"path": "../opentelemetry-api"
},
{
"path": "../opentelemetry-core"
},

0 comments on commit a4ec0d1

Please sign in to comment.