/
http.go
112 lines (97 loc) · 2.7 KB
/
http.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
package api
import (
"encoding/json"
"net/http"
"runtime/pprof" //nolint:nolintlint
"time"
// enable profile
_ "net/http/pprof" //nolint
"github.com/projecteru2/agent/manager/workload"
"github.com/projecteru2/agent/types"
"github.com/projecteru2/agent/version"
"github.com/projecteru2/core/log"
"github.com/bmizerany/pat"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// JSON define a json
type JSON map[string]interface{}
// Handler define handler
type Handler struct {
config *types.Config
workloadsManager *workload.Manager
}
// URL /version/
func (h *Handler) version(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(JSON{"version": version.VERSION})
}
// URL /profile/
func (h *Handler) profile(w http.ResponseWriter, _ *http.Request) {
r := JSON{}
for _, p := range pprof.Profiles() {
r[p.Name()] = p.Count()
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(r)
}
// URL /log/
func (h *Handler) log(w http.ResponseWriter, req *http.Request) {
app := req.URL.Query().Get("app")
if app == "" {
w.WriteHeader(http.StatusBadRequest)
return
}
logger := log.WithFunc("log").WithField("path", "/log")
// fuck httpie
w.WriteHeader(http.StatusOK)
if hijack, ok := w.(http.Hijacker); ok {
conn, buf, err := hijack.Hijack()
if err != nil {
logger.Error(req.Context(), err, "connect failed")
return
}
defer conn.Close()
h.workloadsManager.PullLog(req.Context(), app, buf)
}
}
// NewHandler new api http handler
func NewHandler(config *types.Config, workloadsManager *workload.Manager) *Handler {
return &Handler{
config: config,
workloadsManager: workloadsManager,
}
}
// Serve start a api service
// blocks by http.ListenAndServe
// run this in a separated goroutine
func (h *Handler) Serve() {
if h.config.API.Addr == "" {
return
}
logger := log.WithFunc("serve")
restfulAPIServer := pat.New()
handlers := map[string]map[string]func(http.ResponseWriter, *http.Request){
"GET": {
"/profile/": h.profile,
"/version/": h.version,
"/log/": h.log,
},
}
for method, routes := range handlers {
for route, handler := range routes {
restfulAPIServer.Add(method, route, http.HandlerFunc(handler))
}
}
http.Handle("/", restfulAPIServer)
http.Handle("/metrics", promhttp.Handler())
logger.Infof(nil, "http api started %s", h.config.API.Addr) //nolint
server := &http.Server{
Addr: h.config.API.Addr,
ReadHeaderTimeout: 3 * time.Second,
}
if err := server.ListenAndServe(); err != nil {
logger.Error(nil, err, "http api start failed") //nolint
}
}