Skip to content

Commit

Permalink
fix(exporter-logs-otlp-http): set useHex to true (#3875)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nico385412 authored Jun 21, 2023
1 parent 74393ac commit 5dc0f69
Show file tree
Hide file tree
Showing 8 changed files with 428 additions and 6 deletions.
2 changes: 2 additions & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ All notable changes to experimental packages in this project will be documented

### :bug: (Bug Fix)

* fix(exporter-logs-otlp-http): set useHex to true [#3875](https://github.com/open-telemetry/opentelemetry-js/pull/3875) @Nico385412

### :books: (Refine Doc)

### :house: (Internal)
Expand Down
1 change: 1 addition & 0 deletions experimental/packages/exporter-logs-otlp-http/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"devDependencies": {
"@babel/core": "7.22.5",
"@opentelemetry/api-logs": "0.40.0",
"@opentelemetry/resources": "1.14.0",
"@types/mocha": "10.0.1",
"@types/node": "18.6.5",
"@types/sinon": "10.0.15",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class OTLPLogExporter
}

convert(logRecords: ReadableLogRecord[]): IExportLogsServiceRequest {
return createExportLogsServiceRequest(logRecords);
return createExportLogsServiceRequest(logRecords, true);
}

getDefaultUrl(config: OTLPExporterConfigBase): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class OTLPLogExporter
}

convert(logRecords: ReadableLogRecord[]): IExportLogsServiceRequest {
return createExportLogsServiceRequest(logRecords);
return createExportLogsServiceRequest(logRecords, true);
}

getDefaultUrl(config: OTLPExporterNodeConfigBase): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as assert from 'assert';
import * as sinon from 'sinon';

import * as Config from '../../src/platform/config';
import { OTLPLogExporter } from '../../src/platform/browser';
import { OTLPExporterConfigBase } from '@opentelemetry/otlp-exporter-base';
import { ReadableLogRecord } from '@opentelemetry/sdk-logs';
import { mockedReadableLogRecord } from '../logHelper';
import { ExportResultCode } from '@opentelemetry/core';

describe('OTLPLogExporter', () => {
let envSource: Record<string, any>;
let collectorExporter: OTLPLogExporter;
let collectorExporterConfig: OTLPExporterConfigBase;

afterEach(() => {
sinon.restore();
});

if (typeof process === 'undefined') {
envSource = globalThis as unknown as Record<string, any>;
Expand Down Expand Up @@ -61,4 +70,79 @@ describe('OTLPLogExporter', () => {
assert.strictEqual(getDefaultUrl.callCount, 2);
});
});

describe('export - common', () => {
let spySend: any;
beforeEach(() => {
spySend = sinon.stub(OTLPLogExporter.prototype, 'send');
collectorExporter = new OTLPLogExporter(collectorExporterConfig);
});

it('should export spans as otlpTypes.Spans', done => {
const logs: ReadableLogRecord[] = [];
logs.push(Object.assign({}, mockedReadableLogRecord));

collectorExporter.export(logs, () => {});
setTimeout(() => {
const log = spySend.args[0][0][0] as ReadableLogRecord;
assert.deepStrictEqual(logs[0], log);
done();
});
assert.strictEqual(spySend.callCount, 1);
});

describe('when exporter is shutdown', () => {
it(
'should not export anything but return callback with code' +
' "FailedNotRetryable"',
async () => {
const spans: ReadableLogRecord[] = [];
spans.push(Object.assign({}, mockedReadableLogRecord));
await collectorExporter.shutdown();
spySend.resetHistory();

const callbackSpy = sinon.spy();
collectorExporter.export(spans, callbackSpy);
const returnCode = callbackSpy.args[0][0];

assert.strictEqual(
returnCode.code,
ExportResultCode.FAILED,
'return value is wrong'
);
assert.strictEqual(spySend.callCount, 0, 'should not call send');
}
);
});
describe('when an error occurs', () => {
it('should return failed export result', done => {
const spans: ReadableLogRecord[] = [];
spans.push(Object.assign({}, mockedReadableLogRecord));
spySend.throws({
code: 100,
details: 'Test error',
metadata: {},
message: 'Non-retryable',
stack: 'Stack',
});
const callbackSpy = sinon.spy();
collectorExporter.export(spans, callbackSpy);
setTimeout(() => {
const returnCode = callbackSpy.args[0][0];
assert.strictEqual(
returnCode.code,
ExportResultCode.FAILED,
'return value is wrong'
);
assert.strictEqual(
returnCode.error.message,
'Non-retryable',
'return error message is wrong'
);
assert.strictEqual(spySend.callCount, 1, 'should call send');
done();
});
});
});
});
});
166 changes: 166 additions & 0 deletions experimental/packages/exporter-logs-otlp-http/test/logHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { HrTime, TraceFlags } from '@opentelemetry/api';
import { SeverityNumber } from '@opentelemetry/api-logs';
import { Resource } from '@opentelemetry/resources';
import * as assert from 'assert';
import { VERSION } from '@opentelemetry/core';
import {
IAnyValue,
IExportLogsServiceRequest,
IKeyValue,
ILogRecord,
IResource,
} from '@opentelemetry/otlp-transformer';
import { ReadableLogRecord } from '@opentelemetry/sdk-logs';

export const mockedReadableLogRecord: ReadableLogRecord = {
resource: Resource.default().merge(
new Resource({
'resource-attribute': 'some resource-attr value',
})
),
instrumentationScope: {
name: 'scope_name_1',
version: '0.1.0',
schemaUrl: 'http://url.to.schema',
},
hrTime: [1680253513, 123241635] as HrTime,
hrTimeObserved: [1680253513, 123241635] as HrTime,
attributes: {
'some-attribute': 'some attribute value',
},
severityNumber: SeverityNumber.ERROR,
severityText: 'error',
body: 'some_log_body',
spanContext: {
traceFlags: TraceFlags.SAMPLED,
traceId: '1f1008dc8e270e85c40a0d7c3939b278',
spanId: '5e107261f64fa53e',
},
};
export function ensureExportedAttributesAreCorrect(attributes: IKeyValue[]) {
assert.deepStrictEqual(
attributes,
[
{
key: 'some-attribute',
value: {
stringValue: 'some attribute value',
},
},
],
'exported attributes are incorrect'
);
}

export function ensureExportedBodyIsCorrect(body?: IAnyValue) {
assert.deepStrictEqual(
body,
{ stringValue: 'some_log_body' },
'exported attributes are incorrect'
);
}

export function ensureExportedLogRecordIsCorrect(logRecord: ILogRecord) {
ensureExportedBodyIsCorrect(logRecord.body);
ensureExportedAttributesAreCorrect(logRecord.attributes);
assert.strictEqual(
logRecord.timeUnixNano,
1680253513123241700,
'timeUnixNano is wrong'
);
assert.strictEqual(
logRecord.observedTimeUnixNano,
1680253513123241700,
'observedTimeUnixNano is wrong'
);
assert.strictEqual(
logRecord.severityNumber,
SeverityNumber.ERROR,
'severityNumber is wrong'
);
assert.strictEqual(logRecord.severityText, 'error', 'severityText is wrong');
assert.strictEqual(
logRecord.droppedAttributesCount,
0,
'droppedAttributesCount is wrong'
);
assert.strictEqual(logRecord.flags, TraceFlags.SAMPLED, 'flags is wrong');
}

export function ensureResourceIsCorrect(resource: IResource) {
assert.deepStrictEqual(resource, {
attributes: [
{
key: 'service.name',
value: {
stringValue: `unknown_service:${process.argv0}`,
value: 'stringValue',
},
},
{
key: 'telemetry.sdk.language',
value: {
stringValue: 'nodejs',
value: 'stringValue',
},
},
{
key: 'telemetry.sdk.name',
value: {
stringValue: 'opentelemetry',
value: 'stringValue',
},
},
{
key: 'telemetry.sdk.version',
value: {
stringValue: VERSION,
value: 'stringValue',
},
},
{
key: 'resource-attribute',
value: {
stringValue: 'some resource-attr value',
value: 'stringValue',
},
},
],
droppedAttributesCount: 0,
});
}

export function ensureExportLogsServiceRequestIsSet(
json: IExportLogsServiceRequest
) {
const resourceLogs = json.resourceLogs;
assert.strictEqual(resourceLogs?.length, 1, 'resourceLogs is missing');

const resource = resourceLogs?.[0].resource;
assert.ok(resource, 'resource is missing');

const scopeLogs = resourceLogs?.[0].scopeLogs;
assert.strictEqual(scopeLogs?.length, 1, 'scopeLogs is missing');

const scope = scopeLogs?.[0].scope;
assert.ok(scope, 'scope is missing');

const logRecords = scopeLogs?.[0].logRecords;
assert.strictEqual(logRecords?.length, 1, 'logs are missing');
}
Loading

0 comments on commit 5dc0f69

Please sign in to comment.