-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
149 lines (122 loc) · 3.63 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"strings"
"time"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
var (
tracer = otel.Tracer("test-tracer")
)
func init() {
// Log as JSON instead of the default ASCII formatter.
log.SetFormatter(&log.JSONFormatter{
TimestampFormat: time.RFC3339Nano,
FieldMap: log.FieldMap{
log.FieldKeyTime: "timestamp",
log.FieldKeyLevel: "severity",
log.FieldKeyMsg: "msg",
},
})
// Output to stdout instead of the default stderr
// Can be any io.Writer, see below for File example
log.SetOutput(os.Stdout)
log.SetLevel(log.InfoLevel)
}
func setupRouter() *gin.Engine {
r := gin.New()
r.Use(gin.Recovery()) // panic時に500エラーを返却
r.Use(otelgin.Middleware("", otelgin.WithFilter(ignoreTracingRequest)))
r.Use(loggingHandler)
// Ping test
r.GET("/ping", gin.WrapF(pingHandler))
r.GET("/healthz", gin.WrapF(healthzHandler))
r.GET("/sendmail", gin.WrapF(sendmailHandler))
return r
}
// ロギング・トレース対象外
func ignoreTracingRequest(r *http.Request) bool {
return !(r.RequestURI == "/healthz" || strings.HasPrefix(r.RequestURI, "/static"))
}
func initProvider() (func(context.Context) error, error) {
ctx := context.Background()
resource, err := resource.New(ctx,
resource.WithAttributes(
// the service name used to display traces in backends
),
)
if err != nil {
return nil, fmt.Errorf("failed to create resource: %w", err)
}
client := otlptracehttp.NewClient()
exporter, err := otlptrace.New(ctx, client)
if err != nil {
return nil, fmt.Errorf("creating OTLP trace exporter: %w", err)
}
tracerProvider := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resource),
)
otel.SetTracerProvider(tracerProvider)
otel.SetTextMapPropagator(propagation.TraceContext{})
return tracerProvider.Shutdown, nil
}
func main() {
// init Otel
shutdown, err := initProvider()
if err != nil {
log.Fatal(err)
}
// Gin mode:
// - using env: export GIN_MODE=release
// - using code: gin.SetMode(gin.ReleaseMode)
gin.SetMode(gin.ReleaseMode)
router := setupRouter()
srv := &http.Server{
Handler: router,
Addr: "0.0.0.0:3000",
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
// Run our server in a goroutine so that it doesn't block.
go func() {
log.Info("Start Server")
if err := srv.ListenAndServe(); err != nil {
log.Error(err)
}
}()
c := make(chan os.Signal, 1)
// We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C)
// SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught.
signal.Notify(c, os.Interrupt)
// Block until we receive our signal.
<-c
// Create a deadline to wait for.
log.Info("start shutdown")
wait := time.Second * 15
ctx, cancel := context.WithTimeout(context.Background(), wait)
defer cancel()
// Doesn't block if no connections, but will otherwise wait
// until the timeout deadline.
srv.Shutdown(ctx)
if err := shutdown(ctx); err != nil { // Otel
log.Fatal("failed to shutdown TracerProvider: %w", err)
}
// Optionally, you could run srv.Shutdown in a goroutine and block on
// <-ctx.Done() if your application should wait for other services
// to finalize based on context cancellation.
log.Info("finish shutdown")
os.Exit(0)
}