2

I am trying to integrate Opentelemetry (Otl) in my Angular application to trace the frontend calls. Everything works fine and I am able to see the calls in the Zipkin.

But the only problem is that it is showing it as "unknown_service" in the Zipkin interface.

Below is my entire Angular code and Zipkin screenshot as well. This is just a sample application. But my requirement is that I am going to integrate the Opentelemetry code in the http interceptor so that it will be easy to maintain at one place instead of every service call. Also service.name should be passed dynamically so that it will be traced in Zipkin.

How can I add a service name before it gets called?

import { Component, OnInit } from '@angular/core';
import {ZipkinServicesService} from './zipkin-services.service';


// Opentelemetry components
import { context, trace } from '@opentelemetry/api';
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import { CollectorTraceExporter } from '@opentelemetry/exporter-collector';
import { B3Propagator } from '@opentelemetry/propagator-b3';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';

@Component({
  selector: 'app-zipkin-integration',
  templateUrl: './zipkin-integration.component.html',
  styleUrls: ['./zipkin-integration.component.scss']
})
export class ZipkinIntegrationComponent implements OnInit {

  respData: string;
  webTracerWithZone;
  

  constructor(
    public zipkinService: ZipkinServicesService,
  ) {

    const providerWithZone = new WebTracerProvider();

    const options = {
      url: 'http://localhost:9411/api/v2/spans',
      serviceName: 'interceptor-example',// This is NOT working.
    }
    const exporter = new ZipkinExporter(options);

    const zipKinProcessor = new SimpleSpanProcessor(exporter);

    providerWithZone.addSpanProcessor(zipKinProcessor);

    providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
    providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new CollectorTraceExporter()));

    providerWithZone.register({
      contextManager: new ZoneContextManager(),
      propagator: new B3Propagator(),
    });

    registerInstrumentations({
      instrumentations: [
        new XMLHttpRequestInstrumentation({
          ignoreUrls: [/localhost:8090\/sockjs-node/],
          propagateTraceHeaderCorsUrls: [
            'https://httpbin.org/post',
          ],
        }),
      ],
    });

    this.webTracerWithZone = providerWithZone.getTracer('example-tracer-web');

   }

  ngOnInit(): void {
 
  }

  zipGet (){
    let i = 10;
    const span1 = this.webTracerWithZone.startSpan(`files-series-info-${i}`);
    let postData = [{
      no : 2,
      emp : 3
    }];
    context.with(trace.setSpan(context.active(), span1), () => {
      this.zipkinService.httpGet(postData).subscribe( (data: any) => {
        this.respData = data;
        // Opentelemetry after response.
        trace.getSpan(context.active()).addEvent('fetching-span1-completed');
        span1.end();
      });
    });
    
  }

  zipPost (){
    let postData = [{
      no : 1,
      emp : 2
    }];

    let i = 10;
    const span1 = this.webTracerWithZone.startSpan(`files-series-info-${i}`);

    context.with(trace.setSpan(context.active(), span1), () => {
      this.zipkinService.httpPost(postData).subscribe( (data: any) => {
        this.respData = data;
        // Opentelemetry after response.
        trace.getSpan(context.active()).addEvent('fetching-span1-completed');
        span1.end();
      });
    });
  }

}

enter image description here

halfer
  • 19,824
  • 17
  • 99
  • 186
Raja
  • 3,477
  • 12
  • 47
  • 89

2 Answers2

4

Service name must be set via resource as per the specification. I am not sure which version of js libs you are using. This should get you the service name.

import { Resource } from '@opentelemetry/resources';
import { ResourceAttributes } from '@opentelemetry/semantic-conventions'

...
...

const provider = new WebTracerProvider({
    resource: new Resource({
        [ResourceAttributes.SERVICE_NAME]: "interceptor-example"
    }),
});
Srikanth Chekuri
  • 1,944
  • 1
  • 9
  • 19
  • This is awesome. It is now started showing the Service name in the Zipkin. Thanks Srikanth. One small change here, instead of ResouceAttribute it will be SemanticResourceAttributes. Also Is there a way to update service name before the Span `"this.webTracerWithZone.startSpan(files-series-info-${i})"`? – Raja Aug 18 '21 at 15:46
  • No you aren't allowed to mutate the resource once set. Are you confusing span name with resource name? – Srikanth Chekuri Aug 18 '21 at 18:38
  • No. Actually my intension here is that I want to use this in HTTP interceptor so i have to change the service name based on that. So whenever a service call is triggered from Angular UI, I can pass the service name dynamically based on the request that i get. But again, I am not sure this is the proper way to handle in the UI side. In Java, these things are handled by java spring boot (sleuth). so this process is much simpler there. – Raja Aug 19 '21 at 14:12
  • `ResourceAttributes` has changed to `SemanticResourceAttributes` – Mick Feb 01 '22 at 06:49
  • @SrikanthChekuri: Any idea how can we add service name while using zipkin with angular 7 ? – Mak Jul 27 '22 at 12:11
0

use providerConfig to set service name. follow code set service name to "SPA Test".

import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { ZipkinExporter, ExporterConfig } from '@opentelemetry/exporter-zipkin';

const providerConfig = {
  resource: new Resource({
      [SemanticResourceAttributes.SERVICE_NAME]: "SPA Test"
  }),
};
const provider = new WebTracerProvider(providerConfig);

const zipkinOptions: ExporterConfig = {
  url: "http://localhost:9411/api/v2/spans"
};
const exporter = new ZipkinExporter(zipkinOptions);
const zipkinProcessor = new BatchSpanProcessor(exporter);
provider.addSpanProcessor(zipkinProcessor);
provider.register();

var tracer = provider.getTracer(CustomersComponent.name, "0.1.0");
var span = tracer.startSpan(CustomersComponent.name);
console.info(span);
span.end();
guanjun
  • 1
  • 2