npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@jufab/opentelemetry-angular-interceptor

v1.9.0

Published

@jufab/opentelemetry-angular-interceptor is an Angular Library to deploy [OpenTelemetry](https://opentelemetry.io/) in your Angular application

Downloads

7,851

Readme

OpenTelemetry Angular Interceptor

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

This library uses opentelemetry-js package

Use Angular >= 13.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

Configuration

Use the "OpentelemetryConfig" interface to configure the Tracer

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

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
      resourceAttributes: { // extra resource attributes like service.namespace
        [ATTR_SERVICE_NAMESPACE]: 'namespace'
      },
      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
      resourceAttributes: { // extra resource attributes like service.namespace
        'service.namespace': 'namespace'
      },
      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
    }
  });
})

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
  • resourceAttributes: list of extra resource attributes
  • 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

  • url: (string) url of opentelemetry collector (default : http://localhost:4318/v1/traces)
  • headers: list of custom header (more info: https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-http)
  • concurrencyLimit (string) : An optional limit on pending requests (more info : https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-http)
  • timeoutMillis (string): Maximum time the OTLP exporter will wait for each batch export. The default value is 10000ms (more info : https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/exporter-trace-otlp-http)

Jaeger Propagator Configuration

  • customHeader: (string) custom header (more info : https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-propagator-jaeger)

Zipkin Exporter Configuration

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

B3 Propagator Configuration

  • multiHeader : (string) Single or Multi Header for b3propagator (default: multi). Value : 'O' (single), '1' (multi) (more info: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-propagator-b3)

Ignore URL Configuration

  • urls : (Array<string | RegExp>) URLs that partially match any regex in ignoreUrls will not be traced. In addition, URLs that are exact matches of strings in ignoreUrls will also not be traced

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:

  • NoopSpanExporterModule : This a fake exporter
  • OtelColExporterModule : OpenTelemetry exporter (more info : https://github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-trace-otlp-http)
  • ConsoleSpanExporterModule : Console Exporter
  • ZipkinExporterModule : Zipkin Exporter (more info : https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-zipkin)
Propagator module

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

  • NoopHttpTextPropagatorModule : This is a fake propagator
  • B3PropagatorModule : Use B3 propagator
  • W3CTraceContextPropagatorModule : Use W3CTraceContext propagator
  • JaegerHttpTracePropagatorModule : Use JaegerHttpPropagator (more info about this one: https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-propagator-jaeger)
  • AwsXrayPropagatorModule : Use AWS X-Ray propagator
  • CompositePropagatorModule : use all of the propagator

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.

You need to provide Web instrumentation on the OTEL_INSTRUMENTATION_PLUGINS token in providers section of NgModule

Example in instrumentation-example project

...
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: [
    {provide: OTEL_INSTRUMENTATION_PLUGINS, useValue: [new XMLHttpRequestInstrumentation()]}
  ],
  bootstrap: [AppComponent],
})
export class AppModule { }

This module uses APP_INITIALIZER token to load instrumentation (multi:true). No component needs now

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.

(Optional) Logging in OtelColExporterModule

You can add a logger to the OtelColExporterModule with the OTEL_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 OTEL_LOGGER token to inject NGXLogger

@NgModule({
  ...
  providers: [
    ...
    { provide: OTEL_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 OTEL_CUSTOM_SPAN :

@NgModule({
  ...
  providers: [
    ...
    { provide: OTEL_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|