package logs import ( "errors" "fmt" "net/http" "net/url" "os" "runtime" "strings" "github.com/MindscapeHQ/raygun4go" "github.com/aws/aws-lambda-go/events" log "github.com/sirupsen/logrus" ) var logger *log.Entry var apiRequest *events.APIGatewayProxyRequest var currentRequestID *string var isDebug = false var build string var raygunClient *raygun4go.Client // TODO // Sensitive word filtering func InitLogs(requestID *string, isDebugBuild bool, buildVersion string, request *events.APIGatewayProxyRequest, client *raygun4go.Client) { currentRequestID = requestID apiRequest = request isDebug = isDebugBuild build = buildVersion raygunClient = client if isDebugBuild { log.SetReportCaller(true) log.SetFormatter(&log.TextFormatter{ ForceColors: true, PadLevelText: true, DisableTimestamp: true, CallerPrettyfier: func(f *runtime.Frame) (string, string) { // Exclude the caller, will rather be added as a field return "", "" }, }) } else { log.SetReportCaller(true) log.SetFormatter(&log.JSONFormatter{ CallerPrettyfier: func(f *runtime.Frame) (string, string) { // Exclude the caller, will rather be added as a field return "", "" }}) } log.SetLevel(LogLevel()) val, exists := os.LookupEnv("DEBUGGING") if exists && val == "true" { log.SetLevel(log.TraceLevel) log.SetReportCaller(true) } logger = log.WithFields(log.Fields{ "environment": getEnvironment(), }) if requestID != nil { logger = log.WithFields(log.Fields{ "request_id": *requestID, }) } } func LogLevel() log.Level { logLevelString := os.Getenv("LOG_LEVEL") logLevel := log.InfoLevel if logLevelString != "" { logLevelString = strings.ToLower(logLevelString) switch logLevelString { case "error": logLevel = log.ErrorLevel case "warn": logLevel = log.WarnLevel case "info": logLevel = log.InfoLevel case "debug": logLevel = log.DebugLevel } log.SetLevel(logLevel) } return logLevel } func getEnvironment() string { environment := os.Getenv("ENVIRONMENT") if environment == "" { environment = "dev" os.Setenv("ENVIRONMENT", "dev") } return environment } func getLogger() *log.Entry { if logger == nil { logger = log.WithFields(log.Fields{ "environment": getEnvironment(), }) } return logger } func InfoWithFields(fields map[string]interface{}, message interface{}) { getLogger().WithFields(fields).Info(message) } func Info(format string, a ...interface{}) { getLogger().Info(fmt.Sprintf(format, a...)) } func ErrorWithFields(fields map[string]interface{}, err error) { sendRaygunError(fields, err) getLogger().WithFields(fields).Error(err) } func ErrorWithMsg(message string, err error) { if err == nil { err = errors.New(message) } ErrorWithFields(map[string]interface{}{ "message": message, }, err) } func ErrorMsg(message string) { ErrorWithMsg(message, nil) } func Warn(format string, a ...interface{}) { getLogger().Warn(fmt.Sprintf(format, a...)) } func WarnWithFields(fields map[string]interface{}, err error) { getLogger().WithFields(fields).Warn(err) } func SQLDebugInfo(sql string) { getLogger().WithFields(map[string]interface{}{ "sql": sql, }).Debug("SQL query") } func LogShipmentID(id int64) { InfoWithFields(map[string]interface{}{ "shipment_id": id, }, "Current-shipment-ID") } func LogRequestInfo(req events.APIGatewayProxyRequest) { InfoWithFields(map[string]interface{}{ "http_method": req.HTTPMethod, "path": req.Path, "api_gateway_request_id": req.RequestContext.RequestID, "user_cognito_auth_provider": req.RequestContext.Identity.CognitoAuthenticationProvider, "user_arn": req.RequestContext.Identity.UserArn, }, "Request Info start") } func LogApiAudit(fields log.Fields) { getLogger().WithFields(fields).Info("api-audit-log") } func LogSQSEvent(event events.SQSEvent) { InfoWithFields(map[string]interface{}{ "records": event.Records, }, "SQS event start") } func SetOutputToFile(file *os.File) { log.SetOutput(file) } func ClearInfo() { logger = nil } func sendRaygunError(fields map[string]interface{}, errToSend error) { if isDebug || raygunClient == nil { // Don't log raygun errors on debug return } env := getEnvironment() tags := []string{env} raygunClient.Version(build) tags = append(tags, build) if apiRequest != nil { methodAndPath := apiRequest.HTTPMethod + ": " + apiRequest.Path tags = append(tags, methodAndPath) fields["body"] = apiRequest.Body fields["query"] = apiRequest.QueryStringParameters fields["identity"] = apiRequest.RequestContext.Identity } raygunClient.Tags(tags) if currentRequestID != nil { fields["request_id"] = currentRequestID } fields["env"] = env raygunClient.CustomData(fields) raygunClient.Request(fakeHttpRequest()) if errToSend == nil { errToSend = errors.New("") } err := raygunClient.SendError(errToSend) if err != nil { log.Println("Failed to send raygun error:", err.Error()) } } func fakeHttpRequest() *http.Request { if apiRequest == nil { return nil } requestURL := url.URL{ Path: apiRequest.Path, Host: apiRequest.Headers["Host"], } request := http.Request{ Method: apiRequest.HTTPMethod, URL: &requestURL, Header: apiRequest.MultiValueHeaders, } return &request }