Skip to content

Commit 93e8fb8

Browse files
committed
extend README and url validation to avoid footguns.
1 parent c516264 commit 93e8fb8

File tree

4 files changed

+61
-10
lines changed

4 files changed

+61
-10
lines changed

packages/opentelemetry-exporter-collector-grpc/README.md

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ npm install --save @opentelemetry/exporter-collector-grpc
1818
The CollectorTraceExporter in Node expects the URL to only be the hostname. It will not work with `/v1/trace`.
1919

2020
```js
21+
const Graceful = require('node-graceful');
22+
2123
const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing');
2224
const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-grpc');
2325

2426
const collectorOptions = {
2527
serviceName: 'basic-service',
26-
url: '<opentelemetry-collector-url>' // url is optional and can be omitted - default is localhost:4317
28+
// url is optional and can be omitted - default is localhost:4317
29+
url: '<collector-hostname>:<port>',
2730
};
2831

2932
const provider = new BasicTracerProvider();
@@ -32,48 +35,70 @@ provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
3235

3336
provider.register();
3437

38+
Graceful.on("exit", async () => {
39+
await provider.shutdown();
40+
});
3541
```
3642

3743
By default, plaintext connection is used. In order to use TLS in Node.js, provide `credentials` option like so:
3844

3945
```js
4046
const fs = require('fs');
47+
// Must be 'grpc', _not_ '@grpc/grpc-js'
4148
const grpc = require('grpc');
49+
const Graceful = require('node-graceful');
50+
4251
const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing');
4352
const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-grpc');
4453

4554
const collectorOptions = {
4655
serviceName: 'basic-service',
47-
url: '<opentelemetry-collector-url>', // url is optional and can be omitted - default is localhost:4317
48-
credentials: grpc.credentials.createSsl(
49-
fs.readFileSync('./ca.crt'),
50-
fs.readFileSync('./client.key'),
51-
fs.readFileSync('./client.crt')
52-
)
56+
// url is optional and can be omitted - default is localhost:4317
57+
url: '<collector-hostname>:<port>',
58+
credentials: grpc.credentials.createSsl(),
5359
};
5460

5561
const provider = new BasicTracerProvider();
5662
const exporter = new CollectorTraceExporter(collectorOptions);
5763
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
5864

5965
provider.register();
66+
67+
Graceful.on("exit", async () => {
68+
await provider.shutdown();
69+
});
6070
```
6171

62-
To see how to generate credentials, you can refer to the script used to generate certificates for tests [here](./test/certs/regenerate.sh)
72+
To use mutual authentication, pass to the `createSsl()` constructor:
73+
74+
```js
75+
credentials: grpc.credentials.createSsl(
76+
fs.readFileSync('./ca.crt'),
77+
fs.readFileSync('./client.key'),
78+
fs.readFileSync('./client.crt')
79+
),
80+
```
81+
82+
To generate credentials for mutual authentication, you can refer to the script used to generate certificates for tests [here](./test/certs/regenerate.sh)
6383

6484
The exporter can be configured to send custom metadata with each request as in the example below:
6585

6686
```js
87+
// Must be 'grpc', _not_ '@grpc/grpc-js'
6788
const grpc = require('grpc');
89+
const Graceful = require('node-graceful');
90+
6891
const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing');
6992
const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-grpc');
7093

7194
const metadata = new grpc.Metadata();
95+
// For instance, an API key or access token might go here.
7296
metadata.set('k', 'v');
7397

7498
const collectorOptions = {
7599
serviceName: 'basic-service',
76-
url: '<opentelemetry-collector-url>', // url is optional and can be omitted - default is localhost:4317
100+
// url is optional and can be omitted - default is localhost:4317
101+
url: '<collector-hostname>:<port>',
77102
metadata, // // an optional grpc.Metadata object to be sent with each request
78103
};
79104

@@ -82,6 +107,10 @@ const exporter = new CollectorTraceExporter(collectorOptions);
82107
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
83108

84109
provider.register();
110+
111+
Graceful.on("exit", async () => {
112+
await provider.shutdown();
113+
});
85114
```
86115

87116
Note, that this will only work if TLS is also configured on the server.
@@ -95,7 +124,8 @@ const { MeterProvider } = require('@opentelemetry/metrics');
95124
const { CollectorMetricExporter } = require('@opentelemetry/exporter-collector-grpc');
96125
const collectorOptions = {
97126
serviceName: 'basic-service',
98-
url: '<opentelemetry-collector-url>', // url is optional and can be omitted - default is localhost:55681
127+
// url is optional and can be omitted - default is localhost:4317
128+
url: '<collector-hostname>:<port>',
99129
};
100130
const exporter = new CollectorMetricExporter(collectorOptions);
101131

packages/opentelemetry-exporter-collector-grpc/src/util.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ export function onInit<ExportItem, ServiceRequest>(
3232
config: CollectorExporterConfigNode
3333
): void {
3434
collector.grpcQueue = [];
35+
if (collector.url.indexOf('/') != -1) {
36+
diag.warn('URL path cannot be set when using grpc');
37+
}
3538
const serverAddress = removeProtocol(collector.url);
3639
const credentials: grpc.ChannelCredentials =
3740
config.credentials || grpc.credentials.createInsecure();

packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,15 @@ const testCollectorMetricExporter = (params: TestParams) =>
178178
const args = spyLoggerWarn.args[0];
179179
assert.strictEqual(args[0], 'Headers cannot be set when using grpc');
180180
});
181+
it('should warn about path in url', () => {
182+
const spyLoggerWarn = sinon.stub(diag, 'warn');
183+
collectorExporter = new CollectorMetricExporter({
184+
serviceName: 'basic-service',
185+
url: address + '/v1/metrics',
186+
});
187+
const args = spyLoggerWarn.args[0];
188+
assert.strictEqual(args[0], 'URL path cannot be set when using grpc');
189+
});
181190
});
182191

183192
describe('export', () => {

packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,15 @@ const testCollectorExporter = (params: TestParams) =>
155155
const args = spyLoggerWarn.args[0];
156156
assert.strictEqual(args[0], 'Headers cannot be set when using grpc');
157157
});
158+
it('should warn about path in url', () => {
159+
const spyLoggerWarn = sinon.stub(diag, 'warn');
160+
collectorExporter = new CollectorTraceExporter({
161+
serviceName: 'basic-service',
162+
url: address + '/v1/trace',
163+
});
164+
const args = spyLoggerWarn.args[0];
165+
assert.strictEqual(args[0], 'URL path cannot be set when using grpc');
166+
});
158167
});
159168

160169
describe('export', () => {

0 commit comments

Comments
 (0)