-
Notifications
You must be signed in to change notification settings - Fork 204
/
logs_handler.go
130 lines (102 loc) · 3 KB
/
logs_handler.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
package v2
import (
"bytes"
"encoding/json"
"errors"
"net/http"
"reflect"
"strconv"
"strings"
"time"
"github.com/SpectoLabs/hoverfly/core/handlers"
"github.com/SpectoLabs/hoverfly/core/util"
"github.com/codegangsta/negroni"
"github.com/go-zoo/bone"
"github.com/sirupsen/logrus"
)
const defaultTimestampFormat = time.RFC3339
type HoverflyLogs interface {
GetLogs(limit int, from *time.Time) ([]*logrus.Entry, error)
}
type LogsHandler struct {
Hoverfly HoverflyLogs
}
const DefaultLogLimit = 500
func (this *LogsHandler) RegisterRoutes(mux *bone.Mux, am *handlers.AuthHandler) {
mux.Get("/api/v2/logs", negroni.New(
negroni.HandlerFunc(am.RequireTokenAuthentication),
negroni.HandlerFunc(this.Get),
))
mux.Options("/api/v2/logs", negroni.New(
negroni.HandlerFunc(this.Options),
))
mux.Get("/api/v2/ws/logs", http.HandlerFunc(this.GetWS))
}
func (this *LogsHandler) Get(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
queryParams := req.URL.Query()
limitQuery, _ := strconv.Atoi(queryParams.Get("limit"))
if limitQuery == 0 {
limitQuery = DefaultLogLimit
}
fromTime := util.GetUnixTimeQueryParam(req, "from")
logs, err := this.Hoverfly.GetLogs(limitQuery, fromTime)
if err != nil {
handlers.WriteErrorResponse(w, err.Error(), http.StatusInternalServerError)
return
}
if strings.Contains(req.Header.Get("Accept"), "text/plain") ||
strings.Contains(req.Header.Get("Content-Type"), "text/plain") {
handlers.WriteResponse(w, []byte(logsToPlainText(logs)))
} else {
bytes, _ := json.Marshal(logsToLogsView(logs))
handlers.WriteResponse(w, bytes)
}
}
func (this *LogsHandler) Options(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
w.Header().Add("Allow", "OPTIONS, GET")
handlers.WriteResponse(w, []byte(""))
}
func logsToLogsView(logs []*logrus.Entry) LogsView {
var logInterfaces []map[string]interface{}
for _, entry := range logs {
data := make(map[string]interface{}, len(entry.Data)+3)
for k, v := range entry.Data {
data[k] = v
}
data["time"] = entry.Time.Format(defaultTimestampFormat)
data["msg"] = entry.Message
data["level"] = entry.Level.String()
logInterfaces = append(logInterfaces, data)
}
return LogsView{
Logs: logInterfaces,
}
}
func logsToPlainText(logs []*logrus.Entry) string {
var buffer bytes.Buffer
for _, entry := range logs {
entry.Logger = logrus.New()
entry.Logger.Formatter = &logrus.TextFormatter{
ForceColors: true,
DisableTimestamp: false,
FullTimestamp: true,
}
log, err := entry.String()
if err == nil {
buffer.WriteString(log)
}
}
return buffer.String()
}
func (this *LogsHandler) GetWS(w http.ResponseWriter, r *http.Request) {
var previousLogs LogsView
handlers.NewWebsocket(func() ([]byte, error) {
logs, _ := this.Hoverfly.GetLogs(500, nil)
currentLogs := logsToLogsView(logs)
if !reflect.DeepEqual(currentLogs, previousLogs) {
previousLogs = currentLogs
return json.Marshal(currentLogs)
}
return nil, errors.New("No update needed")
}, w, r)
}