diff --git a/experimental/examples/opencensus-shim/README.md b/experimental/examples/opencensus-shim/README.md
new file mode 100644
index 0000000000..0738d67d89
--- /dev/null
+++ b/experimental/examples/opencensus-shim/README.md
@@ -0,0 +1,75 @@
+# Overview
+
+The OpenCensus shim allows existing OpenCensus instrumentation to interoperate with OpenTelemetry instrumentation by using the OpenTelemetry SDK as an implementation for OpenCensus.
+
+This is a simple example that demonstrates how existing OpenCensus instrumentation can be integrated with OpenTelemetry.
+
+The example has:
+
+- Root Spans (on client), instrumented with OpenCensus's HTTP instrumentation
+- Child Span from a remote parent (on server), instrumented with OpenCensus's HTTP instrumentation
+- Another Child Span created in the server representing some work being done, instrumented manually with OpenTelemetry.
+
+## Installation
+
+```sh
+# from this directory
+$ npm install
+```
+
+## Run the Application
+
+### Jaeger
+
+Setup [Jaeger Tracing All in One](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one) agent. If you have docker installed:
+
+```sh
+docker run \
+ --rm \
+ --name jaeger \
+ -e COLLECTOR_OTLP_ENABLED=true \
+ -p 16686:16686 \
+ -p 4317:4317 \
+ jaegertracing/all-in-one:latest
+```
+
+### Run the sample server
+
+```sh
+# from this directory
+$ node -r @opentelemetry/shim-opencensus/register ./server.js
+```
+
+The `-r @opentelemetry/shim-opencensus/register` flag to Node tells it to load the OpenCensus
+shim's register module to install the OpenCensus shim. The shim bridges all calls to
+OpenCensus's tracers to OpenTelemetry.
+
+### Run the sample client
+
+```sh
+# from this directory
+node -r @opentelemetry/shim-opencensus/register ./client.js
+```
+
+Again, we use the `-r @opentelemetry/shim-opencensus/register` flag to install the OpenCensus shim.
+
+## Check the trace
+
+Go to Jaeger with your browser and click on the "Service" dropdown. Choose `opencensus-shim-example-server` and hit "Find Traces". Click on one of the available traces and you should see 3 spans:
+
+- An outer span from the client. This came from the OpenCensus HTTP instrumentation.
+ - A child from the server. This came from the OpenCensus HTTP instrumentation.
+ - A child for the sleep operation. This was manually instrumented with OpenTelemetry.
+ Notice this span is correctly recorded as a child of the OpenCensus instrumentation.
+
+
+
+## Useful links
+
+- For more information on OpenTelemetry, visit:
+- For more information on OpenTelemetry for Node.js, visit:
+- For more information on OpenCensus, visit:
+
+## LICENSE
+
+Apache License 2.0
diff --git a/experimental/examples/opencensus-shim/client.js b/experimental/examples/opencensus-shim/client.js
new file mode 100644
index 0000000000..e0a2ed52fa
--- /dev/null
+++ b/experimental/examples/opencensus-shim/client.js
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+'use strict';
+
+const setup = require('./setup');
+
+const provider = setup('opencensus-shim-example-client');
+
+const http = require('http');
+
+makeRequest();
+
+async function makeRequest() {
+ const data = await new Promise((resolve, reject) => {
+ http
+ .get(
+ {
+ host: 'localhost',
+ port: 3000,
+ path: '/',
+ },
+ resp => {
+ let data = '';
+
+ resp.on('data', chunk => {
+ data += chunk;
+ });
+
+ resp.on('end', async () => {
+ resolve(JSON.parse(data));
+ });
+ }
+ )
+ .on('error', err => {
+ reject(err);
+ });
+ });
+ console.log('Got data from server: ', data);
+
+ await provider.shutdown();
+}
diff --git a/experimental/examples/opencensus-shim/images/jaeger-trace.png b/experimental/examples/opencensus-shim/images/jaeger-trace.png
new file mode 100644
index 0000000000..15521f64cd
Binary files /dev/null and b/experimental/examples/opencensus-shim/images/jaeger-trace.png differ
diff --git a/experimental/examples/opencensus-shim/package.json b/experimental/examples/opencensus-shim/package.json
new file mode 100644
index 0000000000..baddb59ee3
--- /dev/null
+++ b/experimental/examples/opencensus-shim/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "opencensus-shim",
+ "private": true,
+ "version": "0.38.0",
+ "description": "Example of using @opentelemetry/shim-opencensus in Node.js",
+ "main": "index.js",
+ "scripts": {
+ "client": "node -r @opentelemetry/shim-opencensus/register ./client.js",
+ "server": "node -r @opentelemetry/shim-opencensus/register ./server.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/open-telemetry/opentelemetry-js.git"
+ },
+ "keywords": [
+ "opentelemetry",
+ "http",
+ "tracing",
+ "opencensus"
+ ],
+ "engines": {
+ "node": ">=14"
+ },
+ "author": "OpenTelemetry Authors",
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/open-telemetry/opentelemetry-js/issues"
+ },
+ "dependencies": {
+ "@opentelemetry/api": "1.4.1",
+ "@opentelemetry/sdk-trace-node": "1.13.0",
+ "@opencensus/core": "0.1.0",
+ "@opencensus/nodejs": "0.1.0",
+ "@opentelemetry/semantic-conventions": "1.13.0",
+ "@opentelemetry/exporter-trace-otlp-grpc": "0.39.1",
+ "@opentelemetry/resources": "1.13.0",
+ "@opentelemetry/shim-opencensus": "0.39.1"
+ },
+ "homepage": "https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/examples/opencensus-shim",
+ "devDependencies": {}
+}
diff --git a/experimental/examples/opencensus-shim/server.js b/experimental/examples/opencensus-shim/server.js
new file mode 100644
index 0000000000..98ddcf5b60
--- /dev/null
+++ b/experimental/examples/opencensus-shim/server.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const { SpanStatusCode } = require('@opentelemetry/api');
+const setup = require('./setup');
+const utils = require('./utils');
+const { trace } = require('@opentelemetry/api');
+
+setup('opencensus-shim-example-server');
+const http = require('http');
+
+const otelTracer = trace.getTracer('opencensus-shim-example');
+
+function startServer(port) {
+ // requests are traced by OpenCensus http instrumentation
+ const server = http.createServer(async (req, res) => {
+ // you can mix OTel and OC instrumentation
+
+ // deliberately sleeping to mock some action
+ await otelTracer.startActiveSpan('sleep', async span => {
+ await utils.sleep(1000);
+ span.end();
+ });
+
+ trace.getActiveSpan()?.addEvent('write headers');
+ res.writeHead(200, { 'Content-Type': 'application/json' });
+ trace.getActiveSpan()?.addEvent('write json response');
+ res.write(JSON.stringify({ status: 'OK', message: 'Hello World!' }));
+ trace.getActiveSpan()?.setStatus(SpanStatusCode.OK);
+ res.end();
+ });
+
+ server.listen(port, err => {
+ if (err) throw err;
+
+ console.log(`Server is listening on ${port}`);
+ });
+}
+
+startServer(3000);
diff --git a/experimental/examples/opencensus-shim/setup.js b/experimental/examples/opencensus-shim/setup.js
new file mode 100644
index 0000000000..e96c62ae0c
--- /dev/null
+++ b/experimental/examples/opencensus-shim/setup.js
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+'use strict';
+
+const { DiagConsoleLogger, diag, DiagLogLevel } = require('@opentelemetry/api');
+const {
+ NodeTracerProvider,
+ BatchSpanProcessor,
+} = require('@opentelemetry/sdk-trace-node');
+const {
+ OTLPTraceExporter,
+} = require('@opentelemetry/exporter-trace-otlp-grpc');
+const { Resource } = require('@opentelemetry/resources');
+const {
+ SemanticResourceAttributes,
+} = require('@opentelemetry/semantic-conventions');
+
+module.exports = function setup(serviceName) {
+ const tracing = require('@opencensus/nodejs');
+
+ diag.setLogger(new DiagConsoleLogger(), { logLevel: DiagLogLevel.ALL });
+ const provider = new NodeTracerProvider({
+ resource: new Resource({
+ [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
+ }),
+ });
+ provider.addSpanProcessor(
+ new BatchSpanProcessor(new OTLPTraceExporter(), {
+ scheduledDelayMillis: 5000,
+ })
+ );
+ provider.register();
+
+ // Start OpenCensus tracing
+ tracing.start({ samplingRate: 1, logger: diag });
+
+ return provider;
+};
diff --git a/experimental/examples/opencensus-shim/utils.js b/experimental/examples/opencensus-shim/utils.js
new file mode 100644
index 0000000000..3b1c625009
--- /dev/null
+++ b/experimental/examples/opencensus-shim/utils.js
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+'use strict';
+
+async function sleep(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+}
+
+exports.sleep = sleep;
diff --git a/experimental/packages/shim-opencensus/README.md b/experimental/packages/shim-opencensus/README.md
index e614fccf38..e79cfc0f43 100644
--- a/experimental/packages/shim-opencensus/README.md
+++ b/experimental/packages/shim-opencensus/README.md
@@ -15,7 +15,64 @@ npm install --save @opentelemetry/shim-opencensus
## Usage
-TODO
+### Installing the shim's require-in-the-middle hook
+
+This is the recommended way to use the shim.
+
+This package provides a `require-in-the-middle` hook which replaces OpenCensus's `CoreTracer`
+class with a shim implementation that writes to the OpenTelemetry API. This will cause all
+usage of OpenCensus's tracing methods (in OpenCensus instrumentation or your own custom
+instrumentation) to be reported to OpenTelemetry.
+
+There are two options for installing the hook:
+
+1. Using Node's `--require` flag to load the register module:
+
+ ```sh
+ node --require @opentelemetry/shim-opencensus/register ./app.js
+ ```
+
+2. Programmatically:
+
+ ```js
+ // Early in your application startup
+ require('@opentelemetry/shim-opencensus').installShim();
+ ```
+
+ Note that this has to be run before any OpenCensus tracers have been created.
+
+### Replace OpenCensus tracer with the `ShimTracer` in your code
+
+Alternatively, you can replace any usage of OpenCensus tracers in your code with the `ShimTracer` directly.
+
+Before:
+
+```js
+const tracing = require('@opencensus/nodejs');
+const tracer = tracing.start({samplingRate: 1}).tracer;
+
+// ...
+
+tracer.startRootSpan({name: 'main'}, rootSpan => {
+ rootSpan.end();
+});
+```
+
+After:
+
+```js
+const { trace } = require('@opentelemetry/api');
+const { ShimTracer } = require('@opentelemetry/shim-opencensus');
+const tracer = new ShimTracer(trace.getTracer('my-module'));
+
+// ...
+
+tracer.startRootSpan({name: 'main'}, rootSpan => {
+ rootSpan.end();
+});
+```
+
+## Example
See [examples/opencensus-shim](https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/examples/opencensus-shim) for a short example.
diff --git a/experimental/packages/shim-opencensus/package.json b/experimental/packages/shim-opencensus/package.json
index ec3c5dafed..675c3c4cf6 100644
--- a/experimental/packages/shim-opencensus/package.json
+++ b/experimental/packages/shim-opencensus/package.json
@@ -4,6 +4,10 @@
"description": "OpenCensus to OpenTelemetry shim",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
+ "exports": {
+ ".": "./build/src/index.js",
+ "./register": "./build/src/register.js"
+ },
"repository": "open-telemetry/opentelemetry-js",
"scripts": {
"prepublishOnly": "npm run compile",
diff --git a/experimental/packages/shim-opencensus/src/index.ts b/experimental/packages/shim-opencensus/src/index.ts
index ccfe42e2f8..5df2f6c315 100644
--- a/experimental/packages/shim-opencensus/src/index.ts
+++ b/experimental/packages/shim-opencensus/src/index.ts
@@ -15,3 +15,4 @@
*/
export { ShimTracer } from './ShimTracer';
+export { installShim, uninstallShim } from './shim';