Skip to content

Instantly share code, notes, and snippets.

@mtfelian
Last active June 25, 2022 09:33
Show Gist options
  • Save mtfelian/a360b2c07eee51ebd7f6ed9e9f987ade to your computer and use it in GitHub Desktop.
Save mtfelian/a360b2c07eee51ebd7f6ed9e9f987ade to your computer and use it in GitHub Desktop.
Jaeger 1.6 Golang distributed tracing example (minimalistic)
package main
import (
"context"
"fmt"
"io"
"net/http"
"os"
"time"
"github.com/sirupsen/logrus"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
"go.opentelemetry.io/otel/trace"
)
const jaegerAddr = "http://localhost:14268/api/traces"
const port = "3333"
func initTracing(url string) (trace.Tracer, error) {
const serviceName = "service 2 (client)"
hostName, err := os.Hostname()
if err != nil {
return nil, err
}
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
jExporter, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return nil, err
}
traceProvider := tracesdk.NewTracerProvider(
tracesdk.WithSampler(tracesdk.AlwaysSample()),
tracesdk.WithBatcher(jExporter),
tracesdk.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String(serviceName),
semconv.DeploymentEnvironmentKey.String("dev"),
semconv.HostNameKey.String(hostName),
)),
)
otel.SetTracerProvider(traceProvider)
return traceProvider.Tracer("component-main"), nil
}
var Tracer trace.Tracer
var httpClient = &http.Client{}
func sendRequest(ctx context.Context) error {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://localhost:%s/", port), nil)
if err != nil {
return nil
}
var span trace.Span
if ctx, span = Tracer.Start(ctx, "Client: Sending '/' request"); span != nil {
defer span.End()
otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
spanContext := span.SpanContext()
logrus.Infof("TraceID=%s", spanContext.TraceID())
}
resp, err := httpClient.Do(req)
if err != nil {
return err
}
logrus.Infof("resp.StatusCode = %d", resp.StatusCode)
if resp.Body != nil {
defer resp.Body.Close()
var body []byte
if body, err = io.ReadAll(resp.Body); err != nil {
return err
}
logrus.Infof("body = %s", string(body))
}
return nil
}
func main() {
var err error
if Tracer, err = initTracing(jaegerAddr); err != nil {
logrus.Fatal(err)
}
ctx := context.Background()
var span trace.Span
if ctx, span = Tracer.Start(ctx, "main client span"); span != nil {
//defer span.End()
}
if err = sendRequest(ctx); err != nil {
logrus.Fatal(err)
}
span.End()
time.Sleep(20 * time.Second)
}
version: '3'
services:
jaeger:
image: jaegertracing/all-in-one:1.6
ports:
- "16686:16686"
- "14268:14268"
command:
- '--memory.max-traces=100000'
package main
import (
"fmt"
"net/http"
"os"
"github.com/sirupsen/logrus"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
"go.opentelemetry.io/otel/trace"
)
const jaegerAddr = "http://localhost:14268/api/traces"
const port = "3333"
func getRoot(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
w.WriteHeader(http.StatusNotFound)
return
}
ctx := r.Context()
var span trace.Span
spanName := fmt.Sprintf("%s %s", http.MethodGet, "/")
logrus.Infof("header: %s", r.Header)
if r.Header.Get("Traceparent") != "" {
ctx = otel.GetTextMapPropagator().Extract(ctx, propagation.HeaderCarrier(r.Header))
if ctx, span = Tracer.Start(ctx, "derived span "+spanName); span != nil {
defer span.End()
}
logrus.Infof("span TraceID=%s", span.SpanContext().TraceID())
} else {
if ctx, span = Tracer.Start(ctx, spanName); span != nil {
defer span.End()
}
}
if _, err := fmt.Fprintf(w, "OK %s\n", r.RequestURI); err != nil {
logrus.Fatal(err)
}
}
func initTracing(url string) (trace.Tracer, error) {
const serviceName = "service 1 (server)"
hostName, err := os.Hostname()
if err != nil {
return nil, err
}
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
jExporter, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return nil, err
}
traceProvider := tracesdk.NewTracerProvider(
tracesdk.WithSampler(tracesdk.AlwaysSample()),
tracesdk.WithBatcher(jExporter),
tracesdk.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String(serviceName),
semconv.DeploymentEnvironmentKey.String("dev"),
semconv.HostNameKey.String(hostName),
)),
)
otel.SetTracerProvider(traceProvider)
return traceProvider.Tracer("component-main"), nil
}
func registerHandlers() {
http.HandleFunc("/", getRoot)
}
var Tracer trace.Tracer
func main() {
var err error
if Tracer, err = initTracing(jaegerAddr); err != nil {
logrus.Fatal(err)
}
registerHandlers()
logrus.Infof("Server started on port %s", port)
fmt.Println(http.ListenAndServe(":"+port, nil).Error())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment