Skip to content

Commit 622955a

Browse files
authored
feat(opencensus-shim) add require-in-the-middle hook to patch @opencensus/core (#3809)
1 parent a8ac8ba commit 622955a

File tree

7 files changed

+167
-12
lines changed

7 files changed

+167
-12
lines changed

experimental/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ All notable changes to experimental packages in this project will be documented
1717
* feat(exporter-logs-otlp-http): otlp-http exporter for logs. [#3764](https://github.com/open-telemetry/opentelemetry-js/pull/3764/) @fuaiyi
1818
* feat(otlp-trace-exporters): Add User-Agent header to OTLP trace exporters. [#3790](https://github.com/open-telemetry/opentelemetry-js/pull/3790) @JamieDanielson
1919
* feat(otlp-metric-exporters): Add User-Agent header to OTLP metric exporters. [#3806](https://github.com/open-telemetry/opentelemetry-js/pull/3806) @JamieDanielson
20+
* feat(opencensus-shim): add OpenCensus trace shim [#3809](https://github.com/open-telemetry/opentelemetry-js/pull/3809) @aabmass
2021

2122
### :bug: (Bug Fix)
2223

experimental/packages/shim-opencensus/README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
[![NPM Published Version][npm-img]][npm-url]
44
[![Apache License][license-image]][license-image]
55

6-
> **Note**
7-
> This package is in active development and has not yet been released. You cannot install this
8-
> package from NPM yet.
9-
106
OpenCensus shim allows existing OpenCensus instrumentation to report to OpenTelemetry. This
117
allows you to incrementally migrate your existing OpenCensus instrumentation to OpenTelemetry.
128
More details are available in the [OpenCensus Compatibility Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/compatibility/opencensus.md).

experimental/packages/shim-opencensus/package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"name": "@opentelemetry/shim-opencensus",
33
"version": "0.39.1",
44
"description": "OpenCensus to OpenTelemetry shim",
5-
"private": true,
65
"main": "build/src/index.js",
76
"types": "build/src/index.d.ts",
87
"repository": "open-telemetry/opentelemetry-js",
@@ -45,7 +44,6 @@
4544
"access": "public"
4645
},
4746
"devDependencies": {
48-
"@opentelemetry/core": "1.13.0",
4947
"@opentelemetry/context-async-hooks": "1.13.0",
5048
"@opentelemetry/sdk-trace-base": "1.13.0",
5149
"@opencensus/core": "0.1.0",
@@ -65,7 +63,6 @@
6563
"@opentelemetry/api": "^1.0.0"
6664
},
6765
"dependencies": {
68-
"@opentelemetry/context-async-hooks": "1.13.0",
6966
"@opentelemetry/core": "1.13.0",
7067
"require-in-the-middle": "^7.0.0",
7168
"semver": "^7.3.5"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright The 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 { installShim } from './shim';
18+
19+
installShim();
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright The 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 { diag, trace, Tracer } from '@opentelemetry/api';
18+
import { Hook } from 'require-in-the-middle';
19+
import * as oc from '@opencensus/core';
20+
21+
import { ShimTracer } from './ShimTracer';
22+
import { VERSION } from './version';
23+
24+
type CoreTracerConstructor = new (
25+
...args: ConstructorParameters<typeof oc.CoreTracer>
26+
) => oc.Tracer;
27+
28+
let hook: Hook | null = null;
29+
30+
interface OpenCensusShimConfig {
31+
/**
32+
* An optional OpenTelemetry tracer to send OpenCensus spans to. If not provided, one will be
33+
* created for you.
34+
*/
35+
tracer?: Tracer | undefined;
36+
}
37+
38+
/**
39+
* Patches OpenCensus to redirect all instrumentation to OpenTelemetry. Uses
40+
* require-in-the-middle to override the implementation of OpenCensus's CoreTracer.
41+
*
42+
* Use {@link uninstallShim} to undo the effects of this function.
43+
*
44+
* @param config
45+
*/
46+
export function installShim({
47+
tracer = trace.getTracer('@opentelemetry/shim-opencensus', VERSION),
48+
}: OpenCensusShimConfig = {}): void {
49+
diag.info('Installing OpenCensus shim require-in-the-middle hook');
50+
51+
hook = new Hook(['@opencensus/core'], exports => {
52+
const CoreTracer: CoreTracerConstructor = ShimTracer.bind(null, tracer);
53+
return {
54+
...exports,
55+
CoreTracer,
56+
};
57+
});
58+
}
59+
60+
export function uninstallShim(): void {
61+
hook?.unhook();
62+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright The 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 { installShim, uninstallShim } from '../src/shim';
19+
import { ShimTracer } from '../src';
20+
import { CoreTracer as OrigCoreTracer } from '@opencensus/core';
21+
import { withTestTracerProvider } from './util';
22+
import { trace } from '@opentelemetry/api';
23+
24+
describe('shim', () => {
25+
beforeEach(uninstallShim);
26+
afterEach(uninstallShim);
27+
afterEach(() => {
28+
trace.disable();
29+
});
30+
31+
describe('installShim', () => {
32+
it('should patch the @opencensus/core CoreTracer to create instances of the ShimTracer', () => {
33+
installShim();
34+
const { CoreTracer } = require('@opencensus/core');
35+
assert.notStrictEqual(CoreTracer, OrigCoreTracer);
36+
assert(new CoreTracer() instanceof ShimTracer);
37+
});
38+
39+
it('should use the provided Tracer', async () => {
40+
const spans = await withTestTracerProvider(tracerProvider => {
41+
const tracer = tracerProvider.getTracer('test');
42+
installShim({ tracer });
43+
const CoreTracer: typeof OrigCoreTracer =
44+
require('@opencensus/core').CoreTracer;
45+
const coreTracer = new CoreTracer();
46+
coreTracer.startChildSpan().end();
47+
});
48+
assert.strictEqual(spans.length, 1);
49+
});
50+
51+
it('should use the global OpenTelemetry TracerProvider if none provided', async () => {
52+
installShim();
53+
const spans = await withTestTracerProvider(tracerProvider => {
54+
trace.setGlobalTracerProvider(tracerProvider);
55+
const CoreTracer: typeof OrigCoreTracer =
56+
require('@opencensus/core').CoreTracer;
57+
const coreTracer = new CoreTracer();
58+
coreTracer.startChildSpan().end();
59+
});
60+
assert.strictEqual(spans.length, 1);
61+
});
62+
});
63+
64+
describe('uninstallShim', () => {
65+
it('should restore the original CoreTracer', () => {
66+
installShim();
67+
uninstallShim();
68+
const { CoreTracer } = require('@opencensus/core');
69+
assert.strictEqual(CoreTracer, OrigCoreTracer);
70+
});
71+
});
72+
});

experimental/packages/shim-opencensus/test/util.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,29 @@ import {
2727
AsyncHooksContextManager,
2828
AsyncLocalStorageContextManager,
2929
} from '@opentelemetry/context-async-hooks';
30-
import { Tracer, context } from '@opentelemetry/api';
30+
import { Tracer, TracerProvider, context } from '@opentelemetry/api';
3131

3232
export async function withTestTracer(
3333
func: (shimTracer: ShimTracer, otelTracer: Tracer) => void | Promise<void>
34+
): Promise<ReadableSpan[]> {
35+
return await withTestTracerProvider(tracerProvider =>
36+
func(
37+
new ShimTracer(tracerProvider.getTracer('test-shim')),
38+
tracerProvider.getTracer('test-otel')
39+
)
40+
);
41+
}
42+
43+
export async function withTestTracerProvider(
44+
func: (otelTracerProvider: TracerProvider) => void | Promise<void>
3445
): Promise<ReadableSpan[]> {
3546
const tracerProvider = new BasicTracerProvider({
3647
sampler: new AlwaysOnSampler(),
3748
});
3849
const inMemExporter = new InMemorySpanExporter();
3950
tracerProvider.addSpanProcessor(new SimpleSpanProcessor(inMemExporter));
4051

41-
await func(
42-
new ShimTracer(tracerProvider.getTracer('test-shim')),
43-
tracerProvider.getTracer('test-otel')
44-
);
52+
await func(tracerProvider);
4553

4654
await tracerProvider.forceFlush();
4755
const spans = inMemExporter.getFinishedSpans();

0 commit comments

Comments
 (0)