Skip to content

Commit

Permalink
chore(extension-tracing): start to use opentelemetry
Browse files Browse the repository at this point in the history
  • Loading branch information
raymondfeng committed May 18, 2020
1 parent 2af06b7 commit 0181c3a
Show file tree
Hide file tree
Showing 8 changed files with 415 additions and 141 deletions.
319 changes: 269 additions & 50 deletions extensions/tracing/package-lock.json

Large diffs are not rendered by default.

25 changes: 16 additions & 9 deletions extensions/tracing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,25 @@
"copyright.owner": "IBM Corp.",
"license": "MIT",
"dependencies": {
"@loopback/core": "^1.10.6",
"@loopback/rest": "^1.22.0",
"@types/jaeger-client": "^3.15.1",
"@loopback/core": "^2.5.0",
"@loopback/express": "^1.1.0",
"@loopback/rest": "^4.0.0",
"@opentelemetry/api": "^0.8.0",
"@opentelemetry/exporter-jaeger": "^0.8.0",
"@opentelemetry/exporter-prometheus": "^0.8.0",
"@opentelemetry/metrics": "^0.8.0",
"@opentelemetry/node": "^0.8.0",
"@opentelemetry/plugin-http": "^0.8.0",
"@opentelemetry/plugin-https": "^0.8.0",
"@opentelemetry/tracing": "^0.8.0",
"@types/jaeger-client": "^3.15.4",
"debug": "^4.1.1",
"jaeger-client": "^3.17.1",
"opentracing": "^0.14.4",
"p-event": "^4.1.0"
"jaeger-client": "^3.18.0"
},
"devDependencies": {
"@loopback/build": "^2.0.15",
"@loopback/eslint-config": "^4.1.3",
"@loopback/testlab": "^1.9.3",
"@loopback/build": "^5.3.1",
"@loopback/eslint-config": "^6.0.6",
"@loopback/testlab": "^3.1.3",
"@types/debug": "^4.1.5",
"@types/node": "^10.14.13"
},
Expand Down
73 changes: 0 additions & 73 deletions extensions/tracing/src/interceptors/tracing.interceptor.ts

This file was deleted.

80 changes: 80 additions & 0 deletions extensions/tracing/src/middleware/tracing.middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/extension-tracing
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {bind, Provider, ValueOrPromise} from '@loopback/core';
import {asMiddleware, Middleware, MiddlewareContext} from '@loopback/express';
import openTelemetry, {propagation, Tracer} from '@opentelemetry/api';
import {JaegerExporter} from '@opentelemetry/exporter-jaeger';
import {BasicTracerProvider, SimpleSpanProcessor} from '@opentelemetry/tracing';
import debugFactory from 'debug';
import {TracingBindings} from '../keys';

const debug = debugFactory('loopback:tracing');

@bind(asMiddleware({group: 'tracing'}))
export class TracingMiddleware implements Provider<Middleware> {
private tracer: Tracer;

constructor() {
const provider = new BasicTracerProvider();

// Configure span processor to send spans to the exporter
const exporter = new JaegerExporter({serviceName: 'basic-service'});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

/**
* Initialize the OpenTelemetry APIs to use the BasicTracerProvider bindings.
*
* This registers the tracer provider with the OpenTelemetry API as the global
* tracer provider. This means when you call API methods like
* `opentelemetry.trace.getTracer`, they will use this tracer provider. If you
* do not register a global tracer provider, instrumentation which calls these
* methods will recieve no-op implementations.
*/
provider.register();
this.tracer = openTelemetry.trace.getTracer('loopback:tracer');
}

value() {
return this.intercept.bind(this);
}

async intercept<T>(reqCtx: MiddlewareContext, next: () => ValueOrPromise<T>) {
let reqSpanCtx = propagation.extract(
FORMAT_HTTP_HEADERS,
reqCtx.request.headers,
);
debug('Extracted span context: %s', reqSpanCtx);
let span;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (!reqSpanCtx || !(reqSpanCtx as any).traceId) {
span = this.tracer.startSpan(reqCtx.targetName);
reqSpanCtx = span.context();
debug('Inject a new span context: %s', reqSpanCtx);
this.tracer.inject(
reqSpanCtx,
FORMAT_HTTP_HEADERS,
reqCtx.request.headers,
);
} else {
const parentSpan = reqCtx.getSync(TracingBindings.SPAN, {
optional: true,
});
span = this.tracer.startSpan(reqCtx.targetName, {
references: [followsFrom(parentSpan?.context() ?? reqSpanCtx)],
});
if (debug.enabled) debug('A new span is started: %s', span.context());
}
debug('Span context at %s: %s', reqCtx.targetName, reqSpanCtx);

try {
reqCtx.bind(TracingBindings.SPAN).to(span);
return await next();
} finally {
span.finish();
if (debug.enabled) debug('The span is finished: %s', span.context());
}
}
}
21 changes: 21 additions & 0 deletions extensions/tracing/src/tracing.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
createBindingFromClass,
inject,
} from '@loopback/core';
import {NodeTracerProvider} from '@opentelemetry/node';
import {initTracerFromEnv} from 'jaeger-client';
import {TracingInterceptor} from './interceptors/tracing.interceptor';
import {TracingBindings} from './keys';
Expand All @@ -30,6 +31,8 @@ export class TracingComponent implements Component {
@config()
tracingConfig: TracingConfig = {serviceName: 'loopback'},
) {
setupNodeTraceProvider();

const tracer = initTracerFromEnv(tracingConfig, {
contextKey: LOOPBACK_TRACE_ID,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -38,3 +41,21 @@ export class TracingComponent implements Component {
this.application.add(createBindingFromClass(TracingInterceptor));
}
}

function setupNodeTraceProvider() {
const nodeTraceProvider = new NodeTracerProvider({
plugins: {
http: {
enabled: true,
// You may use a package name or absolute path to the file.
path: '@opentelemetry/plugin-http',
},
https: {
enabled: true,
// You may use a package name or absolute path to the file.
path: '@opentelemetry/plugin-https',
},
},
});
nodeTraceProvider.register();
}
9 changes: 0 additions & 9 deletions extensions/tracing/tsconfig.build.json

This file was deleted.

26 changes: 26 additions & 0 deletions extensions/tracing/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "@loopback/build/config/tsconfig.common.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"composite": true
},
"include": [
"src"
],
"references": [
{
"path": "../../packages/core/tsconfig.json"
},
{
"path": "../../packages/express/tsconfig.json"
},
{
"path": "../../packages/rest/tsconfig.json"
},
{
"path": "../../packages/testlab/tsconfig.json"
}
]
}
3 changes: 3 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@
{
"path": "extensions/metrics/tsconfig.json"
},
{
"path": "extensions/tracing/tsconfig.json"
},
{
"path": "packages/authentication/tsconfig.json"
},
Expand Down

0 comments on commit 0181c3a

Please sign in to comment.