-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmain.go
133 lines (110 loc) · 3.36 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
package main
import (
"flag"
"sync"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/bnelz/gokit-base/config"
"github.com/bnelz/gokit-base/health"
"github.com/bnelz/gokit-base/inmemory"
hb "github.com/bnelz/gokit-base/logger"
"github.com/bnelz/gokit-base/users"
"github.com/go-kit/kit/log"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// serializedLogger is our "global" application logger
type serializedLogger struct {
mtx sync.Mutex
log.Logger
}
// aConfig is the application configuration object
var aConfig *config.Config
func main() {
c := config.Init()
setConfig(c)
// HTTP listener configuration
var (
port = c.Env.HTTPPort
httpAddr = flag.String("http.addr", ":"+port, "HTTP Listen Address")
)
flag.Parse()
// Create and configure the logger
var logger log.Logger
logger = log.NewLogfmtLogger(os.Stderr)
logger = hb.NewHerbertFormatLogger(logger, c.Env.LogPath, c.LogLevel())
logger = &serializedLogger{Logger: logger}
logger = log.With(logger,
"context_environment", c.Env.ApplicationEnvironment,
"timestamp", log.DefaultTimestampUTC,
)
// Repository initialization
var (
userRepo users.Repository
)
fieldKeys := []string{"method"}
userRepo = inmemory.NewInMemUserRepository()
// Initialize the users service and wrap it with our middlewares
var us users.Service
us = users.NewService(userRepo)
us = users.NewLoggingService(log.With(logger, "context_component", "users"), us)
us = users.NewInstrumentingService(
kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: "api",
Subsystem: "user_service",
Name: "request_count",
Help: "Number of requests received.",
}, fieldKeys),
kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
Namespace: "api",
Subsystem: "user_service",
Name: "request_latency_microseconds",
Help: "Total duration of requests in microseconds.",
}, fieldKeys),
us,
)
// Build and initialize our application HTTP handlers and error channels
httpLogger := log.With(logger, "context_component", "http")
mux := http.NewServeMux()
mux.Handle("/api/v1/users", users.MakeHandler(us, httpLogger))
mux.Handle("/api/v1/users/", users.MakeHandler(us, httpLogger))
mux.Handle("/api/v1/health", health.MakeHandler(httpLogger))
http.Handle("/", accessControl(mux))
http.Handle("/metrics", promhttp.Handler())
srv := http.Server{
WriteTimeout: 300 * time.Second,
ReadTimeout: 300 * time.Second,
Addr: *httpAddr,
}
// Define the atreides logging channels
errs := make(chan error, 2)
go func() {
logger.Log("transport", "http", "address", *httpAddr, "message", "listening")
errs <- srv.ListenAndServe()
}()
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
logger.Log("terminated", <-errs)
}
func setConfig(c *config.Config) {
aConfig = c
}
func accessControl(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type")
if r.Method == "OPTIONS" {
return
}
h.ServeHTTP(w, r)
})
}