Skip to content

Commit

Permalink
Add support for gcp error reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
michaellzc committed Aug 24, 2023
1 parent 40c57b6 commit ecd6b9d
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 10 deletions.
2 changes: 2 additions & 0 deletions cmd/example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ func main() {
log.EnvLogScopeLevel,
log.EnvLogSamplingInitial,
log.EnvLogSamplingThereafter,
log.EnvLogStackTraceLevel,
} {
config = append(config, log.String(k, os.Getenv(k)))
}
l.Info("configuration", config...)

// sample message
l.Warn("hello world!", log.Time("now", time.Now()))
l.Error("hello world!", log.Time("now", time.Now()))
}
12 changes: 11 additions & 1 deletion init.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ var (
//
// Defaults to 100 - set explicitly to 0 or -1 to disable.
EnvLogSamplingThereafter = "SRC_LOG_SAMPLING_THEREAFTER"
// EnvLogStackTraceLevel is a key of the environment variable that can be used to set
// the log level to include stack traces on.
// Default does not include stack traces on any level.
EnvLogStackTraceLevel = "SRC_LOG_STACKTRACE_LEVEL"
)

type Resource = otelfields.Resource
Expand Down Expand Up @@ -94,7 +98,13 @@ func Init(r Resource, s ...Sink) *PostInitCallbacks {

// 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)
loggerOption := globallogger.LoggerOption{
Development: currentDevMode,
}
if os.Getenv(EnvLogStackTraceLevel) != "" {
loggerOption.StackTraceLevel = Level(os.Getenv(EnvLogStackTraceLevel)).Parse()
}
sync := globallogger.Init(r, loggerOption, cores)

if sinksBuildErr != nil {
// Log the error
Expand Down
7 changes: 4 additions & 3 deletions internal/encoders/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ var GCPConfig = zapcore.EncoderConfig{
// These don't really have an equivalent in the OT spec, and we can't stick it under
// Attributes because they are top-level traits in Zap, so we just capitalize them and
// hope for the best.
CallerKey: "Caller",
FunctionKey: "Function",
StacktraceKey: "Stacktrace",
CallerKey: "Caller",
FunctionKey: "Function",
// https://cloud.google.com/error-reporting/docs/formatting-error-messages#log-error
StacktraceKey: "stack_trace",

// Defaults
LineEnding: zapcore.DefaultLineEnding,
Expand Down
22 changes: 16 additions & 6 deletions internal/globallogger/globallogger.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ func Get(safe bool) *zap.Logger {

// Init initializes the global logger once. Subsequent calls are no-op. Returns the
// callback to sync the root core.
func Init(r otelfields.Resource, development bool, sinks []zapcore.Core) func() error {
func Init(r otelfields.Resource, opt LoggerOption, sinks []zapcore.Core) func() error {
globalLoggerInit.Do(func() {
devMode = development
globalLogger = initLogger(r, development, sinks)
devMode = opt.Development
globalLogger = initLogger(r, opt, sinks)
initialized.Store(true)
})
return globalLogger.Sync
Expand All @@ -62,6 +62,11 @@ type forceSyncer struct {
core zapcore.Core
}

type LoggerOption struct {
Development bool
StackTraceLevel zapcore.Level
}

var _ zapcore.CheckWriteHook = &forceSyncer{}

// OnWrite calls sync on the underlying core and then calls os.Exit(1).
Expand All @@ -71,14 +76,14 @@ func (f *forceSyncer) OnWrite(_ *zapcore.CheckedEntry, _ []zapcore.Field) {
os.Exit(1)
}

func initLogger(r otelfields.Resource, development bool, sinks []zapcore.Core) *zap.Logger {
func initLogger(r otelfields.Resource, opt LoggerOption, sinks []zapcore.Core) *zap.Logger {
internalErrsSink, err := stderr.Open()
if err != nil {
panic(err.Error())
}

options := []zap.Option{zap.ErrorOutput(internalErrsSink), zap.AddCaller()}
if development {
if opt.Development {
options = append(options, zap.Development())
}

Expand All @@ -87,9 +92,14 @@ func initLogger(r otelfields.Resource, development bool, sinks []zapcore.Core) *
// Add a forceSyncer on the core to ensure Sync is executed on the underlying core when Fatal is called, since
// after Fatal os.Exit is called per default configuration
options = append(options, zap.WithFatalHook(&forceSyncer{core}))

if opt.StackTraceLevel != zapcore.Level(0) {
options = append(options, zap.AddStacktrace(opt.StackTraceLevel))
}

logger := zap.New(core, options...)

if development {
if opt.Development {
return logger
}

Expand Down

0 comments on commit ecd6b9d

Please sign in to comment.