Skip to content

Commit f40e3de

Browse files
llc1123pichlermarclegendecas
authored
feat(otlp-grpc-exporters): Add support for Unix domain socket endpoints. (#3853)
* feat(otlp-grpc-exporter-base): add support for unix domain socket * test(otlp-grpc-exporter): add tests * chore(docs): update docs and changelog * fix: skip UDS tests on windows * Update CHANGELOG.md * fix: add protocol to http test urls * fix: update tests --------- Co-authored-by: Marc Pichler <[email protected]> Co-authored-by: Chengzhong Wu <[email protected]>
1 parent 67d4b80 commit f40e3de

File tree

9 files changed

+130
-68
lines changed

9 files changed

+130
-68
lines changed

experimental/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ All notable changes to experimental packages in this project will be documented
1010

1111
### :rocket: (Enhancement)
1212

13+
* feat(otlp-grpc-exporters): add support for UDS endpoints. [#3853](https://github.com/open-telemetry/opentelemetry-js/pull/3853) @llc1123
14+
1315
### :bug: (Bug Fix)
1416

1517
### :books: (Refine Doc)

experimental/packages/exporter-logs-otlp-grpc/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-grpc';
3434

3535
const collectorOptions = {
3636
// url is optional and can be omitted - default is http://localhost:4317
37+
// Unix domain sockets are also supported: 'unix:///path/to/socket.sock'
3738
url: 'http://<collector-hostname>:<port>',
3839
};
3940

experimental/packages/exporter-logs-otlp-grpc/test/OTLPLogExporter.test.ts

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,23 @@ const includeDirs = [
4444
path.resolve(__dirname, '../../otlp-grpc-exporter-base/protos'),
4545
];
4646

47-
const address = 'localhost:1503';
47+
const httpAddr = 'https://localhost:1503';
48+
const udsAddr = 'unix:///tmp/otlp-logs.sock';
4849

4950
type TestParams = {
51+
address?: string;
5052
useTLS?: boolean;
5153
metadata?: grpc.Metadata;
5254
};
5355

5456
const metadata = new grpc.Metadata();
5557
metadata.set('k', 'v');
5658

57-
const testCollectorExporter = (params: TestParams) =>
58-
describe(`OTLPLogExporter - node ${params.useTLS ? 'with' : 'without'} TLS, ${
59-
params.metadata ? 'with' : 'without'
60-
} metadata`, () => {
59+
const testCollectorExporter = (params: TestParams) => {
60+
const { address = httpAddr, useTLS, metadata } = params;
61+
return describe(`OTLPLogExporter - node ${useTLS ? 'with' : 'without'} TLS, ${
62+
metadata ? 'with' : 'without'
63+
} metadata, target ${address}`, () => {
6164
let collectorExporter: OTLPLogExporter;
6265
let server: grpc.Server;
6366
let exportedData: IResourceLogs | undefined;
@@ -92,7 +95,7 @@ const testCollectorExporter = (params: TestParams) =>
9295
},
9396
}
9497
);
95-
const credentials = params.useTLS
98+
const credentials = useTLS
9699
? grpc.ServerCredentials.createSsl(
97100
fs.readFileSync('./test/certs/ca.crt'),
98101
[
@@ -103,10 +106,15 @@ const testCollectorExporter = (params: TestParams) =>
103106
]
104107
)
105108
: grpc.ServerCredentials.createInsecure();
106-
server.bindAsync(address, credentials, () => {
107-
server.start();
108-
done();
109-
});
109+
const serverAddr = new URL(address);
110+
server.bindAsync(
111+
serverAddr.protocol === 'https:' ? serverAddr.host : address,
112+
credentials,
113+
() => {
114+
server.start();
115+
done();
116+
}
117+
);
110118
});
111119
});
112120

@@ -115,17 +123,17 @@ const testCollectorExporter = (params: TestParams) =>
115123
});
116124

117125
beforeEach(done => {
118-
const credentials = params.useTLS
126+
const credentials = useTLS
119127
? grpc.credentials.createSsl(
120128
fs.readFileSync('./test/certs/ca.crt'),
121129
fs.readFileSync('./test/certs/client.key'),
122130
fs.readFileSync('./test/certs/client.crt')
123131
)
124132
: grpc.credentials.createInsecure();
125133
collectorExporter = new OTLPLogExporter({
126-
url: 'https://' + address,
134+
url: address,
127135
credentials,
128-
metadata: params.metadata,
136+
metadata: metadata,
129137
});
130138
done();
131139
});
@@ -141,7 +149,7 @@ const testCollectorExporter = (params: TestParams) =>
141149
// Need to stub/spy on the underlying logger as the 'diag' instance is global
142150
const spyLoggerWarn = sinon.stub(diag, 'warn');
143151
collectorExporter = new OTLPLogExporter({
144-
url: `http://${address}`,
152+
url: address,
145153
headers: {
146154
foo: 'bar',
147155
},
@@ -150,9 +158,13 @@ const testCollectorExporter = (params: TestParams) =>
150158
assert.strictEqual(args[0], 'Headers cannot be set when using grpc');
151159
});
152160
it('should warn about path in url', () => {
161+
if (new URL(address).protocol === 'unix:') {
162+
// Skip this test for UDS
163+
return;
164+
}
153165
const spyLoggerWarn = sinon.stub(diag, 'warn');
154166
collectorExporter = new OTLPLogExporter({
155-
url: `http://${address}/v1/logs`,
167+
url: `${address}/v1/logs`,
156168
});
157169
const args = spyLoggerWarn.args[0];
158170
assert.strictEqual(
@@ -190,7 +202,7 @@ const testCollectorExporter = (params: TestParams) =>
190202
}, 500);
191203
});
192204
it('should log deadline exceeded error', done => {
193-
const credentials = params.useTLS
205+
const credentials = useTLS
194206
? grpc.credentials.createSsl(
195207
fs.readFileSync('./test/certs/ca.crt'),
196208
fs.readFileSync('./test/certs/client.key'),
@@ -199,9 +211,9 @@ const testCollectorExporter = (params: TestParams) =>
199211
: grpc.credentials.createInsecure();
200212

201213
const collectorExporterWithTimeout = new OTLPLogExporter({
202-
url: 'grpcs://' + address,
214+
url: address,
203215
credentials,
204-
metadata: params.metadata,
216+
metadata: metadata,
205217
timeoutMillis: 100,
206218
});
207219

@@ -222,21 +234,21 @@ const testCollectorExporter = (params: TestParams) =>
222234
});
223235
describe('export - with gzip compression', () => {
224236
beforeEach(() => {
225-
const credentials = params.useTLS
237+
const credentials = useTLS
226238
? grpc.credentials.createSsl(
227239
fs.readFileSync('./test/certs/ca.crt'),
228240
fs.readFileSync('./test/certs/client.key'),
229241
fs.readFileSync('./test/certs/client.crt')
230242
)
231243
: grpc.credentials.createInsecure();
232244
collectorExporter = new OTLPLogExporter({
233-
url: 'https://' + address,
245+
url: address,
234246
credentials,
235-
metadata: params.metadata,
247+
metadata: metadata,
236248
compression: CompressionAlgorithm.GZIP,
237249
});
238250
});
239-
it('should successfully send the spans', done => {
251+
it('should successfully send the log records', done => {
240252
const responseSpy = sinon.spy();
241253
const logRecords = [Object.assign({}, mockedReadableLogRecord)];
242254
collectorExporter.export(logRecords, responseSpy);
@@ -248,13 +260,13 @@ const testCollectorExporter = (params: TestParams) =>
248260
const logs = exportedData.scopeLogs[0].logRecords;
249261
const resource = exportedData.resource;
250262

251-
assert.ok(typeof logs !== 'undefined', 'spans do not exist');
263+
assert.ok(typeof logs !== 'undefined', 'log records do not exist');
252264
ensureExportedLogRecordIsCorrect(logs[0]);
253265

254266
assert.ok(typeof resource !== 'undefined', "resource doesn't exist");
255267
ensureResourceIsCorrect(resource);
256268

257-
ensureMetadataIsCorrect(reqMetadata, params.metadata);
269+
ensureMetadataIsCorrect(reqMetadata, metadata);
258270

259271
done();
260272
}, 500);
@@ -263,7 +275,7 @@ const testCollectorExporter = (params: TestParams) =>
263275
describe('Logs Exporter with compression', () => {
264276
const envSource = process.env;
265277
it('should return gzip compression algorithm on exporter', () => {
266-
const credentials = params.useTLS
278+
const credentials = useTLS
267279
? grpc.credentials.createSsl(
268280
fs.readFileSync('./test/certs/ca.crt'),
269281
fs.readFileSync('./test/certs/client.key'),
@@ -273,9 +285,9 @@ const testCollectorExporter = (params: TestParams) =>
273285

274286
envSource.OTEL_EXPORTER_OTLP_COMPRESSION = 'gzip';
275287
collectorExporter = new OTLPLogExporter({
276-
url: 'https://' + address,
288+
url: address,
277289
credentials,
278-
metadata: params.metadata,
290+
metadata: metadata,
279291
});
280292
assert.strictEqual(
281293
collectorExporter.compression,
@@ -285,6 +297,7 @@ const testCollectorExporter = (params: TestParams) =>
285297
});
286298
});
287299
});
300+
};
288301

289302
describe('OTLPLogExporter - node (getDefaultUrl)', () => {
290303
it('should default to localhost', done => {
@@ -344,3 +357,5 @@ describe('when configuring via environment', () => {
344357
testCollectorExporter({ useTLS: true });
345358
testCollectorExporter({ useTLS: false });
346359
testCollectorExporter({ metadata });
360+
// skip UDS tests on windows
361+
process.platform !== 'win32' && testCollectorExporter({ address: udsAddr });

experimental/packages/exporter-trace-otlp-grpc/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc'
3030

3131
const collectorOptions = {
3232
// url is optional and can be omitted - default is http://localhost:4317
33+
// Unix domain sockets are also supported: 'unix:///path/to/socket.sock'
3334
url: 'http://<collector-hostname>:<port>',
3435
};
3536

@@ -54,6 +55,7 @@ const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc'
5455

5556
const collectorOptions = {
5657
// url is optional and can be omitted - default is http://localhost:4317
58+
// Unix domain sockets are also supported: 'unix:///path/to/socket.sock'
5759
url: 'http://<collector-hostname>:<port>',
5860
credentials: grpc.credentials.createSsl(),
5961
};
@@ -94,6 +96,7 @@ metadata.set('k', 'v');
9496

9597
const collectorOptions = {
9698
// url is optional and can be omitted - default is http://localhost:4317
99+
// Unix domain sockets are also supported: 'unix:///path/to/socket.sock'
97100
url: 'http://<collector-hostname>:<port>',
98101
metadata, // // an optional grpc.Metadata object to be sent with each request
99102
};
@@ -120,6 +123,7 @@ The OTLPTraceExporter has a timeout configuration option which is the maximum ti
120123
const collectorOptions = {
121124
timeoutMillis: 15000,
122125
// url is optional and can be omitted - default is localhost:4317
126+
// Unix domain sockets are also supported: 'unix:///path/to/socket.sock'
123127
url: '<collector-hostname>:<port>',
124128
metadata, // // an optional grpc.Metadata object to be sent with each request
125129
};
@@ -138,6 +142,7 @@ const { CompressionAlgorithm } = require('@opentelemetry/exporter-trace-otlp-grp
138142

139143
const collectorOptions = {
140144
// url is optional and can be omitted - default is http://localhost:4317
145+
// Unix domain sockets are also supported: 'unix:///path/to/socket.sock'
141146
url: 'http://<collector-hostname>:<port>',
142147
metadata, // // an optional grpc.Metadata object to be sent with each request
143148
compression: CompressionAlgorithm.GZIP,

0 commit comments

Comments
 (0)