Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(otlp-grpc-exporters): Add support for Unix domain socket endpoints. #3853

Merged
merged 19 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ All notable changes to experimental packages in this project will be documented

### :rocket: (Enhancement)

* feat(otlp-grpc-exporters): add support for UDS endpoints. [#3853](https://github.com/open-telemetry/opentelemetry-js/pull/3853) @llc1123

### :bug: (Bug Fix)

### :books: (Refine Doc)
Expand Down
1 change: 1 addition & 0 deletions experimental/packages/exporter-logs-otlp-grpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-grpc';

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,23 @@ const includeDirs = [
path.resolve(__dirname, '../../otlp-grpc-exporter-base/protos'),
];

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

type TestParams = {
address?: string;
useTLS?: boolean;
metadata?: grpc.Metadata;
};

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

const testCollectorExporter = (params: TestParams) =>
describe(`OTLPLogExporter - node ${params.useTLS ? 'with' : 'without'} TLS, ${
params.metadata ? 'with' : 'without'
} metadata`, () => {
const testCollectorExporter = (params: TestParams) => {
const { address = httpAddr, useTLS, metadata } = params;
return describe(`OTLPLogExporter - node ${useTLS ? 'with' : 'without'} TLS, ${
metadata ? 'with' : 'without'
} metadata, target ${address}`, () => {
let collectorExporter: OTLPLogExporter;
let server: grpc.Server;
let exportedData: IResourceLogs | undefined;
Expand Down Expand Up @@ -92,7 +95,7 @@ const testCollectorExporter = (params: TestParams) =>
},
}
);
const credentials = params.useTLS
const credentials = useTLS
? grpc.ServerCredentials.createSsl(
fs.readFileSync('./test/certs/ca.crt'),
[
Expand All @@ -103,10 +106,15 @@ const testCollectorExporter = (params: TestParams) =>
]
)
: grpc.ServerCredentials.createInsecure();
server.bindAsync(address, credentials, () => {
server.start();
done();
});
const serverAddr = new URL(address);
server.bindAsync(
serverAddr.protocol === 'https:' ? serverAddr.host : address,
credentials,
() => {
server.start();
done();
}
);
});
});

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

beforeEach(done => {
const credentials = params.useTLS
const credentials = useTLS
? grpc.credentials.createSsl(
fs.readFileSync('./test/certs/ca.crt'),
fs.readFileSync('./test/certs/client.key'),
fs.readFileSync('./test/certs/client.crt')
)
: grpc.credentials.createInsecure();
collectorExporter = new OTLPLogExporter({
url: 'https://' + address,
url: address,
credentials,
metadata: params.metadata,
metadata: metadata,
});
done();
});
Expand All @@ -141,7 +149,7 @@ const testCollectorExporter = (params: TestParams) =>
// Need to stub/spy on the underlying logger as the 'diag' instance is global
const spyLoggerWarn = sinon.stub(diag, 'warn');
collectorExporter = new OTLPLogExporter({
url: `http://${address}`,
url: address,
headers: {
foo: 'bar',
},
Expand All @@ -150,9 +158,13 @@ const testCollectorExporter = (params: TestParams) =>
assert.strictEqual(args[0], 'Headers cannot be set when using grpc');
});
it('should warn about path in url', () => {
if (new URL(address).protocol === 'unix:') {
// Skip this test for UDS
return;
}
const spyLoggerWarn = sinon.stub(diag, 'warn');
collectorExporter = new OTLPLogExporter({
url: `http://${address}/v1/logs`,
url: `${address}/v1/logs`,
});
const args = spyLoggerWarn.args[0];
assert.strictEqual(
Expand Down Expand Up @@ -190,7 +202,7 @@ const testCollectorExporter = (params: TestParams) =>
}, 500);
});
it('should log deadline exceeded error', done => {
const credentials = params.useTLS
const credentials = useTLS
? grpc.credentials.createSsl(
fs.readFileSync('./test/certs/ca.crt'),
fs.readFileSync('./test/certs/client.key'),
Expand All @@ -199,9 +211,9 @@ const testCollectorExporter = (params: TestParams) =>
: grpc.credentials.createInsecure();

const collectorExporterWithTimeout = new OTLPLogExporter({
url: 'grpcs://' + address,
url: address,
credentials,
metadata: params.metadata,
metadata: metadata,
timeoutMillis: 100,
});

Expand All @@ -222,21 +234,21 @@ const testCollectorExporter = (params: TestParams) =>
});
describe('export - with gzip compression', () => {
beforeEach(() => {
const credentials = params.useTLS
const credentials = useTLS
? grpc.credentials.createSsl(
fs.readFileSync('./test/certs/ca.crt'),
fs.readFileSync('./test/certs/client.key'),
fs.readFileSync('./test/certs/client.crt')
)
: grpc.credentials.createInsecure();
collectorExporter = new OTLPLogExporter({
url: 'https://' + address,
url: address,
credentials,
metadata: params.metadata,
metadata: metadata,
compression: CompressionAlgorithm.GZIP,
});
});
it('should successfully send the spans', done => {
it('should successfully send the log records', done => {
const responseSpy = sinon.spy();
const logRecords = [Object.assign({}, mockedReadableLogRecord)];
collectorExporter.export(logRecords, responseSpy);
Expand All @@ -248,13 +260,13 @@ const testCollectorExporter = (params: TestParams) =>
const logs = exportedData.scopeLogs[0].logRecords;
const resource = exportedData.resource;

assert.ok(typeof logs !== 'undefined', 'spans do not exist');
assert.ok(typeof logs !== 'undefined', 'log records do not exist');
ensureExportedLogRecordIsCorrect(logs[0]);

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

ensureMetadataIsCorrect(reqMetadata, params.metadata);
ensureMetadataIsCorrect(reqMetadata, metadata);

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

envSource.OTEL_EXPORTER_OTLP_COMPRESSION = 'gzip';
collectorExporter = new OTLPLogExporter({
url: 'https://' + address,
url: address,
credentials,
metadata: params.metadata,
metadata: metadata,
});
assert.strictEqual(
collectorExporter.compression,
Expand All @@ -285,6 +297,7 @@ const testCollectorExporter = (params: TestParams) =>
});
});
});
};

describe('OTLPLogExporter - node (getDefaultUrl)', () => {
it('should default to localhost', done => {
Expand Down Expand Up @@ -344,3 +357,5 @@ describe('when configuring via environment', () => {
testCollectorExporter({ useTLS: true });
testCollectorExporter({ useTLS: false });
testCollectorExporter({ metadata });
// skip UDS tests on windows
process.platform !== 'win32' && testCollectorExporter({ address: udsAddr });
5 changes: 5 additions & 0 deletions experimental/packages/exporter-trace-otlp-grpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc'

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

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

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

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

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