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: remove injection options #312

Merged
merged 20 commits into from
Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ jobs:
- name: Test mixed example
working-directory: test/examples
run: docker-compose -f e2e.docker-compose.yml -f mixed.override.yml -f published.override.yml up --exit-code-from test
# Should be enabled when 0.13 is released with exposing defaultLogHook
# - name: Test log-injection example
# working-directory: test/examples
# run: docker-compose -f e2e.docker-compose.yml -f log-injection.override.yml -f published.override.yml up --exit-code-from test

e2e:
runs-on: ubuntu-latest
Expand All @@ -101,3 +105,6 @@ jobs:
- name: Test mixed example
working-directory: test/examples
run: docker-compose -f e2e.docker-compose.yml -f mixed.override.yml up --exit-code-from test
- name: Test log-injection example
working-directory: test/examples
run: docker-compose -f e2e.docker-compose.yml -f log-injection.override.yml up --exit-code-from test
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "feat: remove logInjectionEnabled and SPLUNK_LOGS_INJECTION options",
"packageName": "@splunk/otel",
"email": "[email protected]",
"dependentChangeType": "patch"
}
2 changes: 2 additions & 0 deletions examples/log-injection/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
package-lock.json
30 changes: 30 additions & 0 deletions examples/log-injection/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const { trace, SpanStatusCode, context } = require('@opentelemetry/api');

const log = require('pino')();
const doWork = () => {
log.info('before work');
while (Date.now() - start < 500) {}
log.info('after work work');
};

// There is no active span right now so no trace id to report.
// Following log event will not have trace data injected.
log.info('starting...');

const start = Date.now();
const tracer = trace.getTracer('splunk-otel-example-log-injection');
const span = tracer.startSpan('main');
const spanContext = trace.setSpan(context.active(), span);

// This will run a function inside a context which has an active span.
context.with(spanContext, doWork);

// Even though the span has not ended yet it's not active in current context
// anymore and thus will not be logged.
log.info('done!');
span.end();

setTimeout(() => {
// wait for the spans to be flushed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about ForceFlush? spec implementation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our SDK currently doesn't provide access to the NodeTracerProvider we initialize.
#331

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using API to get the global one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That currently gives us ProxyTracerProvider, which doesn't have forceFlush either and has NTP under private property. I don't have a full understanding of the correct way to solve this situation and that's why I'd like to leave it for now and figure it out after the next release.

console.log('Spans flushed');
}, 5000);
27 changes: 27 additions & 0 deletions examples/log-injection/log-injection.tracer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { getInstrumentations } = require('@splunk/otel/lib/instrumentations');
const { defaultLogHook } = require('@splunk/otel/lib/instrumentations/logging');
const { PinoInstrumentation } = require('@opentelemetry/instrumentation-pino');

// an example logHook to add common resource attributes to every log message
const logHook = (span, logRecord) => {
// thrown errors in logHooks are ignored to avoid crashing due to instrumentation
// logic. Deciding on using a try-catch comes down to the usecase and performance requirements.
try {
// defaultLogHook does the default behavior of adding service.[name, version] and deployment.environment
// defaultLogHook(span, logRecord); // supported from 0.13
logRecord['my.attribute'] = 'my.value';
} catch (e) {
console.error(e);
throw e;
}
};

require('@splunk/otel').startTracing({
serviceName: 'example',
instrumentations: [
...getInstrumentations(),
new PinoInstrumentation({
logHook: logHook,
}),
],
});
16 changes: 16 additions & 0 deletions examples/log-injection/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "splunk-otel-example-log-injection",
"private": true,
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node -r ./log-injection.tracer.js index.js",
"basic": "node -r @splunk/otel/instrument index.js"
},
"dependencies": {
"@opentelemetry/api": "^1.0.3",
"@opentelemetry/instrumentation-pino": "^0.23.0",
"@splunk/otel": "^0.12.0",
"pino": "^6.13.3"
}
}
61 changes: 24 additions & 37 deletions src/instrumentations/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,61 +14,48 @@
* limitations under the License.
*/

import { Options } from '../options';
import { Span } from '@opentelemetry/sdk-trace-base';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type LogRecord = Record<string, any>;

export const defaultLogHook = (span: Span, record: LogRecord) => {
record['service.name'] =
span.resource.attributes[SemanticResourceAttributes.SERVICE_NAME];

const version =
span.resource.attributes[SemanticResourceAttributes.SERVICE_VERSION];
if (version !== undefined) {
record['service.version'] = version;
}

const environment =
span.resource.attributes[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT];
if (environment !== undefined) {
record['service.environment'] = environment;
}
};

export function configureLogInjection(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
instrumentation: any,
options: Options
instrumentation: any
) {
if (!options.logInjectionEnabled) {
return;
}

if (
typeof instrumentation['setConfig'] !== 'function' ||
typeof instrumentation['getConfig'] !== 'function'
) {
return;
}

const logHook = (span: Span, record: LogRecord) => {
record['service.name'] =
span.resource.attributes[SemanticResourceAttributes.SERVICE_NAME];

const version =
span.resource.attributes[SemanticResourceAttributes.SERVICE_VERSION];
if (version !== undefined) {
record['service.version'] = version;
}

const environment =
span.resource.attributes[
SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT
];
if (environment !== undefined) {
record['service.environment'] = environment;
}
};

let config = instrumentation.getConfig();
const config = instrumentation.getConfig();

if (config === undefined) {
config = { logHook };
} else if (config.logHook !== undefined) {
const original = config.logHook;
config.logHook = function (this: unknown, span: Span, record: LogRecord) {
logHook(span, record);
original.call(this, span, record);
};
} else {
config.logHook = logHook;
return instrumentation.setConfig({ logHook: defaultLogHook });
}

instrumentation.setConfig(config);
if (config.logHook === undefined) {
config.logHook = defaultLogHook;
return instrumentation.setConfig(config);
}
}
6 changes: 0 additions & 6 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ export interface Options {
accessToken: string;
maxAttrLength: number;
serverTimingEnabled: boolean;
logInjectionEnabled: boolean;
instrumentations: InstrumentationOption[];
tracerConfig: NodeTracerConfig;
spanExporterFactory: SpanExporterFactory;
Expand Down Expand Up @@ -86,10 +85,6 @@ export function _setDefaultOptions(options: Partial<Options> = {}): Options {
);
}

if (options.logInjectionEnabled === undefined) {
options.logInjectionEnabled = getEnvBoolean('SPLUNK_LOGS_INJECTION', false);
}

const extraTracerConfig = options.tracerConfig || {};

let resource = new EnvResourceDetector().detect();
Expand Down Expand Up @@ -138,7 +133,6 @@ export function _setDefaultOptions(options: Partial<Options> = {}): Options {
accessToken: options.accessToken,
maxAttrLength: options.maxAttrLength,
serverTimingEnabled: options.serverTimingEnabled,
logInjectionEnabled: options.logInjectionEnabled,
instrumentations: options.instrumentations,
tracerConfig: tracerConfig,
spanExporterFactory: options.spanExporterFactory,
Expand Down
2 changes: 1 addition & 1 deletion src/tracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function configureInstrumentations(options: Options) {
case '@opentelemetry/instrumentation-bunyan':
case '@opentelemetry/instrumentation-pino':
case '@opentelemetry/instrumentation-winston':
configureLogInjection(instr, options);
configureLogInjection(instr);
break;
}
}
Expand Down
2 changes: 2 additions & 0 deletions test/examples/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ FROM base as published

RUN cd examples/basic && npm install
RUN cd examples/express && npm install
RUN cd examples/log-injection && npm install
RUN cd examples/mixed && npm install

## Project root doesn't have start script defined
Expand All @@ -31,4 +32,5 @@ RUN npm run compile
RUN mv `npm pack` /tmp/splunk-otel.tgz
RUN cd examples/basic && npm i /tmp/splunk-otel.tgz
RUN cd examples/express && npm i /tmp/splunk-otel.tgz
RUN cd examples/log-injection && npm i /tmp/splunk-otel.tgz
RUN cd examples/mixed && npm i /tmp/splunk-otel.tgz
2 changes: 2 additions & 0 deletions test/examples/e2e.docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ services:
dockerfile: test/examples/Dockerfile
working_dir: /home/node/app/examples/basic
env_file: ./basic/app.env
depends_on:
- collector
test:
build:
context: .
Expand Down
8 changes: 8 additions & 0 deletions test/examples/log-injection.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
services:
app:
working_dir: /home/node/app/examples/log-injection
env_file: ./log-injection/app.env
test:
command: node ./log-injection
environment:
COLLECTOR_URL: http://collector:8378
4 changes: 4 additions & 0 deletions test/examples/log-injection/app.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
OTEL_SERVICE_NAME='log-injection-example'
OTEL_RESOURCE_ATTRIBUTES='deployment.environment=dev'
OTEL_LOG_LEVEL='DEBUG'
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:55681/v1/traces
14 changes: 14 additions & 0 deletions test/examples/log-injection/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const {
assertSpans,
logSpanTable,
request,
waitSpans,
} = require('../utils.js');
const snapshot = require('./snapshot.js');

waitSpans(snapshot.length).then((data) => {
logSpanTable(data);
assertSpans(data, snapshot);
}).then(() => {
console.log(`${snapshot.length} span(s) validated.`);
});
19 changes: 19 additions & 0 deletions test/examples/log-injection/snapshot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// a console.log from a previous run
module.exports = [
{
traceId: 'DUaJffuwfAqa53DY7yipHA==',
id: 'QD8nT/PZGF8=',
startTime: '2021-09-28T08:23:37.842474752Z',
name: 'main',
kind: 'internal',
parentSpanId: undefined,
parent: undefined,
references: undefined,
status: { code: undefined },
attributes: {
'otel.library.name': 'splunk-otel-example-log-injection',
'span.kind': 'internal',
'status.code': undefined
}
}
];
Loading