Cleans up a whole bunch of things I wanted to get out of the door right away: * depot internal references to //third_party/nixery have been replaced with //tools/nixery * cleaned up files from Github * fixed SPDX & Copyright headers * code formatting and inclusion in //tools/depotfmt checks Change-Id: Iea79f0fdf3aa04f71741d4f4032f88605ae415bb Reviewed-on: https://cl.tvl.fyi/c/depot/+/5486 Tested-by: BuildkiteCI Reviewed-by: tazjin <tazjin@tvl.su> Autosubmit: tazjin <tazjin@tvl.su>
		
			
				
	
	
		
			108 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2022 The TVL Contributors
 | |
| // SPDX-License-Identifier: Apache-2.0
 | |
| package logs
 | |
| 
 | |
| // This file configures different log formatters via logrus. The
 | |
| // standard formatter uses a structured JSON format that is compatible
 | |
| // with Stackdriver Error Reporting.
 | |
| //
 | |
| // https://cloud.google.com/error-reporting/docs/formatting-error-messages
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/json"
 | |
| 	log "github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| type stackdriverFormatter struct{}
 | |
| 
 | |
| type serviceContext struct {
 | |
| 	Service string `json:"service"`
 | |
| 	Version string `json:"version"`
 | |
| }
 | |
| 
 | |
| type reportLocation struct {
 | |
| 	FilePath     string `json:"filePath"`
 | |
| 	LineNumber   int    `json:"lineNumber"`
 | |
| 	FunctionName string `json:"functionName"`
 | |
| }
 | |
| 
 | |
| var nixeryContext = serviceContext{
 | |
| 	Service: "nixery",
 | |
| }
 | |
| 
 | |
| // isError determines whether an entry should be logged as an error
 | |
| // (i.e. with attached `context`).
 | |
| //
 | |
| // This requires the caller information to be present on the log
 | |
| // entry, as stacktraces are not available currently.
 | |
| func isError(e *log.Entry) bool {
 | |
| 	l := e.Level
 | |
| 	return (l == log.ErrorLevel || l == log.FatalLevel || l == log.PanicLevel) &&
 | |
| 		e.HasCaller()
 | |
| }
 | |
| 
 | |
| // logSeverity formats the entry's severity into a format compatible
 | |
| // with Stackdriver Logging.
 | |
| //
 | |
| // The two formats that are being mapped do not have an equivalent set
 | |
| // of severities/levels, so the mapping is somewhat arbitrary for a
 | |
| // handful of them.
 | |
| //
 | |
| // https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity
 | |
| func logSeverity(l log.Level) string {
 | |
| 	switch l {
 | |
| 	case log.TraceLevel:
 | |
| 		return "DEBUG"
 | |
| 	case log.DebugLevel:
 | |
| 		return "DEBUG"
 | |
| 	case log.InfoLevel:
 | |
| 		return "INFO"
 | |
| 	case log.WarnLevel:
 | |
| 		return "WARNING"
 | |
| 	case log.ErrorLevel:
 | |
| 		return "ERROR"
 | |
| 	case log.FatalLevel:
 | |
| 		return "CRITICAL"
 | |
| 	case log.PanicLevel:
 | |
| 		return "EMERGENCY"
 | |
| 	default:
 | |
| 		return "DEFAULT"
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (f stackdriverFormatter) Format(e *log.Entry) ([]byte, error) {
 | |
| 	msg := e.Data
 | |
| 	msg["serviceContext"] = &nixeryContext
 | |
| 	msg["message"] = &e.Message
 | |
| 	msg["eventTime"] = &e.Time
 | |
| 	msg["severity"] = logSeverity(e.Level)
 | |
| 
 | |
| 	if e, ok := msg[log.ErrorKey]; ok {
 | |
| 		if err, isError := e.(error); isError {
 | |
| 			msg[log.ErrorKey] = err.Error()
 | |
| 		} else {
 | |
| 			delete(msg, log.ErrorKey)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if isError(e) {
 | |
| 		loc := reportLocation{
 | |
| 			FilePath:     e.Caller.File,
 | |
| 			LineNumber:   e.Caller.Line,
 | |
| 			FunctionName: e.Caller.Function,
 | |
| 		}
 | |
| 		msg["context"] = &loc
 | |
| 	}
 | |
| 
 | |
| 	b := new(bytes.Buffer)
 | |
| 	err := json.NewEncoder(b).Encode(&msg)
 | |
| 
 | |
| 	return b.Bytes(), err
 | |
| }
 | |
| 
 | |
| func Init(version string) {
 | |
| 	nixeryContext.Version = version
 | |
| 	log.SetReportCaller(true)
 | |
| 	log.SetFormatter(stackdriverFormatter{})
 | |
| }
 |