@jufab/opentelemetry-angular-interceptor
    TypeScript icon, indicating that this package has built-in type declarations

    1.0.1 • Public • Published

    OpenTelemetry Angular Interceptor

    @jufab/opentelemetry-angular-interceptor is an Angular Library to deploy OpenTelemetry in your Angular application

    This library uses opentelemetry-js package

    Only works for Angular >= 9.0.0

    More info : https://jufab.github.io/opentelemetry-angular-interceptor/

    npm version codecov

    Table of contents

    Getting started

    Content

    This library offers two possibilities to use it in Angular App :

    Installation

    With npm :

    npm i @jufab/opentelemetry-angular-interceptor && npm i @opentelemetry/api @opentelemetry/sdk-trace-web @opentelemetry/sdk-trace-base @opentelemetry/core @opentelemetry/semantic-conventions @opentelemetry/resources @opentelemetry/exporter-trace-otlp-http @opentelemetry/exporter-zipkin @opentelemetry/propagator-b3 @opentelemetry/propagator-jaeger @opentelemetry/context-zone-peer-dep @opentelemetry/instrumentation @opentelemetry/instrumentation-document-load @opentelemetry/instrumentation-fetch @opentelemetry/instrumentation-xml-http-request @opentelemetry/propagator-aws-xray --save-dev
    

    Configuration

    Use the "OpentelemetryConfig" interface to configure the Tracer

    export interface OpenTelemetryConfig {
      commonConfig: CommonCollectorConfig;
      batchSpanProcessorConfig?: BatchSpanProcessorConfig;
      otelcolConfig?: OtelCollectorConfig;
      jaegerPropagatorConfig?: JaegerPropagatorConfig;
      zipkinConfig?: ZipkinCollectorConfig;
      b3PropagatorConfig?: B3PropagatorConfig;
      instrumentationConfig?: InstrumentationConfig;
    }

    Example global Configuration

    From the interceptor-example

    opentelemetryConfig: {
        commonConfig: {
          console: true, //(boolean) Display trace on console
          production: false, //(boolean) Send trace with BatchSpanProcessor (true) or SimpleSpanProcessor (false)
          logBody: true, //(boolean) true add body in a log, nothing otherwise
          serviceName: 'interceptor-example', //Service name send in trace
          probabilitySampler: '0.7', //Samples a configurable percentage of traces, string value between '0' to '1'
          logLevel:DiagLogLevel.ALL //(Enum) DiagLogLevel is an Enum from @opentelemetry/api
        },
        batchSpanProcessorConfig: { //Only if production = true in commonConfig
          maxQueueSize: '2048', // The maximum queue size. After the size is reached spans are dropped.
          maxExportBatchSize: '512', // The maximum batch size of every export. It must be smaller or equal to maxQueueSize.
          scheduledDelayMillis: '5000', // The interval between two consecutive exports
          exportTimeoutMillis: '30000', // How long the export can run before it is cancelled
        },
        otelcolConfig: {
          url: 'http://localhost:4318/v1/traces', //URL of opentelemetry collector
        },
        jaegerPropagatorConfig: {
          customHeader: 'custom-header',
        }
      }

    From the instrumentation-example

    backendApp.get('/api/config', (req,res) => {
      return res.status(200).send({
        commonConfig: {
          console: true, // Display trace on console
          production: true, // Send Trace with BatchSpanProcessor (true) or SimpleSpanProcessor (false)
          serviceName: 'instrumentation-example', // Service name send in trace
          probabilitySampler: '0.75', // 75% sampling
          logLevel: 99 //ALL Log, DiagLogLevel is an Enum from @opentelemetry/api
        },
        otelcolConfig: {
          url: 'http://localhost:4318/v1/traces', // URL of opentelemetry collector
        },
        instrumentationConfig: {
          xmlHttpRequest: true,
          fetch: true,
          documentLoad: true,
        }
      });
    })

    Common Configuration

    • console: (boolean) Display trace on console if true
    • production: (boolean)Send trace via BatchSpanProcessor (Async) or SimpleSpanProcessor (Sync) : It's recommend to use BatchSpanProcessor on Production.
    • serviceName: (string) Service name in your trace
    • probabilitySampler: (string) Samples a configurable percentage of traces, value between 0 to 1
    • logBody: (boolean) true add body in a log, nothing otherwise
    • logLevel: (DiagLogLevel) log level

    BatchSpanProcessor Configuration

    This configuration applies if production is true in commonConfig.

    • maxQueueSize: (string) The maximum queue size. After the size is reached spans are dropped.
    • maxExportBatchSize: (string) The maximum batch size of every export. It must be smaller or equal to maxQueueSize.
    • scheduledDelayMillis: (string) The interval between two consecutive exports
    • exportTimeoutMillis: (string) How long the export can run before it is cancelled

    OpenTelemetry-collector Configuration

    Jaeger Propagator Configuration

    Zipkin Exporter Configuration

    • url: (string) url of zipkin collector (default : http://localhost:9411/api/v2/spans)
    • headers: list of custom header (more info : hhttps://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-zipkin)

    B3 Propagator Configuration

    Instrumentation Configuration

    this configuration is only for the instrumentation Mode

    • xmlHttpRequest: (boolean) Activate XmlHttpRequest plugin
    • fetch:(boolean) Activate fetch plugin
    • documentLoad: (boolean) Activate documentLoad plugin

    External Configuration

    Instrumentation example project have an external configuration to show how you can do it.

    Angular module

    You need 3 modules to add to your application.

    Commons Module

    You add this modules in your application module (generally app.module.ts)

    Exporter module

    There is 4 exporters:

    Propagator module

    there is 6 propagators (more info about propagator: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-core)

    Interceptor Module

    Just add OpenTelemetryInterceptorModule to insert Interceptor

    import { NgModule } from '@angular/core';
    ...
    import { AppComponent } from './app.component';
    import { HttpClientModule } from '@angular/common/http';
    import { OpenTelemetryInterceptorModule, OtelColExporterModule, CompositePropagatorModule } from '@jufab/opentelemetry-angular-interceptor';
    import { environment } from '../environments/environment';
    ...
    
    @NgModule({
      declarations: [AppComponent, ...],
      imports: [
        ...
        HttpClientModule,
        //Insert module OpenTelemetryInterceptorModule with configuration, HttpClientModule is used for interceptor
        OpenTelemetryInterceptorModule.forRoot(environment.opentelemetryConfig),
        //Insert OtelCol exporter module
        OtelColExporterModule,
        //Insert propagator module
        CompositePropagatorModule,
        ...
      ],
      providers: [],
      bootstrap: [AppComponent],
    })
    export class AppModule {}

    Instrumentation Module

    Declare this OtelWebTracerModule to configure instrumentation

    ...
    import { OtelColExporterModule, CompositePropagatorModule, OtelWebTracerModule } from 'projects/opentelemetry-interceptor/src/public-api';
    ...
    
    @NgModule({
      declarations: [AppComponent, ...],
      imports: [
        ...
        // OtelCol Exporter Module
        OtelColExporterModule,
        // Composite Propagator Module
        CompositePropagatorModule,
        // OtelWebTracerModule to configure instrumentation component.
        OtelWebTracerModule.forRoot(environment.openTelemetryConfig),
        ...
      ],
      providers: [],
      bootstrap: [AppComponent],
    })
    export class AppModule { }

    Interceptor Module And Instrumentation Module

    Don't use them at the same time : you're going to have the same trace twice.

    Injection token

    This library exposes injection token. You can use them to override or customize.

    Component otel-instrumentation

    A component named otel-instrumentation must be add in your application.

    In instrumentation-example, this component is in app.component.html like this :

    ...
    <otel-instrumentation></otel-instrumentation>
    ...

    there is no configuration/directive need : all is in OtelWebTracerModule

    (Optional) Logging in OtelColExporterModule

    You can add a logger to the OtelColExporterModule with the OTLP_LOGGER token.

    You can use a custom logger which implements the DiagLogger in @opentelemetry/api.

    Or, you can use an existing logger which implements the same functions (error, warn, info, debug) like ngx-logger.

    NGXLogger

    You can use ngx-logger.

    In your appModule, insert LoggerModule and configure it

    @NgModule({
      ...
      imports: [
        LoggerModule.forRoot(environment.loggerConfig),
      ]
      ...

    And use OTLP_LOGGER token to inject NGXLogger

    @NgModule({
      ...
      providers: [
        ...
        { provide: OTLP_LOGGER, useExisting: NGXLogger }
        ...
      ]

    Don't forget to set "logLevel" in Common Configuration (Level must be the same between NGXLogger and common configuration)

    You can see an example in the interceptor-example.

    (Optional) Add span attributes during interception

    This option is only available for Interceptor Module

    Implement a CustomSpan and the method add(span: Span, request: HttpRequest<unknown>, response: HttpResponse<unknown> | HttpErrorResponse): Span

    • span : Current span, you can set or get attributes
    • request : Current request in interceptor
    • response : Current response in interceptor

    Implement CustomSpan class like :

    class CustomSpanImpl implements CustomSpan {
      add(span: Span, request: HttpRequest<unknown>, response: HttpResponse<unknown> | HttpErrorResponse): Span {
        span.setAttribute('mycustom.key', request.params + ";" + response.status);
        return span;
      }
    }

    Inject it in you App module with CUSTOM_SPAN :

    @NgModule({
      ...
      providers: [
        ...
        { provide: CUSTOM_SPAN, useClass: CustomSpanImpl }
        ...
      ]

    You can see an example in the interceptor-example.

    How it works

    This library is based on HttpClientModule and the HTTP_INTERCEPTORS

    OpenTelemetryInterceptor implement an HttpInterceptor and the intercept method.

    This implementation initialise a WebTracerProvider, create a Span and add header propagation in the current call.

    The response body is adding by an event in span.

    Example

    This project has two example Angular Application:

    You can see how configure and insert all modules.

    You can althought test opentelemetry-angular-interceptor with this two applications.

    Run

    Interceptor

    To start this Interceptor example application, run command :

    npm run start:complete-interceptor-example
    

    and open the application at http://localhost:4200

    Instrumentation

    To start this Instrumentation example application, run command :

    npm run start:complete-instrumentation-example
    

    and open the application at http://localhost:4200

    [Optional] Result in OpenTelemetry-collector

    If you want to see the result in a collector *, there's a docker-compose available in this project.

    You can start it with this command :

    docker-compose -f collector/docker-compose.yaml up -d
    

    Go to the jaeger application (http://localhost:16686) to see result.

    More info about the collector here : https://github.com/open-telemetry/opentelemetry-collector

    * without an Agent or a Collector you can see an error in your browser about sending a "trace".

    Troubleshoot

    Angular 10 Warning

    WARNING in xxx/fesm2015/jufab-opentelemetry-angular-interceptor.js depends on '@opentelemetry/web'. CommonJS or AMD dependencies can cause optimization bailouts.
    For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
    
    WARNING in xxx/fesm2015/jufab-opentelemetry-angular-interceptor.js depends on '@opentelemetry/core'. CommonJS or AMD dependencies can cause optimization bailouts.
    For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
    
    WARNING in xxx/fesm2015/jufab-opentelemetry-angular-interceptor.js depends on '@opentelemetry/tracing'. CommonJS or AMD dependencies can cause optimization bailouts.
    For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
    
    WARNING in xxx/fesm2015/jufab-opentelemetry-angular-interceptor.js depends on '@opentelemetry/api'. CommonJS or AMD dependencies can cause optimization bailouts.
    For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
    
    WARNING in xxx/fesm2015/jufab-opentelemetry-angular-interceptor.js depends on '@opentelemetry/exporter-collector/build/src/platform/browser'. CommonJS or AMD dependencies can cause optimization bailouts.
    For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

    Add to your angular.json

    "options": {
      "allowedCommonJsDependencies": [
        "@opentelemetry/api",
        "@opentelemetry/exporter-collector",
        "@opentelemetry/exporter-zipkin",
        "@opentelemetry/tracing",
        "@opentelemetry/web",
        "@opentelemetry/core",
        "@opentelemetry/propagator-jaeger",
        "@opentelemetry/propagator-b3",
        "@opentelemetry/instrumentation",
        "@opentelemetry/instrumentation-xml-http-request",
        "@opentelemetry/instrumentation-document-load",
        "@opentelemetry/instrumentation-fetch",
        "@opentelemetry/context-zone-peer-dep"
      ],

    Other

    Error Fix
    error TS2694: Namespace 'NodeJS' has no exported member 'Timeout'. Need dependence @type/node >= 12.0.2
    error TS1086: An accessor cannot be declared in an ambient context. Need dependence typescript >= 3.6.0

    Install

    npm i @jufab/opentelemetry-angular-interceptor

    DownloadsWeekly Downloads

    440

    Version

    1.0.1

    License

    Apache-2.0

    Unpacked Size

    486 kB

    Total Files

    74

    Last publish

    Collaborators

    • jufab