jaeger-ui icon indicating copy to clipboard operation
jaeger-ui copied to clipboard

Add tracing to jaeger-ui package

Open psk001 opened this issue 1 year ago • 9 comments

Which problem is this PR solving?

Resolves issue 2307

Short description of the changes

Adds tracing module, which handles trace management and connection to jaeger all-in-one

psk001 avatar Aug 01 '23 08:08 psk001

@psk001 are you planning to address the comments, or should I close this PR?

yurishkuro avatar Aug 25 '23 03:08 yurishkuro

I have been working on the API route as you suggested

in jaeger query, I added another API endpoint as

aH.handleFunc(router, aH.sendToCollector, "/collector").Methods(http.MethodPost)
func (aH *APIHandler) sendToCollector(w http.ResponseWriter, r *http.Request) {

	aH.logger.Debug("Into collect trace controller")

	// aH.logger.Debug("trace received", zap.Stringer("traceId", traceID))

	// Read the request body
	bodyBytes, err := io.ReadAll(r.Body)
	if err != nil {
		aH.logger.Error("error reading request body", zap.Error(err))
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	// Create a new request to the collector
	collectorURL := "<collector-url>"
	collectorReq, err := http.NewRequest("POST", collectorURL, bytes.NewReader(bodyBytes))
	if err != nil {
		aH.logger.Error("error creating collector request", zap.Error(err))
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	// Set headers if needed
	// collectorReq.Header.Set("Authorization", "Bearer YOUR_ACCESS_TOKEN")

	// Make the request to the collector
	client := http.DefaultClient
	collectorResp, err := client.Do(collectorReq)
	if err != nil {
		aH.logger.Error("error sending trace to collector", zap.Error(err))
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}
	defer collectorResp.Body.Close()

	// Check the collector response and handle as needed
	if collectorResp.StatusCode != http.StatusOK {
		aH.logger.Error("collector returned non-OK status", zap.Int("status", collectorResp.StatusCode))
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	// Optionally read and log the collector response body
	// collectorRespBytes, _ := io.ReadAll(collectorResp.Body)
	// aH.logger.Debug("collector response", zap.String("body", string(collectorRespBytes)))

	aH.logger.Debug("returning from trace controller")
	aH.writeJSON(w, r, r.Body)
}

then in jaeger-ui , added tracing file with config as

import {
  BatchSpanProcessor,
  WebTracerProvider,
} from '@opentelemetry/sdk-trace-web';
import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
import { Resource } from '@opentelemetry/resources'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'

import prefixUrl from './utils/prefix-url';
export const DEFAULT_API_ROOT = prefixUrl('/api/');

const collectorOptions = {
  url: `${DEFAULT_API_ROOT}collector`,
  headers: {}, // an optional object containing custom headers to be sent with each request
  concurrencyLimit: 10, // an optional limit on pending requests
};

const provider = new WebTracerProvider({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'Jaeger UI' || process.env.REACT_APP_NAME
  })
});
const exporter = new OTLPTraceExporter(collectorOptions);
provider.addSpanProcessor(new BatchSpanProcessor(exporter));

registerInstrumentations({
  instrumentations: [
    getWebAutoInstrumentations({
      '@opentelemetry/instrumentation-xml-http-request': {
        clearTimingResources: true,
      },
    }),
    new DocumentLoadInstrumentation()
  ],
});

provider.register();

next, used it in the index.html

<body>
    <div id="jaeger-ui-root"></div>
    <!--
      This file is the main entry point for the Jaeger UI application.
      See https://vitejs.dev/guide/#index-html-and-project-root for more information
      on how asset references are managed by the build system.
    -->
    <script type="module" src="/src/index.jsx"></script>
</body>

With the above changes, Im getting the traces in the at the query backend , but the Im unable to generate a different collector so as to display those traces in ui.

psk001 avatar Aug 25 '23 06:08 psk001

I tried building Otel collector locally but was unable to reach the UI , any leads on how to create a collector or UI would be really helpful

psk001 avatar Aug 25 '23 06:08 psk001

I think there are two options for exporting spans from the UI

  1. sending them to a real collector that is different from query/api
  2. sending them to query/api where we can probably mount the standard OTLP receiver

yurishkuro avatar Aug 25 '23 06:08 yurishkuro

The first choice is an easy one, we can replace the url in collector options in tracing config by the collector url and it will be done.

The second one requires changes in query api as well involving the jaeger backend.

Should I go ahead and implement the first option?

psk001 avatar Aug 25 '23 07:08 psk001

Should I go ahead and implement the first option?

yes

yurishkuro avatar Aug 25 '23 15:08 yurishkuro

Using elastic APM for trace viewing

Use following configuration

docker compose configuration

version: "2"
services:
  collector:
    image: otel/opentelemetry-collector:latest
    command: ["--config=/otel-collector-config.yaml"]
    volumes:
      - './otel-collector-config.yaml:/otel-collector-config.yaml'
    ports:
      - "4318:4318"
    depends_on:
      - jaeger-all-in-one
   # Jaeger
  jaeger-all-in-one:
    hostname: jaeger-all-in-one
    image: jaegertracing/all-in-one:latest
    ports:
      - "16685"
      - "16686:16686"
      - "14268:14268"
      - "14250:14250"

openTelemetry collector configuration

receivers:
  otlp:
    protocols:
      http:
        cors:
          allowed_origins: ["*"]
          allowed_headers: ["*"]
exporters:
  logging:
    verbosity: Detailed
  otlp/elastic:
    endpoint: "<url>.apm.us-central1.gcp.cloud.es.io:443"
    compression: none
    headers:
      Authorization: "Bearer <token>"
  jaeger:
    endpoint: jaeger-all-in-one:14250
    tls:
      insecure: true
processors:
  batch:
service:
  telemetry:
    logs:
      level: "debug"
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [logging, jaeger, otlp/elastic]
      processors: [batch]

run docker-compose up and then start the Jaeger-UI . Perform actions like button click, search etc,

As viewed in elastic APM image

psk001 avatar Aug 26 '23 01:08 psk001

Using elastic APM for trace viewing

why, instead of Jaeger?

yurishkuro avatar Aug 26 '23 04:08 yurishkuro

It shows in jaeger as well as

image

with general otel collector config

receivers:
  otlp:
    protocols:
      http:
        cors:
          allowed_origins: ["*"]
          allowed_headers: ["*"]
exporters:
  logging:
    verbosity: Detailed
  jaeger:
    endpoint: jaeger-all-in-one:14250
    tls:
      insecure: true
processors:
  batch:
service:
  telemetry:
    logs:
      level: "debug"
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [logging, jaeger]
      processors: [batch]

psk001 avatar Aug 26 '23 05:08 psk001

no follow-up, closing

yurishkuro avatar Aug 16 '24 05:08 yurishkuro