diff --git a/packages/opentelemetry-exporter-collector-grpc/README.md b/packages/opentelemetry-exporter-collector-grpc/README.md index cb472ee6997..804ffc445f6 100644 --- a/packages/opentelemetry-exporter-collector-grpc/README.md +++ b/packages/opentelemetry-exporter-collector-grpc/README.md @@ -18,12 +18,15 @@ npm install --save @opentelemetry/exporter-collector-grpc The CollectorTraceExporter in Node expects the URL to only be the hostname. It will not work with `/v1/trace`. ```js +const Graceful = require('node-graceful'); + const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing'); const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-grpc'); const collectorOptions = { serviceName: 'basic-service', - url: '' // url is optional and can be omitted - default is localhost:4317 + // url is optional and can be omitted - default is localhost:4317 + url: ':', }; const provider = new BasicTracerProvider(); @@ -32,24 +35,27 @@ provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); provider.register(); +Graceful.on("exit", async () => { + await provider.shutdown(); +}); ``` By default, plaintext connection is used. In order to use TLS in Node.js, provide `credentials` option like so: ```js const fs = require('fs'); +// Must be 'grpc', _not_ '@grpc/grpc-js' const grpc = require('grpc'); +const Graceful = require('node-graceful'); + const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing'); const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-grpc'); const collectorOptions = { serviceName: 'basic-service', - url: '', // url is optional and can be omitted - default is localhost:4317 - credentials: grpc.credentials.createSsl( - fs.readFileSync('./ca.crt'), - fs.readFileSync('./client.key'), - fs.readFileSync('./client.crt') - ) + // url is optional and can be omitted - default is localhost:4317 + url: ':', + credentials: grpc.credentials.createSsl(), }; const provider = new BasicTracerProvider(); @@ -57,23 +63,42 @@ const exporter = new CollectorTraceExporter(collectorOptions); provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); provider.register(); + +Graceful.on("exit", async () => { + await provider.shutdown(); +}); ``` -To see how to generate credentials, you can refer to the script used to generate certificates for tests [here](./test/certs/regenerate.sh) +To use mutual authentication, pass to the `createSsl()` constructor: + +```js + credentials: grpc.credentials.createSsl( + fs.readFileSync('./ca.crt'), + fs.readFileSync('./client.key'), + fs.readFileSync('./client.crt') + ), +``` + +To generate credentials for mutual authentication, you can refer to the script used to generate certificates for tests [here](./test/certs/regenerate.sh) The exporter can be configured to send custom metadata with each request as in the example below: ```js +// Must be 'grpc', _not_ '@grpc/grpc-js' const grpc = require('grpc'); +const Graceful = require('node-graceful'); + const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing'); const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-grpc'); const metadata = new grpc.Metadata(); +// For instance, an API key or access token might go here. metadata.set('k', 'v'); const collectorOptions = { serviceName: 'basic-service', - url: '', // url is optional and can be omitted - default is localhost:4317 + // url is optional and can be omitted - default is localhost:4317 + url: ':', metadata, // // an optional grpc.Metadata object to be sent with each request }; @@ -82,6 +107,10 @@ const exporter = new CollectorTraceExporter(collectorOptions); provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); provider.register(); + +Graceful.on("exit", async () => { + await provider.shutdown(); +}); ``` Note, that this will only work if TLS is also configured on the server. @@ -95,7 +124,8 @@ const { MeterProvider } = require('@opentelemetry/metrics'); const { CollectorMetricExporter } = require('@opentelemetry/exporter-collector-grpc'); const collectorOptions = { serviceName: 'basic-service', - url: '', // url is optional and can be omitted - default is localhost:55681 + // url is optional and can be omitted - default is localhost:4317 + url: ':', }; const exporter = new CollectorMetricExporter(collectorOptions); diff --git a/packages/opentelemetry-exporter-collector-grpc/src/util.ts b/packages/opentelemetry-exporter-collector-grpc/src/util.ts index 45ded6e4f54..9a66ffa7869 100644 --- a/packages/opentelemetry-exporter-collector-grpc/src/util.ts +++ b/packages/opentelemetry-exporter-collector-grpc/src/util.ts @@ -32,6 +32,9 @@ export function onInit( config: CollectorExporterConfigNode ): void { collector.grpcQueue = []; + if (collector.url.includes('/')) { + diag.warn('URL path cannot be set when using grpc'); + } const serverAddress = removeProtocol(collector.url); const credentials: grpc.ChannelCredentials = config.credentials || grpc.credentials.createInsecure(); diff --git a/packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts b/packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts index 59677eb5255..337570d0d19 100644 --- a/packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts +++ b/packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts @@ -178,6 +178,15 @@ const testCollectorMetricExporter = (params: TestParams) => const args = spyLoggerWarn.args[0]; assert.strictEqual(args[0], 'Headers cannot be set when using grpc'); }); + it('should warn about path in url', () => { + const spyLoggerWarn = sinon.stub(diag, 'warn'); + collectorExporter = new CollectorMetricExporter({ + serviceName: 'basic-service', + url: address + '/v1/metrics', + }); + const args = spyLoggerWarn.args[0]; + assert.strictEqual(args[0], 'URL path cannot be set when using grpc'); + }); }); describe('export', () => { diff --git a/packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts b/packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts index a1a38db5f33..8ec9bcd2c47 100644 --- a/packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts +++ b/packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts @@ -155,6 +155,15 @@ const testCollectorExporter = (params: TestParams) => const args = spyLoggerWarn.args[0]; assert.strictEqual(args[0], 'Headers cannot be set when using grpc'); }); + it('should warn about path in url', () => { + const spyLoggerWarn = sinon.stub(diag, 'warn'); + collectorExporter = new CollectorTraceExporter({ + serviceName: 'basic-service', + url: address + '/v1/trace', + }); + const args = spyLoggerWarn.args[0]; + assert.strictEqual(args[0], 'URL path cannot be set when using grpc'); + }); }); describe('export', () => {