This repository has been archived by the owner on Apr 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
126 lines (113 loc) · 3.6 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
/*
Package stackrus provides a Hooks for logrus for both the asynchronous
and synchronous versions of the official Go client library for Stackdriver.
An example:
package main
import (
"context"
"cloud.google.com/go/logging"
log "github.com/sirupsen/logrus"
"github.com/recursionpharma/stackrus"
)
func main() {
client, _ := logging.NewClient(context.Background(), "my-project")
defer client.Close() // The default client is asynchronous/buffered, so Close() should be called to send final packets
h := stackrus.New(client, "my-log")
log.AddHook(h)
log.WithFields(log.Fields{
"animal": "walrus",
"number": 1,
"size": 10,
}).Info("A walrus appears")
}
Output:
time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
// Note that Fields are automatically translated to Stackdriver labels.
*/
package stackrus
import (
"context"
"fmt"
"cloud.google.com/go/logging"
"github.com/sirupsen/logrus"
)
type Hook struct {
client *logging.Client
logger *logging.Logger
syncCtx context.Context
sync bool
}
func initHook(sync bool, client *logging.Client, logID string, opts ...logging.LoggerOption) *Hook {
h := &Hook{client: client, sync: sync, syncCtx: context.Background()}
h.logger = h.client.Logger(logID, opts...)
return h
}
// New returns a logrus hook for the given client and
// relays logs to the Stackdriver API asynchronously. It is the client's
// responsibility to call client.Close() so that buffered logs get
// written before the end of the program!
func New(client *logging.Client, logID string, opts ...logging.LoggerOption) *Hook {
return initHook(false, client, logID, opts...)
}
// NewSync returns a logrus hook for the given client and
// relays logs to the Stackdriver API synchronously. Not recommended for
// typical use (see https://godoc.org/cloud.google.com/go/logging#hdr-Synchronous_Logging)
// In order to use a non-background context for a LogSync entry, call SetSyncContext on the
// returned hook.
func NewSync(client *logging.Client, logID string, opts ...logging.LoggerOption) *Hook {
return initHook(true, client, logID, opts...)
}
func (h *Hook) SetSyncContext(ctx context.Context) {
h.syncCtx = ctx
}
func mapLogrusToStackdriverLevel(l logrus.Level) logging.Severity {
switch l {
case logrus.DebugLevel:
return logging.Debug
case logrus.InfoLevel:
return logging.Info
case logrus.WarnLevel:
return logging.Warning
case logrus.ErrorLevel:
return logging.Error
case logrus.FatalLevel:
return logging.Critical
case logrus.PanicLevel:
return logging.Alert
default:
return logging.Debug // Should never happen
}
}
// Levels returns the logrus levels that this hook is applied to.
// TODO: Allow configuration.
func (h *Hook) Levels() []logrus.Level {
return logrus.AllLevels
}
// Fire sends the log entry to Stackdriver either synchrounously or asynchronously, depending
// on how the hook was instantiated. Levels from Logrus are mapped to the Stackdriver API levels
// (https://godoc.org/cloud.google.com/go/logging#pkg-constants) as follows:
// [logrus Level] -> [Stackdriver Level]
// Debug, Info, Warning, Error -> (same)
// Fatal -> Critical
// Panic -> Alert
func (h *Hook) Fire(e *logrus.Entry) error {
entry := logging.Entry{
Timestamp: e.Time,
Severity: mapLogrusToStackdriverLevel(e.Level),
Payload: e.Message,
}
entry.Labels = make(map[string]string)
for k, v := range e.Data {
switch t := v.(type) {
case string:
entry.Labels[k] = t
default:
entry.Labels[k] = fmt.Sprintf("%v", t)
}
}
if h.sync {
return h.logger.LogSync(h.syncCtx, entry)
}
h.logger.Log(entry)
return nil
}