-
Notifications
You must be signed in to change notification settings - Fork 3
/
init.go
109 lines (97 loc) · 4.24 KB
/
init.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
package log
import (
"os"
"github.com/sourcegraph/log/internal/globallogger"
"github.com/sourcegraph/log/internal/otelfields"
)
var (
// EnvDevelopment is key of the environment variable that is used to set whether
// to use development logger configuration on Init.
EnvDevelopment = globallogger.EnvDevelopment
// EnvLogFormat is key of the environment variable that is used to set the log format
// on Init.
//
// The value should be one of 'json', 'json_gcp' or 'condensed', defaulting to 'json'.
EnvLogFormat = "SRC_LOG_FORMAT"
// EnvLogLevel is key of the environment variable that can be used to set the log
// level on Init.
//
// The value is one of 'debug', 'info', 'warn', 'error', or 'none', defaulting to
// 'warn'.
EnvLogLevel = "SRC_LOG_LEVEL"
// EnvLogScopeLevel is key of the environment variable that can be used to
// override the log level for specific scopes and its children.
//
// It has the format "SCOPE_0=LEVEL_0,SCOPE_1=LEVEL_1,...".
//
// Notes:
//
// - these levels do not respect the root level (SRC_LOG_LEVEL), so this
// allows operators to turn up the verbosity of specific logs.
// - this only affects the outputcore (ie will not effect sentrycore).
// - Scope matches the full scope name. IE the below example has the scope
// "foo.bar" not "bar".
//
// log.Scoped("foo", "").Scoped("bar", "")
EnvLogScopeLevel = "SRC_LOG_SCOPE_LEVEL"
// EnvLogSamplingInitial is key of the environment variable that can be used to set
// the number of entries with identical messages to always output per second.
//
// Defaults to 100 - set explicitly to 0 or -1 to disable.
EnvLogSamplingInitial = "SRC_LOG_SAMPLING_INITIAL"
// EnvLogSamplingThereafter is key of the environment variable that can be used to set
// the number of entries with identical messages to discard before emitting another
// one per second, after EnvLogSamplingInitial.
//
// Defaults to 100 - set explicitly to 0 or -1 to disable.
EnvLogSamplingThereafter = "SRC_LOG_SAMPLING_THEREAFTER"
)
type Resource = otelfields.Resource
// PostInitCallbacks is a set of callbacks returned by Init that enables finalization and
// updating of any configured sinks.
type PostInitCallbacks struct {
// Sync must be called before application exit, such as via defer.
//
// Note: The error from sync is suppressed since this is usually called as a
// defer in func main. In that case there isn't a reasonable way to handle the
// error. As such this function signature doesn't return an error.
Sync func()
// Update should be called to change sink configuration, e.g. via
// conf.Watch. Note that sinks not created upon initialization will
// not be created post-initialization. Is a no-op if no sinks are enabled.
Update func(SinksConfigGetter) func()
}
// Init initializes the log package's global logger as a logger of the given resource.
// It must be called on service startup, i.e. 'main()', NOT on an 'init()' function.
// Subsequent calls will panic, so do not call this within a non-service context.
//
// Init returns a set of callbacks - see PostInitCallbacks for more details. The Sync
// callback in particular must be called before application exit.
//
// For testing, you can use 'logtest.Init' to initialize the logging library.
//
// If Init is not called, trying to create a logger with Scoped will panic.
func Init(r Resource, s ...Sink) *PostInitCallbacks {
if globallogger.IsInitialized() {
panic("log.Init initialized multiple times")
}
// On initialization we get dev mode from env directly instead of from globallogger's
// package variable (globallogger.DevMode()) in case the caller has set an env var
// override, and globallogger.Init will update the global variable.
currentDevMode := os.Getenv(globallogger.EnvDevelopment) == "true"
// Initialize sinks
ss := sinks(append([]Sink{&outputSink{development: currentDevMode}}, s...))
cores, sinksBuildErr := ss.build()
// Init the logger first, so that we can log the error if needed, before dealing with
// sink builder errors
sync := globallogger.Init(r, currentDevMode, cores)
if sinksBuildErr != nil {
// Log the error
Scoped("log.init").
Fatal("sinks initialization failed", Error(sinksBuildErr))
}
return &PostInitCallbacks{
Sync: func() { _ = sync() },
Update: ss.update,
}
}