chore: use local server for http integration tests (#1808)

This commit is contained in:
Daniel Dyla 2021-01-11 14:08:31 -05:00 committed by GitHub
parent 89664a7c4e
commit f2dcec6b17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 447 additions and 152 deletions

View File

@ -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,15 +270,16 @@ 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,
@ -238,20 +287,13 @@ describe('HttpInstrumentation Integration tests', () => {
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]);

View File

@ -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,15 +283,16 @@ 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,
@ -237,20 +300,13 @@ describe('HttpsInstrumentation Integration tests', () => {
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]);

View File

@ -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,7 +134,7 @@ 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) {
@ -100,7 +142,8 @@ describe('Packages', () => {
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) {

View File

@ -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,15 +259,16 @@ 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,
@ -227,16 +276,9 @@ describe('HttpPlugin Integration tests', () => {
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]);

View File

@ -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,13 +147,7 @@ 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) {
@ -108,7 +155,8 @@ describe('Packages', () => {
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) {

View File

@ -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,15 +278,16 @@ 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,
@ -232,20 +295,13 @@ describe('HttpsPlugin Integration tests', () => {
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]);