diff --git a/examples/opentracing-shim/README.md b/examples/opentracing-shim/README.md new file mode 100644 index 0000000000..c56e0d3ef2 --- /dev/null +++ b/examples/opentracing-shim/README.md @@ -0,0 +1,77 @@ +# Overview + +OpenTracing shim allows existing OpenTracing instrumentation to report to OpenTelemetry. + +This is a simple example that demonstrates how existing OpenTracing instrumentation can be integrated with OpenTelemetry. + +The example shows key aspects of tracing such as + +- Root Span (on client) +- Child Span from a remote parent (on server) +- Span Tag +- Span Log +- Make a shim between OpenTracing and OpenTelemetry tracers + +## Installation +```sh +# from this directory +$ npm install +``` + +## Run the Application + +### Zipkin +- Setup [Zipkin Tracing UI](https://zipkin.io/pages/quickstart.html) + +- Run the server +```sh +# from this directory +$ npm run zipkin:server +``` + +- Run the client +```sh +# from this directory +$ npm run zipkin:client +``` + +- Check trace + + `zipkin:client` should output the `traceId` in the terminal. + + Go to Zipkin with your browser [http://localhost:9411/zipkin/traces/(your-trace-id)]() (e.g http://localhost:9411/zipkin/traces/4815c3d576d930189725f1f1d1bdfcc6) + + +

+ +### Jaeger +- Setup [Jaeger Tracing UI](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one) + +- Run the server +```sh +# from this directory +$ npm run jaeger:server +``` + +- Run the client +```sh +# from this directory +$ npm run jaeger:client +``` + +- Check trace + + `jaeger:client` should output the `traceId` in the terminal. + + Go to Jaeger with your browser [http://localhost:16686/trace/(your-trace-id)]() (e.g http://localhost:16686/trace/4815c3d576d930189725f1f1d1bdfcc6) + +

+ +## Useful links +- For more information on OpenTelemetry, visit: +- For more information on OpenTelemetry for Node.js, visit: +- For more information on OpenTracing, visit: + +## LICENSE + +Apache License 2.0 \ No newline at end of file diff --git a/examples/opentracing-shim/client.js b/examples/opentracing-shim/client.js new file mode 100644 index 0000000000..916b1c65f0 --- /dev/null +++ b/examples/opentracing-shim/client.js @@ -0,0 +1,45 @@ +"use strict"; + +const http = require("http"); +const opentracing = require("opentracing"); +const shim = require("./shim").shim("http_client_service"); + +opentracing.initGlobalTracer(shim); +const tracer = opentracing.globalTracer(); + +makeRequest(); + +async function makeRequest() { + const span = tracer.startSpan("make_request"); + + const headers = {}; + tracer.inject(span, opentracing.FORMAT_HTTP_HEADERS, headers); + + http + .get( + { + host: "localhost", + port: 3000, + path: "/", + headers + }, + resp => { + let data = ""; + + resp.on("data", chunk => { + data += chunk; + }); + + resp.on("end", async () => { + console.log(JSON.parse(data)); + span.finish(); + + console.log("Sleeping 5 seconds before shutdown to ensure all records are flushed."); + setTimeout(() => { console.log("Completed."); }, 5000); + }); + } + ) + .on("error", err => { + console.log("Error: " + err.message); + }); +} diff --git a/examples/opentracing-shim/images/jaeger-ui.png b/examples/opentracing-shim/images/jaeger-ui.png new file mode 100644 index 0000000000..489ae445a0 Binary files /dev/null and b/examples/opentracing-shim/images/jaeger-ui.png differ diff --git a/examples/opentracing-shim/images/zipkin-ui.png b/examples/opentracing-shim/images/zipkin-ui.png new file mode 100644 index 0000000000..83933792ef Binary files /dev/null and b/examples/opentracing-shim/images/zipkin-ui.png differ diff --git a/examples/opentracing-shim/package.json b/examples/opentracing-shim/package.json new file mode 100644 index 0000000000..709199fc2d --- /dev/null +++ b/examples/opentracing-shim/package.json @@ -0,0 +1,42 @@ +{ + "name": "opentracing-shim", + "private": true, + "version": "0.2.0", + "description": "Example of using @opentelemetry/shim-opentracing in Node.js", + "main": "index.js", + "scripts": { + "zipkin:client": "cross-env EXPORTER=zipkin node ./client.js", + "zipkin:server": "cross-env EXPORTER=zipkin node ./server.js", + "jaeger:client": "cross-env EXPORTER=jaeger node ./client.js", + "jaeger:server": "cross-env EXPORTER=jaeger node ./server.js" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/open-telemetry/opentelemetry-js.git" + }, + "keywords": [ + "opentelemetry", + "http", + "tracing", + "opentracing" + ], + "engines": { + "node": ">=8" + }, + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/open-telemetry/opentelemetry-js/issues" + }, + "dependencies": { + "@opentelemetry/exporter-jaeger": "^0.2.0", + "@opentelemetry/exporter-zipkin": "^0.2.0", + "@opentelemetry/node": "^0.2.0", + "@opentelemetry/shim-opentracing": "^0.2.0", + "opentracing": "^0.14.4" + }, + "homepage": "https://github.com/open-telemetry/opentelemetry-js#readme", + "devDependencies": { + "cross-env": "^6.0.0" + } +} diff --git a/examples/opentracing-shim/server.js b/examples/opentracing-shim/server.js new file mode 100644 index 0000000000..f10ffdfc5d --- /dev/null +++ b/examples/opentracing-shim/server.js @@ -0,0 +1,58 @@ +"use strict"; + +const http = require("http"); +const opentracing = require("opentracing"); +const utils = require("./utils"); +const shim = require("./shim").shim("http_server_service"); + +opentracing.initGlobalTracer(shim); +const tracer = opentracing.globalTracer(); + +startServer(3000); + +function startServer(port) { + const server = http.createServer(handleRequest); + + server.listen(port, err => { + if (err) throw err; + + console.log(`Server is listening on ${port}`); + }); +} + +async function handleRequest(req, res) { + const parentSpan = tracer.extract( + opentracing.FORMAT_HTTP_HEADERS, + req.headers + ); + + const span = tracer.startSpan("handle_request", { + childOf: parentSpan + }); + + span.setTag("custom", "tag value"); + span.setTag("alpha", "1000"); + + await doSomething(span); + + res.writeHead(200, { "Content-Type": "application/json" }); + res.write( + JSON.stringify({ status: "OK", traceId: span.context().toTraceId() }) + ); + + res.end(); + span.finish(); +} + +async function doSomething(parentSpan) { + const span = tracer.startSpan("do_something", { childOf: parentSpan }); + + span.setTag("alpha", "200"); + span.setTag("beta", "50"); + span.log({ state: "waiting" }); + + // deliberately sleeping to mock some action. + await utils.sleep(1000); + + span.finish(); +} diff --git a/examples/opentracing-shim/shim.js b/examples/opentracing-shim/shim.js new file mode 100644 index 0000000000..8579eb73a4 --- /dev/null +++ b/examples/opentracing-shim/shim.js @@ -0,0 +1,27 @@ +"use strict"; + +const { NodeTracer } = require("@opentelemetry/node"); +const { SimpleSpanProcessor } = require("@opentelemetry/tracing"); +const { JaegerExporter } = require("@opentelemetry/exporter-jaeger"); +const { ZipkinExporter } = require("@opentelemetry/exporter-zipkin"); +const { TracerShim } = require("@opentelemetry/shim-opentracing"); + +function shim(serviceName) { + const tracer = new NodeTracer(); + + tracer.addSpanProcessor(new SimpleSpanProcessor(getExporter(serviceName))); + + return new TracerShim(tracer); +} + +function getExporter(serviceName) { + const type = process.env.EXPORTER.toLowerCase() || "jaeger"; + + if (type.startsWith("z")) { + return new ZipkinExporter({ serviceName }); + } + + return new JaegerExporter({ serviceName, flushInterval: 100 }); +} + +exports.shim = shim; diff --git a/examples/opentracing-shim/utils.js b/examples/opentracing-shim/utils.js new file mode 100644 index 0000000000..813dc35dcd --- /dev/null +++ b/examples/opentracing-shim/utils.js @@ -0,0 +1,7 @@ +"use strict"; + +async function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +exports.sleep = sleep; diff --git a/packages/tsconfig.base.json b/packages/tsconfig.base.json index 9e6f097ccf..116c12d66d 100644 --- a/packages/tsconfig.base.json +++ b/packages/tsconfig.base.json @@ -13,7 +13,8 @@ "sourceMap": true, "strict": true, "strictNullChecks": true, - "target": "esnext" + "target": "es2017", + "incremental": true }, "exclude": [ "node_modules"