// Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "context" "fmt" "io" "log" "strconv" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/trace" ) // name is the Tracer name used to identify this instrumentation library. const name = "fib" // App is an Fibonacci computation application. type App struct { r io.Reader l *log.Logger } // NewApp returns a new App. func NewApp(r io.Reader, l *log.Logger) *App { return &App{r: r, l: l} } // Run starts polling users for Fibonacci number requests and writes results. func (a *App) Run(ctx context.Context) error { for { // Each execution of the run loop, we should get a new "root" span and context. newCtx, span := otel.Tracer(name).Start(ctx, "Run") n, err := a.Poll(newCtx) if err != nil { span.End() return err } a.Write(newCtx, n) span.End() } } // Poll asks a user for input and returns the request. func (a *App) Poll(ctx context.Context) (uint, error) { _, span := otel.Tracer(name).Start(ctx, "Poll") defer span.End() a.l.Print("What Fibonacci number would you like to know: ") var n uint _, err := fmt.Fscanf(a.r, "%d\n", &n) if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) return 0, err } // Store n as a string to not overflow an int64. nStr := strconv.FormatUint(uint64(n), 10) span.SetAttributes(attribute.String("request.n", nStr)) return n, nil } // Write writes the n-th Fibonacci number back to the user. func (a *App) Write(ctx context.Context, n uint) { var span trace.Span ctx, span = otel.Tracer(name).Start(ctx, "Write") defer span.End() f, err := func(ctx context.Context) (uint64, error) { _, span := otel.Tracer(name).Start(ctx, "Fibonacci") defer span.End() f, err := Fibonacci(n) if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) } return f, err }(ctx) if err != nil { a.l.Printf("Fibonacci(%d): %v\n", n, err) } else { a.l.Printf("Fibonacci(%d) = %d\n", n, f) } }