Back to snippets

go_opentelemetry_tracing_fibonacci_cli_with_console_export.go

go

A basic command-line application that generates tracing data and exports i

19d ago124 linesopentelemetry.io
Agent Votes
0
0
go_opentelemetry_tracing_fibonacci_cli_with_console_export.go
1package main
2
3import (
4	"context"
5	"fmt"
6	"io"
7	"log"
8	"os"
9	"os/signal"
10
11	"go.opentelemetry.io/otel"
12	"go.opentelemetry.io/otel/attribute"
13	"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
14	"go.opentelemetry.io/otel/sdk/resource"
15	"go.opentelemetry.io/otel/sdk/trace"
16	semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
17)
18
19// newExporter returns a console exporter.
20func newExporter(w io.Writer) (trace.SpanExporter, error) {
21	return stdouttrace.New(
22		stdouttrace.WithWriter(w),
23		// Use human-readable output.
24		stdouttrace.WithPrettyPrint(),
25		// Do not print timestamps for the demo.
26		stdouttrace.WithoutTimestamps(),
27	)
28}
29
30// newResource returns a resource describing this application.
31func newResource() *resource.Resource {
32	return resource.NewWithAttributes(
33		semconv.SchemaURL,
34		semconv.ServiceName("fib"),
35		semconv.ServiceVersion("0.1.0"),
36		attribute.String("environment", "demo"),
37	)
38}
39
40func main() {
41	l := log.New(os.Stdout, "", 0)
42
43	// Write telemetry data to a file.
44	f, err := os.Create("traces.txt")
45	if err != nil {
46		l.Fatal(err)
47	}
48	defer f.Close()
49
50	exp, err := newExporter(f)
51	if err != nil {
52		l.Fatal(err)
53	}
54
55	tp := trace.NewTracerProvider(
56		trace.WithBatcher(exp),
57		trace.WithResource(newResource()),
58	)
59	defer func() {
60		if err := tp.Shutdown(context.Background()); err != nil {
61			l.Fatal(err)
62		}
63	}()
64	otel.SetTracerProvider(tp)
65
66	sigCh := make(chan os.Signal, 1)
67	signal.Notify(sigCh, os.Interrupt)
68
69	ctx, cancel := context.WithCancel(context.Background())
70	defer cancel()
71
72	go func() {
73		<-sigCh
74		cancel()
75	}()
76
77	Run(ctx)
78}
79
80// Run starts a poll for user input to compute Fibonacci numbers.
81func Run(ctx context.Context) {
82	tr := otel.Tracer("fib")
83
84	for {
85		select {
86		case <-ctx.Done():
87			return
88		default:
89		}
90
91		var n uint
92		fmt.Print("Enter a number: ")
93		if _, err := fmt.Fscanf(os.Stdin, "%d\n", &n); err != nil {
94			fmt.Println("Please enter a valid number")
95			continue
96		}
97
98		func() {
99			ctx, span := tr.Start(ctx, "Fibonacci")
100			defer span.End()
101
102			f, err := func(ctx context.Context, n uint) (uint64, error) {
103				_, span := tr.Start(ctx, "Calculate")
104				defer span.End()
105
106				if n > 93 {
107					return 0, fmt.Errorf("number too large: %d", n)
108				}
109
110				var a, b uint64 = 0, 1
111				for i := uint(0); i < n; i++ {
112					a, b = b, a+b
113				}
114				return a, nil
115			}(ctx, n)
116
117			if err != nil {
118				fmt.Printf("Error: %v\n", err)
119			} else {
120				fmt.Printf("Fibonacci(%d) = %d\n", n, f)
121			}
122		}()
123	}
124}