From 3b482f4ce99b42a2bfdbe94de261af1e6e67680f Mon Sep 17 00:00:00 2001 From: "Kelly, Niall" Date: Thu, 4 Jun 2020 12:09:42 +0100 Subject: [PATCH 1/5] chore: initial commit of grpc-census-example Signed-off-by: Kelly, Niall --- examples/grpc-census-prop/README.md | 130 ++++++++++++++++++ .../grpc-census-prop/capitalize_client.js | 73 ++++++++++ .../grpc-census-prop/capitalize_server.js | 93 +++++++++++++ examples/grpc-census-prop/combination2.md | 95 +++++++++++++ examples/grpc-census-prop/combination4.md | 98 +++++++++++++ examples/grpc-census-prop/package.json | 50 +++++++ examples/grpc-census-prop/protos/defs.proto | 19 +++ examples/grpc-census-prop/tracer.js | 36 +++++ examples/grpc-census-prop/tracer_census.js | 23 ++++ 9 files changed, 617 insertions(+) create mode 100644 examples/grpc-census-prop/README.md create mode 100644 examples/grpc-census-prop/capitalize_client.js create mode 100644 examples/grpc-census-prop/capitalize_server.js create mode 100644 examples/grpc-census-prop/combination2.md create mode 100644 examples/grpc-census-prop/combination4.md create mode 100644 examples/grpc-census-prop/package.json create mode 100644 examples/grpc-census-prop/protos/defs.proto create mode 100644 examples/grpc-census-prop/tracer.js create mode 100644 examples/grpc-census-prop/tracer_census.js diff --git a/examples/grpc-census-prop/README.md b/examples/grpc-census-prop/README.md new file mode 100644 index 0000000000..4d0d465f29 --- /dev/null +++ b/examples/grpc-census-prop/README.md @@ -0,0 +1,130 @@ +# Introduction + +This example uses the same gRPC [defs.proto](./protos/defs.proto) as the +[grpc_dynamic_codegen](../grpc_dynamic_codegen) +example in which a server takes a payload containing bytes and capitalizes them. +In this case we are demonstrating the use of the +[propagator-grpc-census-binary](../../propagators/opentelemetry-propagator-grpc-census-binary) +propagator. The propagator can be useful when communicating with another service +that is already instrumented using OpenCensus. + +If both sides of gRPC communication are using OpenTelemetry instrumentation then +the `propagator-grpc-census-binary` propagator isn't required. Context will be +propagated using the `traceparent` header (thanks to the +[HttpTraceContext](https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-core/src/context/propagation/HttpTraceContext.ts) +propagator from opentelemetry-core). If there is a mix of OpenCensus and OpenTelemetry +instrumentation then the `propagator-grpc-census-binary` propagator allows OpenTelemetry +to propagate context through the `grpc-trace-bin` binary header. + +The same source code is used to run various versions of the client and server. Environment +variables (set up through `scripts` in [package.json](./package.json) determine the various +combinations. This table shows what to expect: + +| Combination | Client Instrumentation | Server Instrumentation | Propagation Header | +| :---------- | :--------------------- | :--------------------- | :----------------- | +| 1 | OpenTelemetry (default propagator) | OpenTelemetry (default propagator) | `traceparent` | +| 2 | OpenCensus | OpenTelemetry (**binary propagator**) | `grpc-trace-bin` | +| 3 | OpenCensus | OpenCensus | `grpc-trace-bin` | +| 4 | OpenTelemetry (**binary propagator**) | OpenCensus | `grpc-trace-bin` | + +If context propagation is working correctly we should see consistent values +for `traceId` in the output of both the client and server. (Note: the example +uses simple Console Exporters rather than Jaeger or Zipkin). The servers also +output the contents of `grpc.Metadata` which allows us to see the values of +`traceparent` or `grpc-trace-bin` where applicable. + +## Installation + +```sh +$ # from this directory +$ npm install +``` + +## Running the Client and Server combinations + +### Combination 1 + +OpenTelemetry (with default propagator) used on both client and server. +Propagation through `traceparent` header. + +- Run the server + + ```sh + $ # from this directory + $ npm run server:otel:defprop + ``` + + - Run the client + + ```sh + $ # from this directory + $ npm run client:otel:defprop + ``` + +### Combination 2 + +OpenTelemetry (with **binary propagator**) used on server, OpenCensus used +on client. Propagation through `grpc-trace-bin` header. + +- Run the server + + ```sh + $ # from this directory + $ npm run server:otel:binprop + ``` + + - Run the client + + ```sh + $ # from this directory + $ npm run client:census + ``` + +See [combination2](./combination2.md) for example output + +### Combination 3 + +OpenCensus used on both client and server. Propagation through `grpc-trace-bin` header. + +- Run the server + + ```sh + $ # from this directory + $ npm run server:census + ``` + + - Run the client + + ```sh + $ # from this directory + $ npm run client:census + ``` + +### Combination 4 + +OpenCensus used on server, OpenTelemetry (with **binary propagator**) used on +client. Propagation through `grpc-trace-bin` header. + +- Run the server + + ```sh + $ # from this directory + $ npm run server:census + ``` + + - Run the client + + ```sh + $ # from this directory + $ npm run client:otel:binprop + ``` + +See [combination4](./combination4.md) for example output + +## Useful links +- For more information on OpenTelemetry, visit: +- For more information on OpenTelemetry for Node.js, visit: + +## LICENSE + +Apache License 2.0 diff --git a/examples/grpc-census-prop/capitalize_client.js b/examples/grpc-census-prop/capitalize_client.js new file mode 100644 index 0000000000..0768d6fe9c --- /dev/null +++ b/examples/grpc-census-prop/capitalize_client.js @@ -0,0 +1,73 @@ +'use strict'; + +const binaryPropagator = process.env.BINARY_PROPAGATOR === 'true' ? true : false; +const censusTracer = process.env.CENSUS_TRACER === 'true' ? true : false; +let tracer; +if (censusTracer) { + tracer = require('./tracer_census')(); +} else { + tracer = require('./tracer')('example-grpc-capitalize-client', binaryPropagator); +} + +const path = require('path'); +const grpc = require('grpc'); + +const PROTO_PATH = path.join(__dirname, 'protos/defs.proto'); + +// Even though grpc.load is deprecated in favor of @grpc/proto-loader, it +// appears @opencensus/instrumentation-grpc only gets to set the +// grpc-trace-bin header if we use grpc.load +const Fetch = grpc.load(PROTO_PATH).rpc.Fetch; + +function main() { + const client = new Fetch('localhost:50051', + grpc.credentials.createInsecure()); + const data = process.argv[2] || 'opentelemetry'; + console.log('> ', data); + + if (censusTracer) { + capitalizeWithCensusTracing(tracer, client, data); + } + else { + capitalizeWithOTelTracing(tracer, client, data); + } + + // The process must live for at least the interval past any traces that + // must be exported, or some risk being lost if they are recorded after the + // last export. + console.log('Sleeping 5 seconds before shutdown to ensure all records are flushed.'); + setTimeout(() => { console.log('Completed.'); }, 5000); +} + +function capitalizeWithCensusTracing(tracer, client, data) { + tracer.startRootSpan({name: 'tutorialsClient.capitalize'}, rootSpan => { + client.capitalize({ data: Buffer.from(data) }, (err, response) => { + if (err) { + console.log('could not get grpc response'); + rootSpan.end(); + return; + } + console.log('< ', response.data.toString('utf8')); + + rootSpan.end(); + }); + }); +} + +function capitalizeWithOTelTracing(tracer, client, data) { + const span = tracer.startSpan('tutorialsClient.capitalize'); + tracer.withSpan(span, () => { + client.capitalize({ data: Buffer.from(data) }, (err, response) => { + if (err) { + console.log('could not get grpc response'); + return; + } + console.log('< ', response.data.toString('utf8')); + // display traceid in the terminal + console.log(`traceid: ${span.context().traceId}`); + span.end(); + }); + }); +} + +main(); diff --git a/examples/grpc-census-prop/capitalize_server.js b/examples/grpc-census-prop/capitalize_server.js new file mode 100644 index 0000000000..817912df7c --- /dev/null +++ b/examples/grpc-census-prop/capitalize_server.js @@ -0,0 +1,93 @@ +'use strict'; + +const binaryPropagator = process.env.BINARY_PROPAGATOR === 'true' ? true : false; +const censusTracer = process.env.CENSUS_TRACER === 'true' ? true : false; + +let tracer; +let SpanKind; +if (censusTracer) { + tracer = require('./tracer_census')(); + SpanKind = require('@opencensus/core').SpanKind; +} else { + tracer = require('./tracer')('example-grpc-capitalize-server', binaryPropagator); + SpanKind = require('@opentelemetry/api').SpanKind; +} + +const path = require('path'); +const grpc = require('grpc'); +const protoLoader = require('@grpc/proto-loader'); + +const PROTO_PATH = path.join(__dirname, 'protos/defs.proto'); +const PROTO_OPTIONS = { + keepCase: true, enums: String, defaults: true, oneofs: true, +}; +const definition = protoLoader.loadSync(PROTO_PATH, PROTO_OPTIONS); +const rpcProto = grpc.loadPackageDefinition(definition).rpc; + +/** Implements the Capitalize RPC method. */ +function capitalize(call, callback) { + if (call.metadata) { + // output the gRPC metadata to see headers e.g. traceparent or grpc-trace-bin + console.dir(call.metadata, { depth: null }); + } + + let capitalized; + if (censusTracer) { + capitalized = capitalizeWithCensusTracing(call); + } else { + capitalized = capitalizeWithOTelTracing(call); + } + + callback(null, { data: Buffer.from(capitalized) }); +} + +function capitalizeWithCensusTracing(call) { + const currentSpan = tracer.currentRootSpan; + // display traceid in the terminal + console.log(`traceid: ${currentSpan.traceId}`); + + const span = tracer.startChildSpan({ + name: 'tutorials.FetchImpl.capitalize', + kind: SpanKind.SERVER + }); + + const data = call.request.data.toString('utf8'); + const capitalized = data.toUpperCase(); + for (let i = 0; i < 100000000; i += 1) { + // empty + } + span.end(); + return capitalized; +} + +function capitalizeWithOTelTracing(call) { + const currentSpan = tracer.getCurrentSpan(); + // display traceid in the terminal + console.log(`traceid: ${currentSpan.context().traceId}`); + + const span = tracer.startSpan('tutorials.FetchImpl.capitalize', { + parent: currentSpan, + kind: SpanKind.SERVER, + }); + + const data = call.request.data.toString('utf8'); + const capitalized = data.toUpperCase(); + for (let i = 0; i < 100000000; i += 1) { + // empty + } + span.end(); + return capitalized; +} + +/** + * Starts an RPC server that receives requests for the Fetch service at the + * sample server port. + */ +function main() { + const server = new grpc.Server(); + server.addService(rpcProto.Fetch.service, { capitalize }); + server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); + server.start(); +} + +main(); diff --git a/examples/grpc-census-prop/combination2.md b/examples/grpc-census-prop/combination2.md new file mode 100644 index 0000000000..446552135c --- /dev/null +++ b/examples/grpc-census-prop/combination2.md @@ -0,0 +1,95 @@ +# Example Output from Combination 2 + +OpenTelemetry (with **binary propagator**) used on server, OpenCensus used +on client. Propagation through `grpc-trace-bin` header. + +## Client + +Note: traceId **1565fbb4d6f042d8880bedb509bf6f2e** + +``` +$ npm run client:census + +> grpc-census-prop-example@0.8.0 client:census /opentelemetry-js-contrib/examples/grpc-census-prop +> cross-env CENSUS_TRACER=true node ./capitalize_client.js + +> opentelemetry +Sleeping 5 seconds before shutdown to ensure all records are flushed. +(node:14866) DeprecationWarning: grpc.load: Use the @grpc/proto-loader module with grpc.loadPackageDefinition instead +< OPENTELEMETRY +RootSpan: {traceId: 1565fbb4d6f042d8880bedb509bf6f2e, spanId: a5ccb3c920a18ace, name: tutorialsClient.capitalize } + ChildSpans: + {spanId: c92c3b3f955cdce1, name: grpc.rpc.Fetch/Capitalize} +Completed. +``` + +## Server + +Note: traceId **1565fbb4d6f042d8880bedb509bf6f2e** + +``` +$ npm run server:otel:binprop + +> grpc-census-prop-example@0.8.0 server:otel:binprop /opentelemetry-js-contrib/examples/grpc-census-prop +> cross-env BINARY_PROPAGATOR=true node ./capitalize_server.js + +PluginLoader#load: trying to load grpc@1.24.2 +Metadata { + _internal_repr: + { 'grpc-trace-bin': + [ Buffer [Uint8Array] [ + 0, + 0, + 21, + 101, + 251, + 180, + 214, + 240, + 66, + 216, + 136, + 11, + 237, + 181, + 9, + 191, + 111, + 46, + 1, + 201, + 44, + 59, + 63, + 149, + 92, + 220, + 225, + 2, + 1 ] ], + 'user-agent': [ 'grpc-node/1.24.2 grpc-c/8.0.0 (linux; chttp2; ganges)' ] }, + flags: 0 } +traceid: 1565fbb4d6f042d8880bedb509bf6f2e +{ traceId: '1565fbb4d6f042d8880bedb509bf6f2e', + parentId: '891bd1ebb5e44ec8', + name: 'tutorials.FetchImpl.capitalize', + id: '61a1c3bce0364fe2', + kind: 1, + timestamp: 1591295467649290, + duration: 101304, + attributes: {}, + status: { code: 0 }, + events: [] } +{ traceId: '1565fbb4d6f042d8880bedb509bf6f2e', + parentId: 'c92c3b3f955cdce1', + name: 'grpc.rpc.Fetch/Capitalize', + id: '891bd1ebb5e44ec8', + kind: 1, + timestamp: 1591295467645184, + duration: 106431, + attributes: + { 'grpc.kind': 1, component: 'grpc', 'grpc.status_code': '0' }, + status: { code: 0 }, + events: + [ { name: 'received', attributes: undefined, time: [Array] } ] } +``` diff --git a/examples/grpc-census-prop/combination4.md b/examples/grpc-census-prop/combination4.md new file mode 100644 index 0000000000..908e55990b --- /dev/null +++ b/examples/grpc-census-prop/combination4.md @@ -0,0 +1,98 @@ +# Example Output from Combination 4 + +OpenCensus used on server, OpenTelemetry (with **binary propagator**) used on +client. Propagation through `grpc-trace-bin` header. + +## Client + +Note: traceId **901c68f681e5a85a125b3dad82e51498** + +``` +$ npm run client:otel:binprop + +> grpc-census-prop-example@0.8.0 client:otel:binprop /opentelemetry-js-contrib/examples/grpc-census-prop +> cross-env BINARY_PROPAGATOR=true node ./capitalize_client.js + +PluginLoader#load: trying to load grpc@1.24.2 +> opentelemetry +Sleeping 5 seconds before shutdown to ensure all records are flushed. +(node:29834) DeprecationWarning: grpc.load: Use the @grpc/proto-loader module with grpc.loadPackageDefinition instead +{ traceId: '901c68f681e5a85a125b3dad82e51498', + parentId: '070c69c837bbbd1e', + name: 'grpc.rpc.Fetch/Capitalize', + id: 'ecdf319bce919fde', + kind: 2, + timestamp: 1591295728961209, + duration: 159530, + attributes: + { component: 'grpc', + 'grpc.method': '/rpc.Fetch/Capitalize', + 'grpc.kind': 2, + 'grpc.status_code': '0' }, + status: { code: 0 }, + events: [ { name: 'sent', attributes: undefined, time: [Array] } ] } +< OPENTELEMETRY +traceid: 901c68f681e5a85a125b3dad82e51498 +{ traceId: '901c68f681e5a85a125b3dad82e51498', + parentId: undefined, + name: 'tutorialsClient.capitalize', + id: '070c69c837bbbd1e', + kind: 0, + timestamp: 1591295728960326, + duration: 163145, + attributes: {}, + status: { code: 0 }, + events: [] } +Completed. +``` + +## Server + +Note: traceId **901c68f681e5a85a125b3dad82e51498** + +``` +$ npm run server:census + +> grpc-census-prop-example@0.8.0 server:census /opentelemetry-js-contrib/examples/grpc-census-prop +> cross-env CENSUS_TRACER=true node ./capitalize_server.js + +Metadata { + _internal_repr: + { 'grpc-trace-bin': + [ Buffer [Uint8Array] [ + 0, + 0, + 144, + 28, + 104, + 246, + 129, + 229, + 168, + 90, + 18, + 91, + 61, + 173, + 130, + 229, + 20, + 152, + 1, + 236, + 223, + 49, + 155, + 206, + 145, + 159, + 222, + 2, + 1 ] ], + 'user-agent': [ 'grpc-node/1.24.2 grpc-c/8.0.0 (linux; chttp2; ganges)' ] }, + flags: 0 } +traceid: 901c68f681e5a85a125b3dad82e51498 +RootSpan: {traceId: 901c68f681e5a85a125b3dad82e51498, spanId: 63028b5ce96caec6, name: grpc.rpc.Fetch/Capitalize } + ChildSpans: + {spanId: d70a03f18955e762, name: tutorials.FetchImpl.capitalize} +``` diff --git a/examples/grpc-census-prop/package.json b/examples/grpc-census-prop/package.json new file mode 100644 index 0000000000..3c904503af --- /dev/null +++ b/examples/grpc-census-prop/package.json @@ -0,0 +1,50 @@ +{ + "name": "grpc-census-prop-example", + "version": "0.8.0", + "description": "Example of using propagator-grpc-census-binary", + "main": "index.js", + "scripts": { + "server:otel:defprop": "cross-env node ./capitalize_server.js", + "server:otel:binprop": "cross-env BINARY_PROPAGATOR=true node ./capitalize_server.js", + "server:census": "cross-env CENSUS_TRACER=true node ./capitalize_server.js", + "client:otel:defprop": "cross-env node ./capitalize_client.js", + "client:otel:binprop": "cross-env BINARY_PROPAGATOR=true node ./capitalize_client.js", + "client:census": "cross-env CENSUS_TRACER=true node ./capitalize_client.js" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/open-telemetry/opentelemetry-js.git" + }, + "keywords": [ + "opentelemetry", + "grpc", + "tracing" + ], + "engines": { + "node": ">=8" + }, + "author": "OpenTelemetry Authors", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/open-telemetry/opentelemetry-js/issues" + }, + "dependencies": { + "@grpc/proto-loader": "^0.4.0", + "@opencensus/core": "0.0.21", + "@opencensus/instrumentation-grpc": "0.0.21", + "@opencensus/nodejs": "0.0.21", + "@opencensus/propagation-binaryformat": "0.0.21", + "@opentelemetry/api": "^0.8.3", + "@opentelemetry/core": "^0.8.3", + "@opentelemetry/node": "^0.8.3", + "@opentelemetry/plugin-grpc": "^0.8.3", + "@opentelemetry/propagator-grpc-census-binary": "^0.8.0", + "@opentelemetry/tracing": "^0.8.3", + "grpc": "^1.24.2", + "node-pre-gyp": "0.12.0" + }, + "homepage": "https://github.com/open-telemetry/opentelemetry-js#readme", + "devDependencies": { + "cross-env": "^6.0.0" + } +} diff --git a/examples/grpc-census-prop/protos/defs.proto b/examples/grpc-census-prop/protos/defs.proto new file mode 100644 index 0000000000..cc4a40334c --- /dev/null +++ b/examples/grpc-census-prop/protos/defs.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.helloworld"; +option java_outer_classname = "HelloWorldProto"; +option objc_class_prefix = "HLW"; + +package rpc; + +service Fetch { + // Sends a capitalizes payload + rpc Capitalize(Payload) returns (Payload) {} +} + +// The request and response payload containing the id and data. +message Payload { + int32 id = 1; + bytes data = 2; +} diff --git a/examples/grpc-census-prop/tracer.js b/examples/grpc-census-prop/tracer.js new file mode 100644 index 0000000000..d1b8c5e206 --- /dev/null +++ b/examples/grpc-census-prop/tracer.js @@ -0,0 +1,36 @@ +'use strict'; + +const opentelemetry = require('@opentelemetry/api'); +const { NodeTracerProvider } = require('@opentelemetry/node'); +const { SimpleSpanProcessor, ConsoleSpanExporter } = require('@opentelemetry/tracing'); +const { HttpTraceContext } = require('@opentelemetry/core'); +const { GrpcCensusPropagator } = require('@opentelemetry/propagator-grpc-census-binary'); + +module.exports = (serviceName, binaryPropagator) => { + const provider = new NodeTracerProvider({ + plugins: { + grpc: { + enabled: true, + // You may use a package name or absolute path to the file. + path: '@opentelemetry/plugin-grpc', + }, + }, + }); + + // It is recommended to use this `BatchSpanProcessor` for better performance + // and optimization, especially in production. + provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); + + if (binaryPropagator) { + // Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings + provider.register({ + propagator: new GrpcCensusPropagator() + }); + } else { + provider.register({ + propagator: new HttpTraceContext() + }); + } + + return opentelemetry.trace.getTracer(serviceName); +}; diff --git a/examples/grpc-census-prop/tracer_census.js b/examples/grpc-census-prop/tracer_census.js new file mode 100644 index 0000000000..32788ffc99 --- /dev/null +++ b/examples/grpc-census-prop/tracer_census.js @@ -0,0 +1,23 @@ +'use strict'; + +const tracing = require('@opencensus/nodejs'); +const { ConsoleExporter } = require('@opencensus/core'); + +const defaultBufferConfig = { + bufferSize: 1, + bufferTimeout: 2000 +}; + +module.exports = () => { + let tracer = tracing.start({ + + samplingRate: 1, + plugins: { + 'grpc': '@opencensus/instrumentation-grpc' + } + }).tracer; + + tracer.registerSpanEventListener(new ConsoleExporter(defaultBufferConfig)); + + return tracer; +}; From edef4824aa73d02b25be56be29596c2db68dd633 Mon Sep 17 00:00:00 2001 From: "Kelly, Niall" Date: Thu, 4 Jun 2020 21:17:09 +0100 Subject: [PATCH 2/5] chore: improve comments and address lint findings Signed-off-by: Kelly, Niall --- .../grpc-census-prop/capitalize_client.js | 29 ++++++++++++------- .../grpc-census-prop/capitalize_server.js | 21 ++++++++++---- examples/grpc-census-prop/tracer.js | 8 +++-- examples/grpc-census-prop/tracer_census.js | 13 +++++---- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/examples/grpc-census-prop/capitalize_client.js b/examples/grpc-census-prop/capitalize_client.js index 0768d6fe9c..09ba541873 100644 --- a/examples/grpc-census-prop/capitalize_client.js +++ b/examples/grpc-census-prop/capitalize_client.js @@ -1,7 +1,8 @@ 'use strict'; -const binaryPropagator = process.env.BINARY_PROPAGATOR === 'true' ? true : false; -const censusTracer = process.env.CENSUS_TRACER === 'true' ? true : false; +/* eslint-disable global-require */ +const binaryPropagator = process.env.BINARY_PROPAGATOR === 'true'; +const censusTracer = process.env.CENSUS_TRACER === 'true'; let tracer; if (censusTracer) { tracer = require('./tracer_census')(); @@ -17,8 +18,11 @@ const PROTO_PATH = path.join(__dirname, 'protos/defs.proto'); // Even though grpc.load is deprecated in favor of @grpc/proto-loader, it // appears @opencensus/instrumentation-grpc only gets to set the // grpc-trace-bin header if we use grpc.load -const Fetch = grpc.load(PROTO_PATH).rpc.Fetch; +const { Fetch } = grpc.load(PROTO_PATH).rpc; +/** + * Creates a gRPC client, makes a gRPC call and waits before shutting down + */ function main() { const client = new Fetch('localhost:50051', grpc.credentials.createInsecure()); @@ -26,10 +30,9 @@ function main() { console.log('> ', data); if (censusTracer) { - capitalizeWithCensusTracing(tracer, client, data); - } - else { - capitalizeWithOTelTracing(tracer, client, data); + capitalizeWithCensusTracing(client, data); + } else { + capitalizeWithOTelTracing(client, data); } // The process must live for at least the interval past any traces that @@ -39,8 +42,11 @@ function main() { setTimeout(() => { console.log('Completed.'); }, 5000); } -function capitalizeWithCensusTracing(tracer, client, data) { - tracer.startRootSpan({name: 'tutorialsClient.capitalize'}, rootSpan => { +/** + * Makes the gRPC call wrapped in an OpenCensus-style span + */ +function capitalizeWithCensusTracing(client, data) { + tracer.startRootSpan({ name: 'tutorialsClient.capitalize' }, (rootSpan) => { client.capitalize({ data: Buffer.from(data) }, (err, response) => { if (err) { console.log('could not get grpc response'); @@ -54,7 +60,10 @@ function capitalizeWithCensusTracing(tracer, client, data) { }); } -function capitalizeWithOTelTracing(tracer, client, data) { +/** + * Makes the gRPC call wrapped in an OpenTelemetry-style span + */ +function capitalizeWithOTelTracing(client, data) { const span = tracer.startSpan('tutorialsClient.capitalize'); tracer.withSpan(span, () => { client.capitalize({ data: Buffer.from(data) }, (err, response) => { diff --git a/examples/grpc-census-prop/capitalize_server.js b/examples/grpc-census-prop/capitalize_server.js index 817912df7c..4a43692201 100644 --- a/examples/grpc-census-prop/capitalize_server.js +++ b/examples/grpc-census-prop/capitalize_server.js @@ -1,16 +1,17 @@ 'use strict'; -const binaryPropagator = process.env.BINARY_PROPAGATOR === 'true' ? true : false; -const censusTracer = process.env.CENSUS_TRACER === 'true' ? true : false; +/* eslint-disable global-require */ +const binaryPropagator = process.env.BINARY_PROPAGATOR === 'true'; +const censusTracer = process.env.CENSUS_TRACER === 'true'; let tracer; let SpanKind; if (censusTracer) { tracer = require('./tracer_census')(); - SpanKind = require('@opencensus/core').SpanKind; + ({ SpanKind } = require('@opencensus/core').SpanKind); } else { tracer = require('./tracer')('example-grpc-capitalize-server', binaryPropagator); - SpanKind = require('@opentelemetry/api').SpanKind; + ({ SpanKind } = require('@opentelemetry/api').SpanKind); } const path = require('path'); @@ -24,7 +25,9 @@ const PROTO_OPTIONS = { const definition = protoLoader.loadSync(PROTO_PATH, PROTO_OPTIONS); const rpcProto = grpc.loadPackageDefinition(definition).rpc; -/** Implements the Capitalize RPC method. */ +/** + * Implements the Capitalize RPC method. + */ function capitalize(call, callback) { if (call.metadata) { // output the gRPC metadata to see headers e.g. traceparent or grpc-trace-bin @@ -41,6 +44,9 @@ function capitalize(call, callback) { callback(null, { data: Buffer.from(capitalized) }); } +/** + * Capitalize wrapped with Census tracing + */ function capitalizeWithCensusTracing(call) { const currentSpan = tracer.currentRootSpan; // display traceid in the terminal @@ -48,7 +54,7 @@ function capitalizeWithCensusTracing(call) { const span = tracer.startChildSpan({ name: 'tutorials.FetchImpl.capitalize', - kind: SpanKind.SERVER + kind: SpanKind.SERVER, }); const data = call.request.data.toString('utf8'); @@ -60,6 +66,9 @@ function capitalizeWithCensusTracing(call) { return capitalized; } +/** + * Capitalize wrapped with OpenTelemetry tracing + */ function capitalizeWithOTelTracing(call) { const currentSpan = tracer.getCurrentSpan(); // display traceid in the terminal diff --git a/examples/grpc-census-prop/tracer.js b/examples/grpc-census-prop/tracer.js index d1b8c5e206..143ef819cf 100644 --- a/examples/grpc-census-prop/tracer.js +++ b/examples/grpc-census-prop/tracer.js @@ -6,6 +6,10 @@ const { SimpleSpanProcessor, ConsoleSpanExporter } = require('@opentelemetry/tra const { HttpTraceContext } = require('@opentelemetry/core'); const { GrpcCensusPropagator } = require('@opentelemetry/propagator-grpc-census-binary'); +/** + * Return an OpenTelemetry tracer configured to use the gRPC plugin and with the + * requested propagator + */ module.exports = (serviceName, binaryPropagator) => { const provider = new NodeTracerProvider({ plugins: { @@ -24,11 +28,11 @@ module.exports = (serviceName, binaryPropagator) => { if (binaryPropagator) { // Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings provider.register({ - propagator: new GrpcCensusPropagator() + propagator: new GrpcCensusPropagator(), }); } else { provider.register({ - propagator: new HttpTraceContext() + propagator: new HttpTraceContext(), }); } diff --git a/examples/grpc-census-prop/tracer_census.js b/examples/grpc-census-prop/tracer_census.js index 32788ffc99..adf346f82a 100644 --- a/examples/grpc-census-prop/tracer_census.js +++ b/examples/grpc-census-prop/tracer_census.js @@ -5,17 +5,20 @@ const { ConsoleExporter } = require('@opencensus/core'); const defaultBufferConfig = { bufferSize: 1, - bufferTimeout: 2000 + bufferTimeout: 2000, }; +/** + * Return an OpenCensus tracer configured to use the gRPC plugin + */ module.exports = () => { - let tracer = tracing.start({ + const { tracer } = tracing.start({ samplingRate: 1, plugins: { - 'grpc': '@opencensus/instrumentation-grpc' - } - }).tracer; + grpc: '@opencensus/instrumentation-grpc', + }, + }); tracer.registerSpanEventListener(new ConsoleExporter(defaultBufferConfig)); From d12314703fdf110f058486ce746395dd9b3a9e21 Mon Sep 17 00:00:00 2001 From: "Kelly, Niall" Date: Thu, 4 Jun 2020 21:29:45 +0100 Subject: [PATCH 3/5] chore: fix destructuring Signed-off-by: Kelly, Niall --- examples/grpc-census-prop/capitalize_server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/grpc-census-prop/capitalize_server.js b/examples/grpc-census-prop/capitalize_server.js index 4a43692201..66574ccc92 100644 --- a/examples/grpc-census-prop/capitalize_server.js +++ b/examples/grpc-census-prop/capitalize_server.js @@ -8,10 +8,10 @@ let tracer; let SpanKind; if (censusTracer) { tracer = require('./tracer_census')(); - ({ SpanKind } = require('@opencensus/core').SpanKind); + ({ SpanKind } = require('@opencensus/core')); } else { tracer = require('./tracer')('example-grpc-capitalize-server', binaryPropagator); - ({ SpanKind } = require('@opentelemetry/api').SpanKind); + ({ SpanKind } = require('@opentelemetry/api')); } const path = require('path'); From aa5b920d15dcb1647abe67153ca0b66a853882ce Mon Sep 17 00:00:00 2001 From: "Kelly, Niall" Date: Fri, 5 Jun 2020 11:08:36 +0100 Subject: [PATCH 4/5] chore: fix typo in readme Signed-off-by: Kelly, Niall --- examples/grpc-census-prop/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/grpc-census-prop/README.md b/examples/grpc-census-prop/README.md index 4d0d465f29..d85f0446ff 100644 --- a/examples/grpc-census-prop/README.md +++ b/examples/grpc-census-prop/README.md @@ -17,7 +17,7 @@ instrumentation then the `propagator-grpc-census-binary` propagator allows OpenT to propagate context through the `grpc-trace-bin` binary header. The same source code is used to run various versions of the client and server. Environment -variables (set up through `scripts` in [package.json](./package.json) determine the various +variables (set up through `scripts` in [package.json](./package.json)) determine the various combinations. This table shows what to expect: | Combination | Client Instrumentation | Server Instrumentation | Propagation Header | From b1331a206219f8e46f770393ba29175e99f52baa Mon Sep 17 00:00:00 2001 From: "Kelly, Niall" Date: Mon, 8 Jun 2020 09:30:12 +0100 Subject: [PATCH 5/5] chore: mention example in propagator readme Signed-off-by: Kelly, Niall --- .../opentelemetry-propagator-grpc-census-binary/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/propagators/opentelemetry-propagator-grpc-census-binary/README.md b/propagators/opentelemetry-propagator-grpc-census-binary/README.md index 9ac3becb1c..471975100a 100644 --- a/propagators/opentelemetry-propagator-grpc-census-binary/README.md +++ b/propagators/opentelemetry-propagator-grpc-census-binary/README.md @@ -32,8 +32,12 @@ provider.register({ propagator: new GrpcCensusPropagator() }); ``` + +Also, see [examples/grpc-census-prop](../../examples/grpc-census-prop) for a +worked example that shows when this propagator can be useful. + ## Implementation Details -See [binary-format.ts](https://github.com/census-instrumentation/opencensus-node/blob/master/packages/opencensus-propagation-binaryformat/src/binary-format.ts) for equivalent encoding/decoding of the format in OpenCensus. Note: the author of the OpenCensus binary format, [~mayurkale22](https://github.com/mayurkale22), also created BinaryTraceContext.ts in [opentelemetry-core](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-core) but that was subsequently removed as part of PR [#804](https://github.com/open-telemetry/opentelemetry-js/pull/804). The implementation of GrpcCensusPropagator in _this_ module uses a version of BinaryTraceContext.ts inspired by Mayur's previous work (with minor modifications e.g. there is no longer a BinaryFormat interface to implement). +See [binary-format.ts](https://github.com/census-instrumentation/opencensus-node/blob/master/packages/opencensus-propagation-binaryformat/src/binary-format.ts) for equivalent encoding/decoding of the format in OpenCensus. Note: the author of the OpenCensus binary format, [@mayurkale22](https://github.com/mayurkale22), also created BinaryTraceContext.ts in [opentelemetry-core](https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-core) but that was subsequently removed as part of PR [#804](https://github.com/open-telemetry/opentelemetry-js/pull/804). The implementation of GrpcCensusPropagator in _this_ module uses a version of BinaryTraceContext.ts inspired by Mayur's previous work (with minor modifications e.g. there is no longer a BinaryFormat interface to implement). ## Useful links - For more information on OpenTelemetry, visit: