Skip to content

Commit

Permalink
feat(opencensus-shim) add require-in-the-middle hook to patch @opence…
Browse files Browse the repository at this point in the history
…nsus/core (#3809)
  • Loading branch information
aabmass authored May 31, 2023
1 parent a8ac8ba commit 622955a
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 12 deletions.
1 change: 1 addition & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ All notable changes to experimental packages in this project will be documented
* feat(exporter-logs-otlp-http): otlp-http exporter for logs. [#3764](https://github.com/open-telemetry/opentelemetry-js/pull/3764/) @fuaiyi
* feat(otlp-trace-exporters): Add User-Agent header to OTLP trace exporters. [#3790](https://github.com/open-telemetry/opentelemetry-js/pull/3790) @JamieDanielson
* feat(otlp-metric-exporters): Add User-Agent header to OTLP metric exporters. [#3806](https://github.com/open-telemetry/opentelemetry-js/pull/3806) @JamieDanielson
* feat(opencensus-shim): add OpenCensus trace shim [#3809](https://github.com/open-telemetry/opentelemetry-js/pull/3809) @aabmass

### :bug: (Bug Fix)

Expand Down
4 changes: 0 additions & 4 deletions experimental/packages/shim-opencensus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
[![NPM Published Version][npm-img]][npm-url]
[![Apache License][license-image]][license-image]

> **Note**
> This package is in active development and has not yet been released. You cannot install this
> package from NPM yet.
OpenCensus shim allows existing OpenCensus instrumentation to report to OpenTelemetry. This
allows you to incrementally migrate your existing OpenCensus instrumentation to OpenTelemetry.
More details are available in the [OpenCensus Compatibility Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/compatibility/opencensus.md).
Expand Down
3 changes: 0 additions & 3 deletions experimental/packages/shim-opencensus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "@opentelemetry/shim-opencensus",
"version": "0.39.1",
"description": "OpenCensus to OpenTelemetry shim",
"private": true,
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js",
Expand Down Expand Up @@ -45,7 +44,6 @@
"access": "public"
},
"devDependencies": {
"@opentelemetry/core": "1.13.0",
"@opentelemetry/context-async-hooks": "1.13.0",
"@opentelemetry/sdk-trace-base": "1.13.0",
"@opencensus/core": "0.1.0",
Expand All @@ -65,7 +63,6 @@
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
"@opentelemetry/context-async-hooks": "1.13.0",
"@opentelemetry/core": "1.13.0",
"require-in-the-middle": "^7.0.0",
"semver": "^7.3.5"
Expand Down
19 changes: 19 additions & 0 deletions experimental/packages/shim-opencensus/src/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { installShim } from './shim';

installShim();
62 changes: 62 additions & 0 deletions experimental/packages/shim-opencensus/src/shim.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { diag, trace, Tracer } from '@opentelemetry/api';
import { Hook } from 'require-in-the-middle';
import * as oc from '@opencensus/core';

import { ShimTracer } from './ShimTracer';
import { VERSION } from './version';

type CoreTracerConstructor = new (
...args: ConstructorParameters<typeof oc.CoreTracer>
) => oc.Tracer;

let hook: Hook | null = null;

interface OpenCensusShimConfig {
/**
* An optional OpenTelemetry tracer to send OpenCensus spans to. If not provided, one will be
* created for you.
*/
tracer?: Tracer | undefined;
}

/**
* Patches OpenCensus to redirect all instrumentation to OpenTelemetry. Uses
* require-in-the-middle to override the implementation of OpenCensus's CoreTracer.
*
* Use {@link uninstallShim} to undo the effects of this function.
*
* @param config
*/
export function installShim({
tracer = trace.getTracer('@opentelemetry/shim-opencensus', VERSION),
}: OpenCensusShimConfig = {}): void {
diag.info('Installing OpenCensus shim require-in-the-middle hook');

hook = new Hook(['@opencensus/core'], exports => {
const CoreTracer: CoreTracerConstructor = ShimTracer.bind(null, tracer);
return {
...exports,
CoreTracer,
};
});
}

export function uninstallShim(): void {
hook?.unhook();
}
72 changes: 72 additions & 0 deletions experimental/packages/shim-opencensus/test/shim.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as assert from 'assert';
import { installShim, uninstallShim } from '../src/shim';
import { ShimTracer } from '../src';
import { CoreTracer as OrigCoreTracer } from '@opencensus/core';
import { withTestTracerProvider } from './util';
import { trace } from '@opentelemetry/api';

describe('shim', () => {
beforeEach(uninstallShim);
afterEach(uninstallShim);
afterEach(() => {
trace.disable();
});

describe('installShim', () => {
it('should patch the @opencensus/core CoreTracer to create instances of the ShimTracer', () => {
installShim();
const { CoreTracer } = require('@opencensus/core');
assert.notStrictEqual(CoreTracer, OrigCoreTracer);
assert(new CoreTracer() instanceof ShimTracer);
});

it('should use the provided Tracer', async () => {
const spans = await withTestTracerProvider(tracerProvider => {
const tracer = tracerProvider.getTracer('test');
installShim({ tracer });
const CoreTracer: typeof OrigCoreTracer =
require('@opencensus/core').CoreTracer;
const coreTracer = new CoreTracer();
coreTracer.startChildSpan().end();
});
assert.strictEqual(spans.length, 1);
});

it('should use the global OpenTelemetry TracerProvider if none provided', async () => {
installShim();
const spans = await withTestTracerProvider(tracerProvider => {
trace.setGlobalTracerProvider(tracerProvider);
const CoreTracer: typeof OrigCoreTracer =
require('@opencensus/core').CoreTracer;
const coreTracer = new CoreTracer();
coreTracer.startChildSpan().end();
});
assert.strictEqual(spans.length, 1);
});
});

describe('uninstallShim', () => {
it('should restore the original CoreTracer', () => {
installShim();
uninstallShim();
const { CoreTracer } = require('@opencensus/core');
assert.strictEqual(CoreTracer, OrigCoreTracer);
});
});
});
18 changes: 13 additions & 5 deletions experimental/packages/shim-opencensus/test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,29 @@ import {
AsyncHooksContextManager,
AsyncLocalStorageContextManager,
} from '@opentelemetry/context-async-hooks';
import { Tracer, context } from '@opentelemetry/api';
import { Tracer, TracerProvider, context } from '@opentelemetry/api';

export async function withTestTracer(
func: (shimTracer: ShimTracer, otelTracer: Tracer) => void | Promise<void>
): Promise<ReadableSpan[]> {
return await withTestTracerProvider(tracerProvider =>
func(
new ShimTracer(tracerProvider.getTracer('test-shim')),
tracerProvider.getTracer('test-otel')
)
);
}

export async function withTestTracerProvider(
func: (otelTracerProvider: TracerProvider) => void | Promise<void>
): Promise<ReadableSpan[]> {
const tracerProvider = new BasicTracerProvider({
sampler: new AlwaysOnSampler(),
});
const inMemExporter = new InMemorySpanExporter();
tracerProvider.addSpanProcessor(new SimpleSpanProcessor(inMemExporter));

await func(
new ShimTracer(tracerProvider.getTracer('test-shim')),
tracerProvider.getTracer('test-otel')
);
await func(tracerProvider);

await tracerProvider.forceFlush();
const spans = inMemExporter.getFinishedSpans();
Expand Down

0 comments on commit 622955a

Please sign in to comment.