Skip to content

Instantly share code, notes, and snippets.

@chanwit
Created January 24, 2026 15:01
Show Gist options
  • Select an option

  • Save chanwit/6671694140acfd34194a0a83be923d71 to your computer and use it in GitHub Desktop.

Select an option

Save chanwit/6671694140acfd34194a0a83be923d71 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
"time"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)
type SearchResponse struct {
Token string `json:"token"`
Timestamp time.Time `json:"timestamp"`
}
type ResultResponse struct {
Data string `json:"data"`
Token string `json:"token"`
Timestamp time.Time `json:"timestamp"`
}
func initTracer() (*sdktrace.TracerProvider, error) {
file, err := os.Create("client_traces.json")
if err != nil {
return nil, err
}
exporter, err := stdouttrace.New(
stdouttrace.WithWriter(file),
)
if err != nil {
return nil, err
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("client"),
)),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
return tp, nil
}
func parseSpansFromFile(filename string) ([]map[string]interface{}, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
var spans []map[string]interface{}
// stdouttrace outputs JSON Lines format (one span per line)
lines := strings.Split(string(data), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
var span map[string]interface{}
if err := json.Unmarshal([]byte(line), &span); err != nil {
// Skip invalid lines
continue
}
spans = append(spans, span)
}
return spans, nil
}
func mergeTraces() error {
// Read and parse client traces
clientSpans, err := parseSpansFromFile("client_traces.json")
if err != nil {
return fmt.Errorf("failed to read client traces: %w", err)
}
// Read and parse server traces
serverSpans, err := parseSpansFromFile("server_traces.json")
if err != nil {
return fmt.Errorf("failed to read server traces: %w", err)
}
// Merge all spans into a single array
allSpans := append(clientSpans, serverSpans...)
// Write merged traces as JSON array
outputFile, err := os.Create("traces.json")
if err != nil {
return fmt.Errorf("failed to create output file: %w", err)
}
defer outputFile.Close()
encoder := json.NewEncoder(outputFile)
encoder.SetIndent("", " ")
if err := encoder.Encode(allSpans); err != nil {
return fmt.Errorf("failed to write merged traces: %w", err)
}
return nil
}
func main() {
tp, err := initTracer()
if err != nil {
log.Fatal("Failed to initialize tracer:", err)
}
// Create instrumented HTTP client
client := &http.Client{
Transport: otelhttp.NewTransport(http.DefaultTransport),
}
tracer := otel.Tracer("client")
// Wait for server to start
time.Sleep(2 * time.Second)
// Create root span for client workflow
ctx, rootSpan := tracer.Start(context.Background(), "client-workflow")
// Make search request
log.Println("Making search request...")
searchReq, err := http.NewRequestWithContext(ctx, "GET", "http://localhost:8080/search?q=opentelemetry", nil)
if err != nil {
log.Fatal("Failed to create search request:", err)
}
searchResp, err := client.Do(searchReq)
if err != nil {
log.Fatal("Search request failed:", err)
}
defer searchResp.Body.Close()
body, err := io.ReadAll(searchResp.Body)
if err != nil {
log.Fatal("Failed to read search response:", err)
}
var searchResult SearchResponse
if err := json.Unmarshal(body, &searchResult); err != nil {
log.Fatal("Failed to parse search response:", err)
}
log.Printf("Received token: %s", searchResult.Token)
// Make result request with token
log.Println("Making result request...")
resultReq, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:8080/result?token=%s", searchResult.Token), nil)
if err != nil {
log.Fatal("Failed to create result request:", err)
}
resultResp, err := client.Do(resultReq)
if err != nil {
log.Fatal("Result request failed:", err)
}
defer resultResp.Body.Close()
body, err = io.ReadAll(resultResp.Body)
if err != nil {
log.Fatal("Failed to read result response:", err)
}
var resultData ResultResponse
if err := json.Unmarshal(body, &resultData); err != nil {
log.Fatal("Failed to parse result response:", err)
}
log.Printf("Received data: %s", resultData.Data)
fmt.Println("Client completed successfully")
// End root span
rootSpan.End()
// Flush client traces
if err := tp.Shutdown(context.Background()); err != nil {
log.Printf("Error shutting down tracer: %v", err)
}
// Use raw HTTP client (not instrumented) to call shutdown endpoint
rawClient := &http.Client{Timeout: 5 * time.Second}
shutdownResp, err := rawClient.Get("http://localhost:8080/shutdown")
if err != nil {
log.Printf("Warning: Failed to call shutdown endpoint: %v", err)
} else {
shutdownResp.Body.Close()
}
// Wait for server to flush traces
time.Sleep(1 * time.Second)
// Merge traces
if err := mergeTraces(); err != nil {
log.Printf("Warning: Failed to merge traces: %v", err)
}
}
2026/01/24 21:56:29 Making search request...
2026/01/24 21:56:29 Received token: 7822179bacedbe74
2026/01/24 21:56:29 Making result request...
2026/01/24 21:56:29 Received data: Results for query: opentelemetry
Client completed successfully
{"Name":"HTTP GET","SpanContext":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"32296cf8372a12a6","TraceFlags":"01","TraceState":"","Remote":false},"Parent":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"f8c2f05b612e6178","TraceFlags":"01","TraceState":"","Remote":false},"SpanKind":3,"StartTime":"2026-01-24T21:56:29.485408053+07:00","EndTime":"2026-01-24T21:56:29.537426752+07:00","Attributes":[{"Key":"http.method","Value":{"Type":"STRING","Value":"GET"}},{"Key":"http.url","Value":{"Type":"STRING","Value":"http://localhost:8080/search?q=opentelemetry"}},{"Key":"net.peer.name","Value":{"Type":"STRING","Value":"localhost"}},{"Key":"net.peer.port","Value":{"Type":"INT64","Value":8080}},{"Key":"http.status_code","Value":{"Type":"INT64","Value":200}},{"Key":"http.response_content_length","Value":{"Type":"INT64","Value":79}}],"Events":null,"Links":null,"Status":{"Code":"Unset","Description":""},"DroppedAttributes":0,"DroppedEvents":0,"DroppedLinks":0,"ChildSpanCount":0,"Resource":[{"Key":"service.name","Value":{"Type":"STRING","Value":"client"}}],"InstrumentationLibrary":{"Name":"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp","Version":"0.49.0","SchemaURL":""}}
{"Name":"HTTP GET","SpanContext":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"4986658f466edfdd","TraceFlags":"01","TraceState":"","Remote":false},"Parent":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"f8c2f05b612e6178","TraceFlags":"01","TraceState":"","Remote":false},"SpanKind":3,"StartTime":"2026-01-24T21:56:29.537644311+07:00","EndTime":"2026-01-24T21:56:29.568934293+07:00","Attributes":[{"Key":"http.method","Value":{"Type":"STRING","Value":"GET"}},{"Key":"http.url","Value":{"Type":"STRING","Value":"http://localhost:8080/result?token=7822179bacedbe74"}},{"Key":"net.peer.name","Value":{"Type":"STRING","Value":"localhost"}},{"Key":"net.peer.port","Value":{"Type":"INT64","Value":8080}},{"Key":"http.status_code","Value":{"Type":"INT64","Value":200}},{"Key":"http.response_content_length","Value":{"Type":"INT64","Value":121}}],"Events":null,"Links":null,"Status":{"Code":"Unset","Description":""},"DroppedAttributes":0,"DroppedEvents":0,"DroppedLinks":0,"ChildSpanCount":0,"Resource":[{"Key":"service.name","Value":{"Type":"STRING","Value":"client"}}],"InstrumentationLibrary":{"Name":"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp","Version":"0.49.0","SchemaURL":""}}
{"Name":"client-workflow","SpanContext":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"f8c2f05b612e6178","TraceFlags":"01","TraceState":"","Remote":false},"Parent":{"TraceID":"00000000000000000000000000000000","SpanID":"0000000000000000","TraceFlags":"00","TraceState":"","Remote":false},"SpanKind":1,"StartTime":"2026-01-24T21:56:29.485208033+07:00","EndTime":"2026-01-24T21:56:29.569047247+07:00","Attributes":null,"Events":null,"Links":null,"Status":{"Code":"Unset","Description":""},"DroppedAttributes":0,"DroppedEvents":0,"DroppedLinks":0,"ChildSpanCount":2,"Resource":[{"Key":"service.name","Value":{"Type":"STRING","Value":"client"}}],"InstrumentationLibrary":{"Name":"client","Version":"","SchemaURL":""}}
package main
import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"sync"
"syscall"
"time"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)
type SearchResponse struct {
Token string `json:"token"`
Timestamp time.Time `json:"timestamp"`
}
type ResultResponse struct {
Data string `json:"data"`
Token string `json:"token"`
Timestamp time.Time `json:"timestamp"`
}
var (
tokenStore = make(map[string]string)
mu sync.RWMutex
)
func initTracer() (*sdktrace.TracerProvider, error) {
file, err := os.Create("server_traces.json")
if err != nil {
return nil, err
}
exporter, err := stdouttrace.New(
stdouttrace.WithWriter(file),
)
if err != nil {
return nil, err
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("server"),
)),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
return tp, nil
}
func searchHandler(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("q")
if query == "" {
query = "default"
}
log.Printf("Search request received for query: %s", query)
// Simulate processing
time.Sleep(50 * time.Millisecond)
// Generate token
hash := sha256.Sum256([]byte(query + time.Now().String()))
token := hex.EncodeToString(hash[:])[:16]
// Store result
mu.Lock()
tokenStore[token] = fmt.Sprintf("Results for query: %s", query)
mu.Unlock()
response := SearchResponse{
Token: token,
Timestamp: time.Now(),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
func resultHandler(w http.ResponseWriter, r *http.Request) {
token := r.URL.Query().Get("token")
if token == "" {
http.Error(w, "Token required", http.StatusBadRequest)
return
}
log.Printf("Result request received for token: %s", token)
// Simulate processing
time.Sleep(30 * time.Millisecond)
mu.RLock()
data, exists := tokenStore[token]
mu.RUnlock()
if !exists {
http.Error(w, "Token not found", http.StatusNotFound)
return
}
response := ResultResponse{
Data: data,
Token: token,
Timestamp: time.Now(),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
var (
shutdownChan = make(chan struct{})
tracerProvider *sdktrace.TracerProvider
)
func shutdownHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Shutdown request received")
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
// Signal shutdown after response is sent
go func() {
time.Sleep(100 * time.Millisecond)
close(shutdownChan)
}()
}
func main() {
tp, err := initTracer()
if err != nil {
log.Fatal("Failed to initialize tracer:", err)
}
tracerProvider = tp
// Set up signal handling for graceful shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
// Wrap handlers with otelhttp to extract trace context and create server spans
searchOtelHandler := otelhttp.NewHandler(http.HandlerFunc(searchHandler), "/search")
resultOtelHandler := otelhttp.NewHandler(http.HandlerFunc(resultHandler), "/result")
http.Handle("/search", searchOtelHandler)
http.Handle("/result", resultOtelHandler)
// Shutdown endpoint - not instrumented to avoid extra spans
http.HandleFunc("/shutdown", shutdownHandler)
server := &http.Server{Addr: ":8080"}
go func() {
select {
case <-sigChan:
log.Println("Received signal, shutting down...")
case <-shutdownChan:
log.Println("Shutdown requested via API...")
}
// Flush traces first
if err := tp.Shutdown(context.Background()); err != nil {
log.Printf("Error shutting down tracer: %v", err)
}
// Shutdown the HTTP server
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
server.Shutdown(ctx)
}()
log.Println("Server starting on :8080")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal(err)
}
}
2026/01/24 21:56:25 Server starting on :8080
2026/01/24 21:56:29 Search request received for query: opentelemetry
2026/01/24 21:56:29 Result request received for token: 7822179bacedbe74
2026/01/24 21:56:29 Shutdown request received
2026/01/24 21:56:29 Shutdown requested via API...
{"Name":"/search","SpanContext":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"ce52397dc050e001","TraceFlags":"01","TraceState":"","Remote":false},"Parent":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"32296cf8372a12a6","TraceFlags":"01","TraceState":"","Remote":true},"SpanKind":2,"StartTime":"2026-01-24T21:56:29.486199862+07:00","EndTime":"2026-01-24T21:56:29.536882424+07:00","Attributes":[{"Key":"http.method","Value":{"Type":"STRING","Value":"GET"}},{"Key":"http.scheme","Value":{"Type":"STRING","Value":"http"}},{"Key":"net.host.name","Value":{"Type":"STRING","Value":"localhost"}},{"Key":"net.host.port","Value":{"Type":"INT64","Value":8080}},{"Key":"net.sock.peer.addr","Value":{"Type":"STRING","Value":"127.0.0.1"}},{"Key":"net.sock.peer.port","Value":{"Type":"INT64","Value":56696}},{"Key":"user_agent.original","Value":{"Type":"STRING","Value":"Go-http-client/1.1"}},{"Key":"http.target","Value":{"Type":"STRING","Value":"/search"}},{"Key":"net.protocol.version","Value":{"Type":"STRING","Value":"1.1"}},{"Key":"http.wrote_bytes","Value":{"Type":"INT64","Value":79}},{"Key":"http.status_code","Value":{"Type":"INT64","Value":200}}],"Events":null,"Links":null,"Status":{"Code":"Unset","Description":""},"DroppedAttributes":0,"DroppedEvents":0,"DroppedLinks":0,"ChildSpanCount":0,"Resource":[{"Key":"service.name","Value":{"Type":"STRING","Value":"server"}}],"InstrumentationLibrary":{"Name":"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp","Version":"0.49.0","SchemaURL":""}}
{"Name":"/result","SpanContext":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"abb4289b11b6d83a","TraceFlags":"01","TraceState":"","Remote":false},"Parent":{"TraceID":"adcf39e2704f6657367473d1477ca759","SpanID":"4986658f466edfdd","TraceFlags":"01","TraceState":"","Remote":true},"SpanKind":2,"StartTime":"2026-01-24T21:56:29.538010494+07:00","EndTime":"2026-01-24T21:56:29.568429147+07:00","Attributes":[{"Key":"http.method","Value":{"Type":"STRING","Value":"GET"}},{"Key":"http.scheme","Value":{"Type":"STRING","Value":"http"}},{"Key":"net.host.name","Value":{"Type":"STRING","Value":"localhost"}},{"Key":"net.host.port","Value":{"Type":"INT64","Value":8080}},{"Key":"net.sock.peer.addr","Value":{"Type":"STRING","Value":"127.0.0.1"}},{"Key":"net.sock.peer.port","Value":{"Type":"INT64","Value":56696}},{"Key":"user_agent.original","Value":{"Type":"STRING","Value":"Go-http-client/1.1"}},{"Key":"http.target","Value":{"Type":"STRING","Value":"/result"}},{"Key":"net.protocol.version","Value":{"Type":"STRING","Value":"1.1"}},{"Key":"http.wrote_bytes","Value":{"Type":"INT64","Value":121}},{"Key":"http.status_code","Value":{"Type":"INT64","Value":200}}],"Events":null,"Links":null,"Status":{"Code":"Unset","Description":""},"DroppedAttributes":0,"DroppedEvents":0,"DroppedLinks":0,"ChildSpanCount":0,"Resource":[{"Key":"service.name","Value":{"Type":"STRING","Value":"server"}}],"InstrumentationLibrary":{"Name":"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp","Version":"0.49.0","SchemaURL":""}}
[
{
"Attributes": [
{
"Key": "http.method",
"Value": {
"Type": "STRING",
"Value": "GET"
}
},
{
"Key": "http.url",
"Value": {
"Type": "STRING",
"Value": "http://localhost:8080/search?q=opentelemetry"
}
},
{
"Key": "net.peer.name",
"Value": {
"Type": "STRING",
"Value": "localhost"
}
},
{
"Key": "net.peer.port",
"Value": {
"Type": "INT64",
"Value": 8080
}
},
{
"Key": "http.status_code",
"Value": {
"Type": "INT64",
"Value": 200
}
},
{
"Key": "http.response_content_length",
"Value": {
"Type": "INT64",
"Value": 79
}
}
],
"ChildSpanCount": 0,
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"EndTime": "2026-01-24T21:56:29.537426752+07:00",
"Events": null,
"InstrumentationLibrary": {
"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"SchemaURL": "",
"Version": "0.49.0"
},
"Links": null,
"Name": "HTTP GET",
"Parent": {
"Remote": false,
"SpanID": "f8c2f05b612e6178",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"Resource": [
{
"Key": "service.name",
"Value": {
"Type": "STRING",
"Value": "client"
}
}
],
"SpanContext": {
"Remote": false,
"SpanID": "32296cf8372a12a6",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"SpanKind": 3,
"StartTime": "2026-01-24T21:56:29.485408053+07:00",
"Status": {
"Code": "Unset",
"Description": ""
}
},
{
"Attributes": [
{
"Key": "http.method",
"Value": {
"Type": "STRING",
"Value": "GET"
}
},
{
"Key": "http.url",
"Value": {
"Type": "STRING",
"Value": "http://localhost:8080/result?token=7822179bacedbe74"
}
},
{
"Key": "net.peer.name",
"Value": {
"Type": "STRING",
"Value": "localhost"
}
},
{
"Key": "net.peer.port",
"Value": {
"Type": "INT64",
"Value": 8080
}
},
{
"Key": "http.status_code",
"Value": {
"Type": "INT64",
"Value": 200
}
},
{
"Key": "http.response_content_length",
"Value": {
"Type": "INT64",
"Value": 121
}
}
],
"ChildSpanCount": 0,
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"EndTime": "2026-01-24T21:56:29.568934293+07:00",
"Events": null,
"InstrumentationLibrary": {
"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"SchemaURL": "",
"Version": "0.49.0"
},
"Links": null,
"Name": "HTTP GET",
"Parent": {
"Remote": false,
"SpanID": "f8c2f05b612e6178",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"Resource": [
{
"Key": "service.name",
"Value": {
"Type": "STRING",
"Value": "client"
}
}
],
"SpanContext": {
"Remote": false,
"SpanID": "4986658f466edfdd",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"SpanKind": 3,
"StartTime": "2026-01-24T21:56:29.537644311+07:00",
"Status": {
"Code": "Unset",
"Description": ""
}
},
{
"Attributes": null,
"ChildSpanCount": 2,
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"EndTime": "2026-01-24T21:56:29.569047247+07:00",
"Events": null,
"InstrumentationLibrary": {
"Name": "client",
"SchemaURL": "",
"Version": ""
},
"Links": null,
"Name": "client-workflow",
"Parent": {
"Remote": false,
"SpanID": "0000000000000000",
"TraceFlags": "00",
"TraceID": "00000000000000000000000000000000",
"TraceState": ""
},
"Resource": [
{
"Key": "service.name",
"Value": {
"Type": "STRING",
"Value": "client"
}
}
],
"SpanContext": {
"Remote": false,
"SpanID": "f8c2f05b612e6178",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"SpanKind": 1,
"StartTime": "2026-01-24T21:56:29.485208033+07:00",
"Status": {
"Code": "Unset",
"Description": ""
}
},
{
"Attributes": [
{
"Key": "http.method",
"Value": {
"Type": "STRING",
"Value": "GET"
}
},
{
"Key": "http.scheme",
"Value": {
"Type": "STRING",
"Value": "http"
}
},
{
"Key": "net.host.name",
"Value": {
"Type": "STRING",
"Value": "localhost"
}
},
{
"Key": "net.host.port",
"Value": {
"Type": "INT64",
"Value": 8080
}
},
{
"Key": "net.sock.peer.addr",
"Value": {
"Type": "STRING",
"Value": "127.0.0.1"
}
},
{
"Key": "net.sock.peer.port",
"Value": {
"Type": "INT64",
"Value": 56696
}
},
{
"Key": "user_agent.original",
"Value": {
"Type": "STRING",
"Value": "Go-http-client/1.1"
}
},
{
"Key": "http.target",
"Value": {
"Type": "STRING",
"Value": "/search"
}
},
{
"Key": "net.protocol.version",
"Value": {
"Type": "STRING",
"Value": "1.1"
}
},
{
"Key": "http.wrote_bytes",
"Value": {
"Type": "INT64",
"Value": 79
}
},
{
"Key": "http.status_code",
"Value": {
"Type": "INT64",
"Value": 200
}
}
],
"ChildSpanCount": 0,
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"EndTime": "2026-01-24T21:56:29.536882424+07:00",
"Events": null,
"InstrumentationLibrary": {
"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"SchemaURL": "",
"Version": "0.49.0"
},
"Links": null,
"Name": "/search",
"Parent": {
"Remote": true,
"SpanID": "32296cf8372a12a6",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"Resource": [
{
"Key": "service.name",
"Value": {
"Type": "STRING",
"Value": "server"
}
}
],
"SpanContext": {
"Remote": false,
"SpanID": "ce52397dc050e001",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"SpanKind": 2,
"StartTime": "2026-01-24T21:56:29.486199862+07:00",
"Status": {
"Code": "Unset",
"Description": ""
}
},
{
"Attributes": [
{
"Key": "http.method",
"Value": {
"Type": "STRING",
"Value": "GET"
}
},
{
"Key": "http.scheme",
"Value": {
"Type": "STRING",
"Value": "http"
}
},
{
"Key": "net.host.name",
"Value": {
"Type": "STRING",
"Value": "localhost"
}
},
{
"Key": "net.host.port",
"Value": {
"Type": "INT64",
"Value": 8080
}
},
{
"Key": "net.sock.peer.addr",
"Value": {
"Type": "STRING",
"Value": "127.0.0.1"
}
},
{
"Key": "net.sock.peer.port",
"Value": {
"Type": "INT64",
"Value": 56696
}
},
{
"Key": "user_agent.original",
"Value": {
"Type": "STRING",
"Value": "Go-http-client/1.1"
}
},
{
"Key": "http.target",
"Value": {
"Type": "STRING",
"Value": "/result"
}
},
{
"Key": "net.protocol.version",
"Value": {
"Type": "STRING",
"Value": "1.1"
}
},
{
"Key": "http.wrote_bytes",
"Value": {
"Type": "INT64",
"Value": 121
}
},
{
"Key": "http.status_code",
"Value": {
"Type": "INT64",
"Value": 200
}
}
],
"ChildSpanCount": 0,
"DroppedAttributes": 0,
"DroppedEvents": 0,
"DroppedLinks": 0,
"EndTime": "2026-01-24T21:56:29.568429147+07:00",
"Events": null,
"InstrumentationLibrary": {
"Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"SchemaURL": "",
"Version": "0.49.0"
},
"Links": null,
"Name": "/result",
"Parent": {
"Remote": true,
"SpanID": "4986658f466edfdd",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"Resource": [
{
"Key": "service.name",
"Value": {
"Type": "STRING",
"Value": "server"
}
}
],
"SpanContext": {
"Remote": false,
"SpanID": "abb4289b11b6d83a",
"TraceFlags": "01",
"TraceID": "adcf39e2704f6657367473d1477ca759",
"TraceState": ""
},
"SpanKind": 2,
"StartTime": "2026-01-24T21:56:29.538010494+07:00",
"Status": {
"Code": "Unset",
"Description": ""
}
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment