### Install Clue Packages Source: https://github.com/goadesign/clue/blob/main/README.md Install the required Clue packages for your Go application using 'go get'. Ensure you are using Go 1.24 or later. ```bash go get goa.design/clue/clue go get goa.design/clue/log go get goa.design/clue/health go get goa.design/clue/mock go get goa.design/clue/debug ``` -------------------------------- ### Install Clue Mock Generator Source: https://github.com/goadesign/clue/blob/main/mock/README.md Command to install the Clue Mock Generator tool using Go's package management. ```bash go install goa.design/clue/mock/cmd/cmg ``` -------------------------------- ### Migrate Initialization from Clue v0.x to v1.x Source: https://github.com/goadesign/clue/blob/main/README.md Shows the transition from v0.x context-based telemetry setup to v1.x using clue.NewConfig and clue.ConfigureOpenTelemetry. ```go v0.x: ctx := log.Context(context.Background()) traceExporter := tracestdout.New() metricsExporter := metricstdout.New() cxt = trace.Context(ctx, "service", traceExporter) cxt = metrics.Context(ctx, "service", metricsExporter) v1.x: ctx := log.Context(context.Background()) traceExporter := tracestdout.New() metricsExporter := metricstdout.New() cfg := clue.NewConfig(ctx, "service", "1.0.0", metricsExporter, traceExporter) clue.ConfigureOpenTelemetry(ctx, cfg) ``` -------------------------------- ### Setup and Run Weather Services Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Execute these commands to set up dependencies, compile services, and run them with overmind and SigNoz for instrumentation. ```bash scripts/setup scripts/server ``` -------------------------------- ### Test Setup with Mock Clients Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Demonstrates how to initialize mock clients for different services (locator and forecaster) and configure their behavior using AddGetForecast and AddGetLocation before creating the main service instance for testing. ```go lmock := mocklocator.NewClient(t) lmock.AddGetLocation(c.locationFunc) // Mock the locator service. fmock := mockforecaster.NewClient(t) fmock.AddGetForecast(c.forecastFunc) // Mock the forecast service. s := New(fmock, lmock) // Create front service instance for testing ``` -------------------------------- ### Implementing Pinger Interface for SQL Databases Source: https://github.com/goadesign/clue/blob/main/health/README.md Provides an example of implementing the `health.Pinger` interface for SQL database clients. ```go // SQL database client used by service. type client struct { db *sql.DB } // Ping implements the `health.Pinger` interface. func (c *client) Ping(ctx context.Context) error { return c.db.PingContext(ctx) } // Name implements the `health.Pinger` interface. func (c *client) Name() string { return "PostgreSQL" // ClickHouse, MySQL, etc. } ``` -------------------------------- ### Goa OpenTelemetry Plugin Context Setup (v0.x) Source: https://github.com/goadesign/clue/blob/main/README.md Set up the OpenTelemetry context with a route resolver for Goa v0.x. ```go mux := goahttp.NewMuxer() ctx = metrics.Context(ctx, genfront.ServiceName, metrics.WithRouteResolver(func(r *http.Request) string { return mux.ResolvePattern(r) }), ) ``` -------------------------------- ### Configure OTLP Metric Exporter Source: https://github.com/goadesign/clue/blob/main/README.md Example of configuring an OpenTelemetry OTLP compliant metric exporter using gRPC transport. ```go import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" // ... metricExporter, err := otlpmetricgrpc.New( context.Background(), otlpmetricgrpc.WithEndpoint("localhost:4317"), otlpmetricgrpc.WithTLSCredentials(insecure.NewCredentials())) ``` -------------------------------- ### Using a Custom Log Format Function Source: https://github.com/goadesign/clue/blob/main/log/README.md Demonstrates creating and using a custom log format function that accepts a log.Entry and returns formatted bytes. This example formats logs as 'Severity: FirstKeyValue'. ```go func formatFunc(entry *log.Entry) []byte { return []byte(fmt.Sprintf("%s: %s", entry.Severity, entry.KeyVals[0].V)) } ctx := log.Context(context.Background(), log.WithFormat(formatFunc)) log.Printf(ctx, "hello world") ``` -------------------------------- ### Generate Mocks with Clue Mock Generator Source: https://github.com/goadesign/clue/blob/main/mock/README.md Example command to invoke the Clue Mock Generator for specified Go packages. ```bash cmg gen ./example/weather/services/... ``` -------------------------------- ### Wrapping Stream for Automatic Trace Context Handling Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Shows how to use a wrapper interface to automatically handle trace context setup and retrieval during stream receive operations. This simplifies the integration of tracing into stream handling logic. ```go ws := interceptors.WrapTraceBidirectionalStreamClientStream(stream) err := ws.Send(ctx, &genmyservice.MyBidirectionalStreamPayload{ ... }) ... ctx, result, err := ws.RecvAndReturnContext(ctx) ... ``` -------------------------------- ### Goa OpenTelemetry Plugin Design (v1.x) Source: https://github.com/goadesign/clue/blob/main/README.md Example import statement for the OpenTelemetry plugin in Goa v1.x design. ```go package design import ( . "goa.design/goa/v3/dsl" _ "goa.design/plugins/v3/clue" ) ``` -------------------------------- ### Healthy Service Example Source: https://github.com/goadesign/clue/blob/main/health/README.md Demonstrates a successful health check response from a service. ```bash http http://localhost:8083/livez HTTP/1.1 200 OK Content-Length: 109 Content-Type: application/json Date: Mon, 17 Jan 2022 23:23:12 GMT { "status": { "ClickHouse": "OK", "poller": "OK" }, "uptime": 20, "version": "91bb64a8103b494d0eac680f8e929e74882eea5f" } ``` -------------------------------- ### Generate Load for Weather System Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Start a script to generate load on the weather system after a successful request has been made. ```bash scripts/load ``` -------------------------------- ### Server Stream Interceptor Initialization Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Example of initializing various trace interceptors for a generated Goa server service. This includes bidirectional, server-to-client, and client-to-server stream interceptors. ```go type MyServerServiceInterceptors struct { interceptors.TraceBidirectionalStreamServerInterceptor[*genmyservice.TraceBidirectionalStreamInfo, genmyservice.MyBidirectionalStreamPayload, genmyservice.MyBidirectionalStreamResult] interceptors.TraceServerToClientStreamServerInterceptor[*genmyservice.TraceServerToClientStreamInfo, genmyservice.MyServerToClientStreamResult] interceptors.TraceClientToServerStreamServerInterceptor[*genmyservice.TraceClientToServerStreamInfo, genmyservice.MyClientToServerStreamPayload] } ``` -------------------------------- ### Configure OTLP Span Exporter Source: https://github.com/goadesign/clue/blob/main/README.md Example of configuring an OpenTelemetry OTLP compliant span exporter using gRPC transport. ```go import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" // ... spanExporter, err := otlptracegrpc.New( context.Background(), otlptracegrpc.WithEndpoint("localhost:4317"), otlptracegrpc.WithTLSCredentials(insecure.NewCredentials())) ``` -------------------------------- ### Alternative Content-Type Example Source: https://github.com/goadesign/clue/blob/main/health/README.md Shows a health check response with an XML content type. ```bash http http://localhost:8083/livez Accept:application/xml HTTP/1.1 200 OK Content-Length: 158 Content-Type: application/xml Date: Thu, 07 Sep 2023 13:28:29 GMT 20 91bb64a8103b494d0eac680f8e929e74882eea5f OK OK ``` -------------------------------- ### Unhealthy Service Example Source: https://github.com/goadesign/clue/blob/main/health/README.md Illustrates a health check response indicating a service is unavailable. ```bash http http://localhost:8083/livez HTTP/1.1 503 Service Unavailable Content-Length: 113 Content-Type: application/json Date: Mon, 17 Jan 2022 23:23:20 GMT { "status": { "ClickHouse": "OK", "poller": "NOT OK" }, "uptime": 20, "version": "91bb64a8103b494d0eac680f8e929e74882eea5f" } ``` -------------------------------- ### Client-to-Server Stream Interceptor Initialization Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Example of initializing a TraceClientToServerStreamClientInterceptor for a generated Goa service. This is used on the client side to trace data flowing from the client to the server in a stream. ```go interceptors.TraceClientToServerStreamClientInterceptor[*genmyservice.TraceClientToServerStreamInfo, genmyservice.MyClientToServerStreamPayload] ``` -------------------------------- ### Make a Request to the Front Service Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Use curl to send a request to the front service's public HTTP API to get weather forecast information for a given IP. ```bash curl http://localhost:8084/forecast/8.8.8.8 ``` -------------------------------- ### Basic Logging with Context Source: https://github.com/goadesign/clue/blob/main/log/README.md Demonstrates basic logging using context, including string formatting, key-value pairs, and structured fields. ```go package main import ( "context" "goa.design/clue/log" ) func main() { ctx := log.Context(context.Background()) log.Printf(ctx, "hello %s", "world") log.Print(ctx, log.KV{"hello", "world"}) log.Print(ctx, log.KV{"example", "log.KV"}, log.KV{"order", "deterministic"}, log.KV{"backed_by", "slice"}, ) log.Print(ctx, log.Fields{ "example": "log.Fields", "order": "random", "backed_by": "map", }) } ``` -------------------------------- ### Instrument HTTP Server with Clue Source: https://github.com/goadesign/clue/blob/main/README.md Illustrates setting up and instrumenting an HTTP server using Goadesign Clue. Includes middleware for logging, debugging, and OpenTelemetry tracing. ```go ctx := log.Context(context.Background(), // Create a clue logger context. log.WithFunc(log.Span)) // Log trace and span IDs. metricExporter := stdoutmetric.New() // Create metric and span exporters. spanExporter := stdouttrace.New() cfg := clue.NewConfig(ctx, "service", "1.0.0", metricExporter, spanExporter) clue.ConfigureOpenTelemetry(ctx, cfg) // Configure OpenTelemetry. handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, World!")) }) // Create HTTP handler. handler = otelhttp.NewHandler(handler, "service" ) // Instrument handler. handler = debug.HTTP()(handler) // Setup debug log level control. handler = log.HTTP(ctx)(handler) // Add logger to request context and log requests. mux := http.NewServeMux() // Create HTTP mux. mux.HandleFunc("/", handler) // Mount handler. debug.MountDebugLogEnabler(mux) // Mount debug log level control handler. debug.MountDebugPprof(mux) // Mount pprof handlers. mux.HandleFunc("/health", health.NewHandler(health.NewChecker())) // Mount health check handler. http.ListenAndServe(":8080", mux) // Start HTTP server. ``` -------------------------------- ### Structured Logging with Key/Value Pairs Source: https://github.com/goadesign/clue/blob/main/log/README.md Demonstrates building log context with key/value pairs using log.With and logging messages with log.Print. Values can be strings, numbers, booleans, nil, or slices of these types. ```go ctx := log.Context(context.Background()) ctx := log.With(ctx, log.KV{"key2", "val2"}) log.Print(ctx, log.KV{"hello", "world 1"}) ctx = log.With(ctx, log.KV{"key3", "val3"}) log.Print(ctx, log.KV{"hello", "world 2"}, log.KV{"key4", "val4"}) ``` -------------------------------- ### Use a Mock in a Test Source: https://github.com/goadesign/clue/blob/main/mock/README.md Demonstrates how to use the mock client in a test. It shows adding a mock call, executing it, and verifying that the sequence was consumed. ```go // Create a new mock client (defined above). mock := newMock(t) // Add a mock call for the GetPrices method. mock.Add("GetPrices", getPricesFunc) // Call the mock. prices, err := mock.GetPrices(ctx, firstHour, lastHour, nodeID) // Validate prices and err if err != nil { t.Errorf("GetPrices returned %v", err) } // Make sure entire sequence has been consumed (in this example there is only // one call). if mock.HasMore() { t.Error("GetPrices was not called") } ``` -------------------------------- ### Setting Up Trace Context for Stream Receive Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Demonstrates how to manually set up the trace context after receiving data from a stream on the server side. This is necessary because Goa's generated receive methods do not return a context. ```go ctx = interceptors.SetupTraceStreamRecvContext(ctx, stream) result, err := stream.RecvWithContext(ctx) ctx = interceptors.GetTraceStreamRecvContext(ctx) ``` -------------------------------- ### Initialize Log Context with Outputs and Span Function Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Initialize the log context in the main function, setting the output format and adding trace and span IDs to log entries. ```go ctx := log.Context(context.Background(), log.WithOutputs(log.Output{Writer: os.Stdout, Format: format}), log.WithFunc(log.Span), ) ``` -------------------------------- ### Logger Instantiation with Service Name Source: https://github.com/goadesign/clue/blob/main/log/README.md Shows how to initialize a logger context with a service name for consistent logging across a Goa service. ```go ctx := log.With(log.Context(context.Background()), log.KV{"svc", svcgen.ServiceName}) ``` -------------------------------- ### Instrument gRPC Server with Clue Source: https://github.com/goadesign/clue/blob/main/README.md Demonstrates how to instrument a gRPC server using Goadesign Clue, including unary interceptors for logging and debugging, and OpenTelemetry server handler. ```go ctx := log.Context(context.Background(), // Create a clue logger context. log.WithFunc(log.Span)) // Log trace and span IDs. metricExporter := stdoutmetric.New() spanExporter := stdouttrace.New() cfg := clue.NewConfig(ctx, "service", "1.0.0", metricExporter, spanExporter) clue.ConfigureOpenTelemetry(ctx, cfg) // Configure OpenTelemetry. svr := grpc.NewServer( grpc.ChainUnaryInterceptor( log.UnaryServerInterceptor(ctx), // Add logger to request context and log requests. debug.UnaryServerInterceptor()), // Enable debug log level control grpc.StatsHandler(otelgrpc.NewServerHandler()), // Instrument server. ) ``` -------------------------------- ### Configure Clue with OpenTelemetry Exporters Source: https://github.com/goadesign/clue/blob/main/README.md Shows how to use configured OpenTelemetry span and metric exporters to initialize Goadesign Clue. ```go // Configure OpenTelemetry. cfg := clue.NewConfig(ctx, "service", "1.0.0", metricExporter, spanExporter) clue.ConfigureOpenTelemetry(ctx, cfg) ``` -------------------------------- ### Mounting Health Check Handler in Go Source: https://github.com/goadesign/clue/blob/main/health/README.md Demonstrates how to integrate the health check handler into a Go HTTP server using the clue/health package. ```go package main import ( "context" "database/sql" "goa.design/clue/health" "goa.design/clue/log" goahttp "goa.design/goa/v3/http" "github.com/repo/services/svc/clients/storage" httpsvrgen "github.com/repo/services/svc/gen/http/svc/server" svcgen "github.com/repo/services/svc/gen/svc" ) func main() { // Initialize the log context ctx := log.With(log.Context(context.Background()), "svc", svcgen.ServiceName) // Create service clients used by this service // The client object must implement the `health.Pinger` interface // dsn := ... con, err := sql.Open("clickhouse", dsn) if err != nil { log.Error(ctx, "could not connect to clickhouse", "err", err.Error()) } stc := storage.New(con) // Create the service (user code) svc := svc.New(ctx, stc) // Wrap the service with Goa endpoints endpoints := svcgen.NewEndpoints(svc) // Create HTTP server mux := goahttp.NewMuxer() httpsvr := httpsvrgen.New(endpoints, mux, goahttp.RequestDecoder, goahttp.ResponseEncoder, nil, nil) httpsvrgen.Mount(mux, httpsvr) // ** Mount health check handler ** check := health.Handler(health.NewChecker(stc)) mux.Handle("GET", "/healthz", check) mux.Handle("GET", "/livez", check) // ... start HTTP server } ``` -------------------------------- ### Create a Mock Implementation Source: https://github.com/goadesign/clue/blob/main/mock/README.md Defines a mock struct that embeds the `mock.Mock` and includes a testing.T pointer. This is used to create mock clients for services. ```go // mock implementation of the `prices` service type mock struct { *mock.Mock // Embed the mock package Mock struct which provides the mock API t *testing.T } func newMock(t *testing.T) *mock { return &mock{mock.New(), t} } // mock implementation of the GetPrices method. The implementation leverages // the mock package to replay a sequence of calls. func (m *mock) GetPrices(ctx context.Context, first, last time.Time, nodeID string) ([]*Price, error) { if f := m.Next("GetPrices"); f != nil { // Get the next mock in the sequence (or the permanent mock) return f.(func(ctx, time.Time, time.Time, string) ([]*Price, error))(ctx, first, last, nodeID) } m.t.Error("unexpected GetPrices call") } ``` -------------------------------- ### Instrument HTTP Client with Clue and OpenTelemetry Source: https://github.com/goadesign/clue/blob/main/README.md Wraps an HTTP transport to log requests/responses and add OpenTelemetry tracing. Requires importing 'go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp' and 'goa.design/clue/log'. ```go import ( "context" "net/http" "net/http/httptrace" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttptrace" "goa.design/clue/log" ) // ... httpc := &http.Client{ Transport: log.Client( otelhttp.NewTransport( http.DefaultTransport, otelhttp.WithClientTrace(func(ctx context.Context) *httptrace.ClientTrace { return otelhttptrace.NewClientTrace(ctx) }), ), ), } ``` -------------------------------- ### Multiple Log Outputs with Independent Formats Source: https://github.com/goadesign/clue/blob/main/log/README.md Illustrates configuring multiple log outputs with different writers and formats using log.WithOutputs(). ```go ctx := log.Context(context.Background(), log.WithOutputs( log.Output{Writer: os.Stdout, Format: log.FormatTerminal}, log.Output{Writer: logfile, Format: log.FormatJSON}, )) ``` -------------------------------- ### HTTP Middleware for Request Context Source: https://github.com/goadesign/clue/blob/main/log/README.md Initializes the HTTP request context with the logger configured in the given context using log.HTTP. ```go check := log.HTTP(ctx)(health.Handler(health.NewChecker(dep1, dep2, ...))) ``` -------------------------------- ### Enabling Debug Logging Source: https://github.com/goadesign/clue/blob/main/log/README.md Shows how to enable debug logging using log.WithDebug(). By default, debug logs are not written to the output. ```go ctx := log.Context(context.Background()) log.Debugf(ctx, "debug message 1") ctx := log.Context(ctx, log.WithDebug()) log.Debugf(ctx, "debug message 2") log.Infof(ctx, "info message") ``` -------------------------------- ### Instrument gRPC Client with Clue and OpenTelemetry Source: https://github.com/goadesign/clue/blob/main/README.md Adds Clue logging and OpenTelemetry tracing to a gRPC client connection. Requires importing 'go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc' and 'goa.design/clue/log'. ```go import ( "context" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "goa.design/clue/log" ) // ... grpcconn, err := grpc.DialContext(ctx, "localhost:8080", grpc.WithUnaryInterceptor(log.UnaryClientInterceptor()), grpc.WithStatsHandler(otelgrpc.NewClientHandler())) ) ``` -------------------------------- ### Real Forecast Service Client Instantiation Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Instantiates a new real client for the forecast service using a gRPC client connection. ```go // New instantiates a new forecast service client. func New(cc *grpc.ClientConn) Client { c := genclient.NewClient(cc, grpc.WaitForReady(true)) return &client{c.Forecast()} } ``` -------------------------------- ### Configure OpenTelemetry Collector Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Initializes gRPC exporters for traces and metrics and configures the OpenTelemetry collector. Ensure SigNoz or a compatible backend is running. ```go spanExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithEndpoint(*oteladdr), otlptracegrpc.WithTLSCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf(ctx, err, "failed to initialize tracing") } deffer func() { if err := spanExporter.Shutdown(ctx); err != nil { log.Errorf(ctx, err, "failed to shutdown tracing") } }() metricExporter, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithEndpoint(*oteladdr), otlpmetricgrpc.WithTLSCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf(ctx, err, "failed to initialize metrics") } deffer func() { if err := metricExporter.Shutdown(ctx); err != nil { log.Errorf(ctx, err, "failed to shutdown metrics") } }() cfg, err := clue.NewConfig(ctx, genforecaster.ServiceName, genforecaster.APIVersion, metricExporter, spanExporter, ) if err != nil { log.Fatalf(ctx, err, "failed to initialize instrumentation") } clue.ConfigureOpenTelemetry(ctx, cfg) ``` -------------------------------- ### Instrument HTTP Service (v1.x) Source: https://github.com/goadesign/clue/blob/main/README.md Instrument an HTTP service using otelhttp for v1.x. ```go http.ListenAndServe(":8080", otelhttp.NewHandler("service", handler)) ``` -------------------------------- ### Apply HTTP Middleware for Log Context in Front Service Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Use the log HTTP middleware to initialize the log context for every incoming request to the front service's HTTP handler. ```go handler = log.HTTP(ctx)(handler) ``` -------------------------------- ### Instrument HTTP Service (v0.x) Source: https://github.com/goadesign/clue/blob/main/README.md Instrument an HTTP service using the trace and metrics packages for v0.x. ```go handler = trace.HTTP(ctx)(handler) handler = metrics.HTTP(ctx)(handler) http.ListenAndServe(":8080", handler) ``` -------------------------------- ### Implement Server Interceptor Functions Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Implement server interceptor functions for your service. These functions call the provided interceptor functions from the 'goa.design/clue/interceptors' package to handle tracing logic. ```go func (i *MyServerServiceInterceptors) TraceBidirectionalStream(ctx context.Context, info *genmyservice.TraceBidirectionalStreamInfo, next goa.InterceptorEndpoint) (any, context.Context, error) { return interceptors.TraceBidirectionalStreamServer(ctx, info, next) } func (i *MyServerServiceInterceptors) TraceServerToClientStream(ctx context.Context, info *genmyservice.TraceServerToClientStreamInfo, next goa.InterceptorEndpoint) (any, context.Context, error) { return interceptors.TraceServerToClientStreamServer(ctx, info, next) } func (i *MyServerServiceInterceptors) TraceClientToServerStream(ctx context.Context, info *genmyservice.TraceClientToServerStreamInfo, next goa.InterceptorEndpoint) (any, context.Context, error) { return interceptors.TraceClientToServerStreamServer(ctx, info, next) } ``` -------------------------------- ### Instrument gRPC Client Connection Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Creates an instrumented gRPC client connection to a downstream service, enabling logging, metrics, and tracing. Requires the 'otelgrpc' and 'log' packages. ```go lcc, err := grpc.DialContext(ctx, *locatorAddr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithUnaryInterceptor(log.UnaryClientInterceptor()), // Log requests grpc.WithStatsHandler(otelgrpc.NewClientHandler())) // Collect metrics and traces if err != nil { log.Fatalf(ctx, err, "failed to connect to locator") } lc := locator.New(lcc) // Create client using instrumented connection ``` -------------------------------- ### Mock Forecast Service Client Instantiation Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Instantiates a new mock client for the forecast service using the cmg tool. This mock client is intended for testing. ```go // NewMock returns a new mock client. func NewClient(t *testing.T) *Client { var ( m = &Client{mock.New(), t} _ = forecaster.Client = m ) return m } ``` -------------------------------- ### Mock Client Structure and Method Signature Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Defines the structure of the mock client, including a reference to the mock object and testing object, and the function signature for mocked methods like GetForecast. ```go type ( // Mock implementation of the forecast client. Client struct { m *mock.Mock t *testing.T } ClientGetForecastFunc func(ctx context.Context, lat, long float64) (*forecaster.Forecast, error) ) ``` -------------------------------- ### Configuring Mocked Method Calls Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Provides methods to add or set specific function implementations for mocked methods, enabling control over mock behavior during tests. ```go // AddGetForecastFunc adds f to the mocked call sequence. func (m *Client) AddGetForecast(f ClientGetForecastFunc) { m.m.Add("GetForecast", f) } // SetGetForecastFunc sets f for all calls to the mocked method. func (m *Client) SetGetForecast(f ClientGetForecastFunc) { m.m.Set("GetForecast", f) } ``` -------------------------------- ### Implement Client Interceptor Functions Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Implement client interceptor functions for your service. These functions call the provided interceptor functions from the 'goa.design/clue/interceptors' package to handle tracing logic. ```go import ( ... "goa.design/clue/interceptors) ... func (i *MyServiceClientInterceptors) TraceBidirectionalStream(ctx context.Context, info *genmyservice.TraceBidirectionalStream, next goa.InterceptorEndpoint) (any, context.Context, error) { return interceptors.TraceBidirectionalStreamClient(ctx, info, next) } func (i *MyServiceClientInterceptors) TraceServerToClientStream(ctx context.Context, info *genmyservice.TraceServerToClientStream, next goa.InterceptorEndpoint) (any, context.Context, error) { return interceptors.TraceServerToClientStreamClient(ctx, info, next) } func (i *MyServiceClientInterceptors) TraceClientToServerStream(ctx context.Context, info *genmyservice.TraceClientToServerStream, next goa.InterceptorEndpoint) (any, context.Context, error) { return interceptors.TraceClientToServerStreamClient(ctx, info, next) } ``` -------------------------------- ### Conditional Buffering with Tracing Source: https://github.com/goadesign/clue/blob/main/log/README.md Demonstrates how to conditionally disable log buffering based on a context-aware function, such as checking if tracing is enabled. ```go ctx := log.Context(req.Context(), log.WithDisableBuffering(log.IsTracing)) log.Infof(ctx, "request started") // buffering disabled if tracing is enabled ``` -------------------------------- ### Apply Goa Endpoint Middleware with Clue and Debug Source: https://github.com/goadesign/clue/blob/main/README.md Applies Clue's log.Endpoint middleware for service/method context and debug.LogPayloads for request/response logging in Goa services. ```go svc := forecaster.New(wc) endpoints := genforecaster.NewEndpoints(svc) endpoints.Use(debug.LogPayloads()) endpoints.Use(log.Endpoint) ``` -------------------------------- ### Mount pprof Handlers Source: https://github.com/goadesign/clue/blob/main/debug/README.md Configures an HTTP mux to serve pprof profiling handlers under the /debug/pprof/ path. This allows for runtime profiling of the microservice. ```go mux := http.NewServeMux() debug.MountPprofHandlers(mux) // ... configure mux with other handlers ``` -------------------------------- ### Expose Debug Endpoints via HTTP for gRPC Source: https://github.com/goadesign/clue/blob/main/README.md Shows how to set up a separate HTTP server to expose debug log level control, pprof, and health check endpoints for a gRPC application. ```go mux := http.NewServeMux() // Create HTTP mux. debug.MountDebugLogEnabler(mux) // Mount debug log level control handler. debug.MountDebugPprof(mux) // Mount pprof handlers. mux.HandleFunc("/health", health.NewHandler(health.NewChecker())) // Mount health check handler. go http.ListenAndServe(":8081", mux) // Start HTTP server. ``` -------------------------------- ### Create Custom Counter and Span with Clue Source: https://github.com/goadesign/clue/blob/main/README.md Illustrates creating a custom counter and span using OpenTelemetry APIs within Clue. Ensure OpenTelemetry is configured first using clue.ConfigureOpenTelemetry. ```go // ... configure OpenTelemetry like in example above clue.ConfigureOpenTelemetry(ctx, cfg) // Create a meter and tracer meter := otel.Meter("mymeter") tracer := otel.Tracer("mytracer") // Create a counter counter, err := meter.Int64Counter("my.counter", metric.WithDescription("The number of times the service has been called"), metric.WithUnit("{call}")) if err != nil { log.Fatalf("failed to create counter: %s", err) } handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Create a span ctx, span := tracer.Start(r.Context(), "myhandler") defer span.End() // ... do something // Add custom attributes to span and counter attr := attribute.Int("myattr", 42) span.SetAttributes(attr) counter.Add(ctx, 1, metric.WithAttributes(attr)) // ... do something else if _, err := w.Write([]byte("Hello, World!")); err != nil { log.Errorf(ctx, err, "failed to write response") } }) ``` -------------------------------- ### Implement Health Check Handler Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Creates a health check handler using the 'health' package. This is typically used for liveness and readiness probes. ```go check := health.Handler(health.NewChecker(wc)) ``` -------------------------------- ### Use Standard Go Logger with Goa Context Source: https://github.com/goadesign/clue/blob/main/log/README.md Adapts a Goa logger context to the standard Go log.Logger interface. Useful for integrating existing standard logging code with Goa's context-aware logging. ```go ctx := log.Context(context.Background()) logger := log.AsStdLogger(ctx) logger.Print("hello world") ``` -------------------------------- ### Instrument gRPC Service (v1.x) Source: https://github.com/goadesign/clue/blob/main/README.md Instrument a gRPC service using otelgrpc stats handler for v1.x. ```go grpcsvr := grpc.NewServer(grpc.StatsHandler(otelgrpc.NewServerHandler())) ``` -------------------------------- ### Instrument gRPC Service (v0.x) Source: https://github.com/goadesign/clue/blob/main/README.md Instrument a gRPC service using trace and metrics interceptors for v0.x. ```go grpcsvr := grpc.NewServer( grpcmiddleware.WithUnaryServerChain( trace.UnaryServerInterceptor(ctx), metrics.UnaryServerInterceptor(ctx), ), grpcmiddleware.WithStreamServerChain( trace.StreamServerInterceptor(ctx), metrics.StreamServerInterceptor(ctx), ), ) ``` -------------------------------- ### Mocked Method Implementation with Call Validation Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Implements the GetForecast method for the mock client, utilizing the mock package to retrieve and execute predefined functions or report unexpected calls. ```go // GetForecast implements the Client interface. func (m *Client) GetForecast(ctx context.Context, lat, long float64) (*forecaster.Forecast, error) { if f := m.m.Next("GetForecast"); f != nil { return f.(ClientGetForecastFunc)(ctx, lat, long) } m.t.Helper() m.t.Error("unexpected GetForecast call") return nil, nil } ``` -------------------------------- ### Setting Log Format to Terminal Source: https://github.com/goadesign/clue/blob/main/log/README.md Sets the log format to Terminal, suitable for colored terminal output and the default for terminal applications. ```go ctx := log.Context(context.Background(), log.WithFormat(log.FormatTerminal)) log.Printf(ctx, "hello world") ``` -------------------------------- ### Setting Log Format to Text Source: https://github.com/goadesign/clue/blob/main/log/README.md Configures the log format to plain text using log.FormatText, which is the default for non-terminal applications. ```go ctx := log.Context(context.Background(), log.WithFormat(log.FormatText)) log.Printf(ctx, "hello world") ``` -------------------------------- ### Buffering Log Messages Source: https://github.com/goadesign/clue/blob/main/log/README.md Illustrates how log messages are buffered until an error occurs or the buffer is explicitly flushed, useful for request handling. ```go log.Infof(ctx, "request started") // ... no log written so far log.Errorf(ctx, err, "request failed") // flushes all previous log entries ``` -------------------------------- ### TestLocator Source: https://github.com/goadesign/clue/blob/main/example/weather/services/tester/README.md Runs all tests specifically defined for the Locator service as found in `services/tester/func_map.go`. ```APIDOC ## TestLocator ### Description Runs all tests defined for the Locator service in `services/tester/func_map.go`. ### Method GRPC ### Endpoint `/tester.Tester/TestLocator` ### Parameters None ### Response #### Success Response - **TestResults** (object) - Encapsulates the system integration test outcomes. - **Collections** (array) - Array of `TestCollection` instances. - **Duration** (integer) - Total test time in milliseconds. - **PassCount** (integer) - Number of tests that passed. - **FailCount** (integer) - Number of tests that failed. #### Response Example { "Collections": [ { "Name": "string", "Tests": [ { "Name": "string", "Passed": true, "Error": "string", "Duration": 0 } ], "Duration": 0, "PassCount": 0, "FailCount": 0 } ], "Duration": 0, "PassCount": 0, "FailCount": 0 } ``` -------------------------------- ### Setting Log Format to JSON Source: https://github.com/goadesign/clue/blob/main/log/README.md Configures the log format to JSON, printing log entries in a structured JSON format. ```go ctx := log.Context(context.Background(), log.WithFormat(log.FormatJSON)) log.Printf(ctx, "hello world") ``` -------------------------------- ### Instrument HTTP Client Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Configures an HTTP client with OpenTelemetry tracing and logging interceptors. This ensures that outgoing HTTP requests are traced and logged. ```go httpc := &http.Client{ Transport: log.Client( // Log requests otelhttp.NewTransport( http.DefaultTransport, otelhttp.WithClientTrace(func(ctx context.Context) *httptrace.ClientTrace { return otelhttptrace.NewClientTrace(ctx) }), // Propagate traces ))} ipc := ipapi.New(httpc) ``` -------------------------------- ### Forecast Service Client Interface Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Defines the interface for the forecast service client, specifying the GetForecast method signature. ```go Client interface { // GetForecast gets the forecast for the given location. GetForecast(ctx context.Context, lat, long float64) (*Forecast, error) } ``` -------------------------------- ### Implement Pinger Health Check Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Sets up health checks for downstream services using 'health.NewPinger'. It specifies the service name, protocol, and address for each service to ping. ```go check := health.Handler(health.NewChecker( health.NewPinger("locator", "http", *locatorHealthAddr), health.NewPinger("forecaster", "http", *forecasterHealthAddr))) ``` -------------------------------- ### TestAll Source: https://github.com/goadesign/clue/blob/main/example/weather/services/tester/README.md Runs all tests defined in the tester service, with optional filtering capabilities via a TesterPayload. The payload can include or exclude tests based on their names, supporting wildcards. ```APIDOC ## TestAll ### Description Runs all tests defined in `services/tester/func_map.go`. Optionally filters tests using `TesterPayload`. `Include` and `Exclude` fields are mutually exclusive and support `*` wildcards. ### Method GRPC ### Endpoint `/tester.Tester/TestAll` ### Parameters #### Request Body - **TesterPayload** (object) - Optional payload for filtering tests. - **Include** (array of strings) - Names of tests to include. Supports `*` wildcards. - **Exclude** (array of strings) - Names of tests to exclude. Supports `*` wildcards. ### Request Example ```json { "Include": ["TestForecaster*"], "Exclude": [] } ``` ### Response #### Success Response - **TestResults** (object) - Encapsulates the system integration test outcomes. - **Collections** (array) - Array of `TestCollection` instances. - **Duration** (integer) - Total test time in milliseconds. - **PassCount** (integer) - Number of tests that passed. - **FailCount** (integer) - Number of tests that failed. #### Response Example { "Collections": [ { "Name": "string", "Tests": [ { "Name": "string", "Passed": true, "Error": "string", "Duration": 0 } ], "Duration": 0, "PassCount": 0, "FailCount": 0 } ], "Duration": 0, "PassCount": 0, "FailCount": 0 } #### Error Response (400 Bad Request) - Returned if `Include` and `Exclude` fields are used together in `TesterPayload`. ``` -------------------------------- ### Mount Health and Metrics Handlers Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Registers the health check and metrics handlers on the global HTTP server. This allows external systems to query the service's health and metrics. ```go http.Handle("/livez", check) http.Handle("/metrics", instrument.Handler(ctx)) ``` -------------------------------- ### Mount Service HTTP Handler Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md Mounts the main service HTTP handler onto the root path of the global HTTP server. This ensures all requests not handled by health or metrics are routed to the service. ```go http.Handle("/", handler) ``` -------------------------------- ### TestForecaster Source: https://github.com/goadesign/clue/blob/main/example/weather/services/tester/README.md Runs all tests specifically defined for the Forecaster service as found in `services/tester/func_map.go`. ```APIDOC ## TestForecaster ### Description Runs all tests defined for the Forecaster service in `services/tester/func_map.go`. ### Method GRPC ### Endpoint `/tester.Tester/TestForecaster` ### Parameters None ### Response #### Success Response - **TestResults** (object) - Encapsulates the system integration test outcomes. - **Collections** (array) - Array of `TestCollection` instances. - **Duration** (integer) - Total test time in milliseconds. - **PassCount** (integer) - Number of tests that passed. - **FailCount** (integer) - Number of tests that failed. #### Response Example { "Collections": [ { "Name": "string", "Tests": [ { "Name": "string", "Passed": true, "Error": "string", "Duration": 0 } ], "Duration": 0, "PassCount": 0, "FailCount": 0 } ], "Duration": 0, "PassCount": 0, "FailCount": 0 } ``` -------------------------------- ### Mount Debug Log Enabler for gRPC Source: https://github.com/goadesign/clue/blob/main/debug/README.md Mounts a debug log enabler handler on an HTTP mux and configures gRPC servers with a UnaryInterceptor to manage debug log state. Requires an exposed HTTP endpoint for control. ```go mux := http.NewServeMux() debug.MountDebugLogEnabler(mux) srv := &http.Server{Handler: mux} go srv.ListenAndServe() gsrv := grpc.NewServer(grpc.UnaryInterceptor(debug.UnaryInterceptor)) lis, _ := net.Listen("tcp", ":8080") gsrv.Serve(lis) ``` -------------------------------- ### Changing Log Output to Stderr Source: https://github.com/goadesign/clue/blob/main/log/README.md Demonstrates redirecting log output to os.Stderr using log.WithOutput(). The function accepts any type implementing the io.Writer interface. ```go ctx := log.Context(context.Background(), log.WithOutput(os.Stderr)) log.Printf(ctx, "hello world") ``` -------------------------------- ### Adapt Goa Logger for Goa Middleware Source: https://github.com/goadesign/clue/blob/main/log/README.md Adapts a Goa logger context to the goa.design/goa/v3/middleware.Logger interface. This allows configuring the logger used by Goa's built-in middlewares. ```go ctx := log.Context(context.Background()) logger := log.AsGoaMiddlewareLogger(ctx) // logger implements middleware.Logger ``` -------------------------------- ### gRPC Unary Server Interceptor Source: https://github.com/goadesign/clue/blob/main/log/README.md Includes a unary gRPC interceptor that initializes the request context with the logger configured in the given context. ```go grpcsvr := grpc.NewServer( grpcmiddleware.WithUnaryServerChain( goagrpcmiddleware.UnaryRequestID(), log.UnaryServerInterceptor(ctx), )) ``` -------------------------------- ### Apply Unary Server Interceptor for Log Context in gRPC Services Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md gRPC services use the UnaryServerInterceptor from the log package to initialize the log context for each request. ```go grpcsvr := grpc.NewServer( grpc.ChainUnaryInterceptor( log.UnaryServerInterceptor(ctx), // <- debug.UnaryServerInterceptor()), grpc.StatsHandler(otelgrpc.NewServerHandler())) ``` -------------------------------- ### Mount Debug Log Enabler for Goa Muxer Source: https://github.com/goadesign/clue/blob/main/debug/README.md Adapts a Goa muxer to mount the debug log enabler handler, allowing runtime control of debug logs within a Goa application. ```go mux := goa.NewMuxer() debug.MountDebugLogEnabler(debug.Adapt(mux)) ``` -------------------------------- ### Mount Debug Log Enabler for HTTP Source: https://github.com/goadesign/clue/blob/main/debug/README.md Mounts a handler to an HTTP mux to control debug log state via a /debug endpoint. Ensure HTTP servers use handlers returned by debug.HTTP. ```go mux := http.NewServeMux() debug.MountDebugLogEnabler(mux) // ... configure mux with other handlers srv := &http.Server{Handler: debug.HTTP(mux)} srv.ListenAndServe() ``` -------------------------------- ### Embed Interceptor Structs in Implementations Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Alternatively, embed the interceptor structs directly into your interceptor implementations. This approach leverages Go generics for seamless integration with generated service types. ```go import ( ... "goa.design/clue/interceptors) ... type MyServiceClientInterceptors struct { interceptors.TraceBidirectionalStreamClientInterceptor[*genmyservice.TraceBidirectionalStreamInfo, genmyservice.MyBidirectionalStreamPayload, genmyservice.MyBidirectionalStreamResult] interceptors.TraceServerToClientStreamClientInterceptor[*genmyservice.TraceServerToClientStreamInfo, genmyservice.MyServerToClientStreamResult] ``` -------------------------------- ### TestSmoke Source: https://github.com/goadesign/clue/blob/main/example/weather/services/tester/README.md Runs all smoke tests defined in the tester service. Smoke tests are a subset of all tests designed to provide basic confidence in application functionality. ```APIDOC ## TestSmoke ### Description Runs all smoke tests defined in `services/tester/func_map.go`. These tests provide a basic level of confidence that the application is functioning properly. ### Method GRPC ### Endpoint `/tester.Tester/TestSmoke` ### Parameters None ### Response #### Success Response - **TestResults** (object) - Encapsulates the system integration test outcomes. - **Collections** (array) - Array of `TestCollection` instances. - **Duration** (integer) - Total test time in milliseconds. - **PassCount** (integer) - Number of tests that passed. - **FailCount** (integer) - Number of tests that failed. #### Response Example { "Collections": [ { "Name": "string", "Tests": [ { "Name": "string", "Passed": true, "Error": "string", "Duration": 0 } ], "Duration": 0, "PassCount": 0, "FailCount": 0 } ], "Duration": 0, "PassCount": 0, "FailCount": 0 } ``` -------------------------------- ### Define Trace Metadata Attribute Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Define the `TraceMetadata` attribute or field within your streaming payload and/or result definitions. This attribute is used to carry tracing information over HTTP or gRPC. ```go Attribute("TraceMetadata", MapOf(String, String)) // for HTTP Field(101, "TraceMetadata", MapOf(String, String)) // for gRPC ``` -------------------------------- ### Apply HTTP Middleware for Log Context in Health Check Source: https://github.com/goadesign/clue/blob/main/example/weather/README.md The health check HTTP endpoints also utilize the log HTTP middleware to log any errors that occur. ```go check = log.HTTP(ctx)(check).(http.HandlerFunc) ``` -------------------------------- ### Apply Interceptors to Service Methods Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Specify the defined trace stream interceptors as both client and server interceptors for your Goa service methods. This ensures that tracing is applied to both directions of communication. ```go Method("MyBidirectionalStreamMethod", func() { ClientInterceptor(TraceBidirectionalStream) ServerInterceptor(TraceBidirectionalStream) ... }) Method("MyServerToClientStreamMethod", func() { ClientInterceptor(TraceServerToClientStream) ServerInterceptor(TraceServerToClientStream) ... }) Method("MyClientToServerStreamMethod", func() { ClientInterceptor(TraceClientToServerStream) ServerInterceptor(TraceClientToServerStream) ... }) ``` -------------------------------- ### Log Request and Result Payloads with Goa Middleware Source: https://github.com/goadesign/clue/blob/main/debug/README.md Applies the LogPayloads middleware to Goa endpoints to log request and result payloads when debug logs are enabled. This is a no-op if debug logs are disabled. ```go endpoints := genforecaster.NewEndpoints(svc) endpoints.Use(debug.LogPayloads()) endpoints.Use(log.Endpoint) ``` -------------------------------- ### Define Trace Stream Interceptors Source: https://github.com/goadesign/clue/blob/main/interceptors/README.md Define the different types of trace stream interceptors (bidirectional, server-to-client, client-to-server) in your Goa design. These interceptors are used to capture metadata for tracing. ```go var TraceBidirectionalStream = Interceptor("TraceBidirectionalStream", func() { WriteStreamingPayload(func() { Attribute("TraceMetadata", MapOf(String, String)) }) ReadStreamingPayload(func() { Attribute("TraceMetadata", MapOf(String, String)) }) WriteStreamingResult(func() { Attribute("TraceMetadata", MapOf(String, String)) }) ReadStreamingResult(func() { Attribute("TraceMetadata", MapOf(String, String)) }) }) var TraceServerToClientStream = Interceptor("TraceServerToClientStream", func() { WriteStreamingResult(func() { Attribute("TraceMetadata", MapOf(String, String)) }) ReadStreamingResult(func() { Attribute("TraceMetadata", MapOf(String, String)) }) }) var TraceClientToServerStream = Interceptor("TraceClientToServerStream", func() { WriteStreamingPayload(func() { Attribute("TraceMetadata", MapOf(String, String)) }) ReadStreamingPayload(func() { Attribute("TraceMetadata", MapOf(String, String)) }) }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.