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
|
package main
import (
"fmt"
"log"
"net"
"net/http"
"os"
"gitlab.com/gitlab-org/gitaly/internal/config"
"gitlab.com/gitlab-org/gitaly/internal/service"
"gitlab.com/gitlab-org/gitaly/internal/service/middleware/panichandler"
"github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/mwitkow/go-grpc-middleware"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
var version string
func loadConfig() {
switch {
case len(os.Args) >= 2:
cfgFile, err := os.Open(os.Args[1])
if err != nil {
log.Printf("warning: can not open file for reading: %q: %v", os.Args[1], err)
break
}
defer cfgFile.Close()
if err = config.Load(cfgFile); err != nil {
log.Printf("warning: can not load configuration: %q: %v", os.Args[1], err)
}
default:
log.Printf("warning: no configuration file given")
if err := config.Load(nil); err != nil {
log.Printf("warning: can not load configuration: %v", err)
}
}
}
func validateConfig() error {
if config.Config.SocketPath == "" && config.Config.ListenAddr == "" {
return fmt.Errorf("Must set $GITALY_SOCKET_PATH or $GITALY_LISTEN_ADDR")
}
return config.ValidateStorages()
}
func main() {
log.Println("Starting Gitaly", version)
loadConfig()
if err := validateConfig(); err != nil {
log.Fatal(err)
}
var listeners []net.Listener
if socketPath := config.Config.SocketPath; socketPath != "" {
l, err := createUnixListener(socketPath)
if err != nil {
log.Fatalf("configure unix listener: %v", err)
}
log.Printf("listening on unix socket %q", socketPath)
listeners = append(listeners, l)
}
if addr := config.Config.ListenAddr; addr != "" {
l, err := net.Listen("tcp", addr)
if err != nil {
log.Fatalf("configure tcp listener: %v", err)
}
log.Printf("listening at tcp address %q", addr)
listeners = append(listeners, l)
}
server := grpc.NewServer(
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
panichandler.StreamPanicHandler, // Panic Handler first: handle panics gracefully
grpc_prometheus.StreamServerInterceptor, // Prometheus Metrics next: measure RPC times
)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
panichandler.UnaryPanicHandler, // Panic Handler first: handle panics gracefully
grpc_prometheus.UnaryServerInterceptor, // Prometheus Metrics next: measure RPC times
)),
)
service.RegisterAll(server)
reflection.Register(server)
// After all your registrations, make sure all of the Prometheus metrics are initialized.
grpc_prometheus.Register(server)
serverError := make(chan error, len(listeners))
for _, listener := range listeners {
// Must pass the listener as a function argument because there is a race
// between 'go' and 'for'.
go func(l net.Listener) {
serverError <- server.Serve(l)
}(listener)
}
if config.Config.PrometheusListenAddr != "" {
log.Print("Starting prometheus listener ", config.Config.PrometheusListenAddr)
promMux := http.NewServeMux()
promMux.Handle("/metrics", promhttp.Handler())
go func() {
http.ListenAndServe(config.Config.PrometheusListenAddr, promMux)
}()
}
log.Fatal(<-serverError)
}
func createUnixListener(socketPath string) (net.Listener, error) {
if err := os.Remove(socketPath); err != nil && !os.IsNotExist(err) {
return nil, err
}
return net.Listen("unix", socketPath)
}
|