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
  • Loading branch information
aabmass committed May 17, 2023
1 parent 68eba71 commit cf2cf58
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 9 deletions.
7 changes: 3 additions & 4 deletions experimental/packages/shim-opencensus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,9 @@
"@opentelemetry/api": "^1.0.0"
},
"dependencies": {
"@opentelemetry/context-async-hooks": "1.13.0",
"@opentelemetry/core": "1.13.0",
"require-in-the-middle": "^6.0.0",
"semver": "^7.3.5"
"@opentelemetry/core": "^1.0.0",
"semver": "^7.3.5",
"require-in-the-middle": "^7.1.0"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/shim-opencensus",
"sideEffects": false
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 cf2cf58

Please sign in to comment.