Skip to content

Commit a15ccb9

Browse files
authored
feat: node-tracer initial implementation (open-telemetry#140)
* feat: node-tracer initial implementation * fix: config order * fix: build pipeline
1 parent 807a56d commit a15ccb9

File tree

4 files changed

+220
-0
lines changed

4 files changed

+220
-0
lines changed

packages/opentelemetry-basic-tracer/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
*/
1616

1717
export * from './types';
18+
export * from './BasicTracer';
1819
export * from './Span';

packages/opentelemetry-node-tracer/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"scripts": {
99
"test": "c8 ts-mocha -p tsconfig.json test/**/*.ts",
1010
"tdd": "yarn test -- --watch-extensions ts --watch",
11+
"codecov": "c8 report --reporter=json && codecov -f coverage/*.json -p ../../",
1112
"clean": "rimraf build/*",
1213
"check": "gts check",
1314
"compile": "tsc -p .",
@@ -49,6 +50,7 @@
4950
"typescript": "^3.4.5"
5051
},
5152
"dependencies": {
53+
"@opentelemetry/basic-tracer": "^0.0.1",
5254
"@opentelemetry/core": "^0.0.1",
5355
"@opentelemetry/scope-async-hooks": "^0.0.1",
5456
"@opentelemetry/scope-base": "^0.0.1",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Copyright 2019, OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { BasicTracer, BasicTracerConfig } from '@opentelemetry/basic-tracer';
18+
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
19+
20+
/**
21+
* This class represents a node tracer with `async_hooks` module.
22+
*/
23+
export class NodeTracer extends BasicTracer {
24+
/**
25+
* Constructs a new Tracer instance.
26+
*/
27+
constructor(config: BasicTracerConfig) {
28+
super(
29+
Object.assign({}, { scopeManager: new AsyncHooksScopeManager() }, config)
30+
);
31+
32+
// @todo: Integrate Plugin Loader (pull/126).
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/**
2+
* Copyright 2019, OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as assert from 'assert';
18+
import {
19+
ALWAYS_SAMPLER,
20+
BinaryTraceContext,
21+
HttpTraceContext,
22+
NEVER_SAMPLER,
23+
NoopLogger,
24+
NOOP_SPAN,
25+
} from '@opentelemetry/core';
26+
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
27+
import { NodeTracer } from '../src/NodeTracer';
28+
29+
describe('NodeTracer', () => {
30+
describe('constructor', () => {
31+
it('should construct an instance with required only options', () => {
32+
const tracer = new NodeTracer({
33+
scopeManager: new AsyncHooksScopeManager(),
34+
});
35+
assert.ok(tracer instanceof NodeTracer);
36+
});
37+
38+
it('should construct an instance with binary format', () => {
39+
const tracer = new NodeTracer({
40+
binaryFormat: new BinaryTraceContext(),
41+
scopeManager: new AsyncHooksScopeManager(),
42+
});
43+
assert.ok(tracer instanceof NodeTracer);
44+
});
45+
46+
it('should construct an instance with http text format', () => {
47+
const tracer = new NodeTracer({
48+
httpTextFormat: new HttpTraceContext(),
49+
scopeManager: new AsyncHooksScopeManager(),
50+
});
51+
assert.ok(tracer instanceof NodeTracer);
52+
});
53+
54+
it('should construct an instance with logger', () => {
55+
const tracer = new NodeTracer({
56+
logger: new NoopLogger(),
57+
scopeManager: new AsyncHooksScopeManager(),
58+
});
59+
assert.ok(tracer instanceof NodeTracer);
60+
});
61+
62+
it('should construct an instance with sampler', () => {
63+
const tracer = new NodeTracer({
64+
scopeManager: new AsyncHooksScopeManager(),
65+
sampler: ALWAYS_SAMPLER,
66+
});
67+
assert.ok(tracer instanceof NodeTracer);
68+
});
69+
70+
it('should construct an instance with default attributes', () => {
71+
const tracer = new NodeTracer({
72+
defaultAttributes: {
73+
region: 'eu-west',
74+
asg: 'my-asg',
75+
},
76+
scopeManager: new AsyncHooksScopeManager(),
77+
});
78+
assert.ok(tracer instanceof NodeTracer);
79+
});
80+
});
81+
82+
describe('.startSpan()', () => {
83+
it('should start a span with name only', () => {
84+
const tracer = new NodeTracer({
85+
scopeManager: new AsyncHooksScopeManager(),
86+
});
87+
const span = tracer.startSpan('my-span');
88+
assert.ok(span);
89+
});
90+
91+
it('should start a span with name and options', () => {
92+
const tracer = new NodeTracer({
93+
scopeManager: new AsyncHooksScopeManager(),
94+
});
95+
const span = tracer.startSpan('my-span', {});
96+
assert.ok(span);
97+
});
98+
99+
it('should return a default span with no sampling', () => {
100+
const tracer = new NodeTracer({
101+
sampler: NEVER_SAMPLER,
102+
scopeManager: new AsyncHooksScopeManager(),
103+
});
104+
const span = tracer.startSpan('my-span');
105+
assert.deepStrictEqual(span, NOOP_SPAN);
106+
});
107+
108+
// @todo: implement
109+
it('should start a Span with always sampling');
110+
111+
// @todo: implement
112+
it('should set default attributes on span');
113+
});
114+
115+
describe('.getCurrentSpan()', () => {
116+
it('should return null with AsyncHooksScopeManager when no span started', () => {
117+
const tracer = new NodeTracer({
118+
scopeManager: new AsyncHooksScopeManager(),
119+
});
120+
assert.deepStrictEqual(tracer.getCurrentSpan(), null);
121+
});
122+
});
123+
124+
describe('.withSpan()', () => {
125+
it('should run scope with AsyncHooksScopeManager scope manager', done => {
126+
const tracer = new NodeTracer({
127+
scopeManager: new AsyncHooksScopeManager(),
128+
});
129+
const span = tracer.startSpan('my-span');
130+
tracer.withSpan(span, () => {
131+
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
132+
return done();
133+
});
134+
assert.deepStrictEqual(tracer.getCurrentSpan(), null);
135+
});
136+
137+
it('should run scope with AsyncHooksScopeManager scope manager with multiple spans', done => {
138+
const tracer = new NodeTracer({
139+
scopeManager: new AsyncHooksScopeManager(),
140+
});
141+
const span = tracer.startSpan('my-span');
142+
tracer.withSpan(span, () => {
143+
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
144+
145+
const span1 = tracer.startSpan('my-span1', { parent: span });
146+
tracer.withSpan(span1, () => {
147+
assert.deepStrictEqual(tracer.getCurrentSpan(), span1);
148+
assert.deepStrictEqual(
149+
span1.context().traceId,
150+
span.context().traceId
151+
);
152+
return done();
153+
});
154+
});
155+
// when span ended.
156+
// @todo: below check is not running.
157+
assert.deepStrictEqual(tracer.getCurrentSpan(), null);
158+
});
159+
});
160+
161+
describe('.recordSpanData()', () => {
162+
// @todo: implement
163+
it('should call exporters with span data');
164+
});
165+
166+
describe('getBinaryFormat', () => {
167+
it('should get default binary formatter', () => {
168+
const tracer = new NodeTracer({
169+
scopeManager: new AsyncHooksScopeManager(),
170+
});
171+
assert.ok(tracer.getBinaryFormat() instanceof BinaryTraceContext);
172+
});
173+
});
174+
175+
describe('.getHttpTextFormat()', () => {
176+
it('should get default HTTP text formatter', () => {
177+
const tracer = new NodeTracer({
178+
scopeManager: new AsyncHooksScopeManager(),
179+
});
180+
assert.ok(tracer.getHttpTextFormat() instanceof HttpTraceContext);
181+
});
182+
});
183+
});

0 commit comments

Comments
 (0)