- Add bootstrap package to initialize application components including logger, tracer, and HTTP server. - Create config package to load runtime settings from environment variables. - Implement observability features including logging, metrics, and tracing. - Add health check and hello use cases with corresponding HTTP handlers. - Introduce middleware for request ID, access logging, metrics, and recovery. - Set up HTTP router with defined routes for health and hello endpoints. - Include tests for health and hello endpoints to ensure proper functionality. - Add OpenTelemetry collector configuration for trace exporting.
45 lines
1.1 KiB
Go
45 lines
1.1 KiB
Go
package middleware
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"runtime/debug"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.opentelemetry.io/otel/codes"
|
|
"go.opentelemetry.io/otel/trace"
|
|
|
|
"switchbot-api/internal/transport/http/contextkeys"
|
|
"switchbot-api/internal/transport/http/response"
|
|
)
|
|
|
|
func Recovery(logger *slog.Logger) gin.HandlerFunc {
|
|
return gin.CustomRecoveryWithWriter(io.Discard, func(c *gin.Context, recovered any) {
|
|
ctx := c.Request.Context()
|
|
span := trace.SpanFromContext(ctx)
|
|
span.RecordError(fmt.Errorf("panic: %v", recovered))
|
|
span.SetStatus(codes.Error, "panic recovered")
|
|
|
|
spanCtx := trace.SpanContextFromContext(ctx)
|
|
traceID := ""
|
|
spanID := ""
|
|
if spanCtx.IsValid() {
|
|
traceID = spanCtx.TraceID().String()
|
|
spanID = spanCtx.SpanID().String()
|
|
}
|
|
|
|
logger.Error(
|
|
"panic recovered",
|
|
slog.Any("panic", recovered),
|
|
slog.String("request_id", contextkeys.RequestIDFromContext(ctx)),
|
|
slog.String("trace_id", traceID),
|
|
slog.String("span_id", spanID),
|
|
slog.String("stack", string(debug.Stack())),
|
|
)
|
|
|
|
response.WriteInternalError(c)
|
|
c.Abort()
|
|
})
|
|
}
|