From 953ea6147ed15127c18fce5d7c7316de9ee79a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Alves?= Date: Wed, 16 May 2018 10:07:57 +0100 Subject: [PATCH 01/21] added http request, trace, logName and source location structures --- formatter.go | 69 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/formatter.go b/formatter.go index 9d36f4b..982bcb4 100644 --- a/formatter.go +++ b/formatter.go @@ -33,29 +33,50 @@ var levelsToSeverity = map[logrus.Level]severity{ logrus.PanicLevel: severityAlert, } -type serviceContext struct { +type ServiceContext struct { Service string `json:"service,omitempty"` Version string `json:"version,omitempty"` } -type reportLocation struct { - FilePath string `json:"filePath,omitempty"` - LineNumber int `json:"lineNumber,omitempty"` - FunctionName string `json:"functionName,omitempty"` +type ReportLocation struct { + FilePath string `json:"file,omitempty"` + LineNumber int `json:"line,omitempty"` + FunctionName string `json:"function,omitempty"` } -type context struct { +type Context struct { Data map[string]interface{} `json:"data,omitempty"` - ReportLocation *reportLocation `json:"reportLocation,omitempty"` + ReportLocation *ReportLocation `json:"reportLocation,omitempty"` HTTPRequest map[string]interface{} `json:"httpRequest,omitempty"` } -type entry struct { +type HttpRequest struct { + RequestMethod string `json:"requestMethod,omitempty"` + RequestUrl string `json:"requestUrl,omitempty"` + RequestSize string `json:"requestSize,omitempty"` + Status int `json:"status,omitempty"` + ResponseSize string `json:"responseSize,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + ServerIp string `json:"serverIp,omitempty"` + Referer string `json:"referer,omitempty"` + Latency string `json:"latency,omitempty"` + CacheLookup bool `json:"cacheLookup,omitempty"` + CacheHit bool `json:"cacheHit,omitempty"` + CacheValidatedWithOriginServer bool `json:"cacheValidatedWithOriginServer,omitempty"` + CacheFillBytes string `json:"cacheFillBytes,omitempty"` + Protocol string `json:"protocol,omitempty"` +} + +type Entry struct { + LogName string `json:"logName,omitempty"` Timestamp string `json:"timestamp,omitempty"` - ServiceContext *serviceContext `json:"serviceContext,omitempty"` - Message string `json:"message,omitempty"` Severity severity `json:"severity,omitempty"` - Context *context `json:"context,omitempty"` + HTTPRequest *HttpRequest `json:"httpRequest"` + Trace string `json:"trace,omitempty"` + ServiceContext *ServiceContext `json:"serviceContext,omitempty"` + Message string `json:"message,omitempty"` + Context *Context `json:"context,omitempty"` + SourceLocation *ReportLocation `json:"sourceLocation,omitempty"` } // Formatter implements Stackdriver formatting for logrus. @@ -133,22 +154,34 @@ func (f *Formatter) errorOrigin() (stack.Call, error) { func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { severity := levelsToSeverity[e.Level] - ee := entry{ + ee := Entry{ Message: e.Message, Severity: severity, - Context: &context{ + Context: &Context{ Data: e.Data, }, } + // if val, ok := e.Data["trace"]; ok { + // ee.Trace = val.(string) + // } + + if val, ok := e.Data["httpRequest"]; ok { + ee.HTTPRequest = val.(*HttpRequest) + } + + if val, ok := e.Data["logName"]; ok { + ee.LogName = val.(string) + } + if !skipTimestamp { ee.Timestamp = time.Now().UTC().Format(time.RFC3339) } switch severity { case severityError, severityCritical, severityAlert: - ee.ServiceContext = &serviceContext{ + ee.ServiceContext = &ServiceContext{ Service: f.Service, Version: f.Version, } @@ -176,7 +209,13 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { if c, err := f.errorOrigin(); err == nil { lineNumber, _ := strconv.ParseInt(fmt.Sprintf("%d", c), 10, 64) - ee.Context.ReportLocation = &reportLocation{ + ee.Context.ReportLocation = &ReportLocation{ + FilePath: fmt.Sprintf("%+s", c), + LineNumber: int(lineNumber), + FunctionName: fmt.Sprintf("%n", c), + } + + ee.SourceLocation = &ReportLocation{ FilePath: fmt.Sprintf("%+s", c), LineNumber: int(lineNumber), FunctionName: fmt.Sprintf("%n", c), From 34738480ba30d3c112a0c5d127e6282443b89135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Alves?= Date: Wed, 16 May 2018 10:09:30 +0100 Subject: [PATCH 02/21] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 072e578..80c1e73 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ package main import ( "github.com/sirupsen/logrus" - stackdriver "github.com/TV4/logrus-stackdriver-formatter" + stackdriver "github.com/brpx/logrus-stackdriver-formatter" ) var log = logrus.New() From 475780bc52fb33d479074e405de5451efabe40d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Alves?= Date: Wed, 16 May 2018 11:53:51 +0100 Subject: [PATCH 03/21] bug fix http request --- formatter.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/formatter.go b/formatter.go index 982bcb4..adddc27 100644 --- a/formatter.go +++ b/formatter.go @@ -71,7 +71,7 @@ type Entry struct { LogName string `json:"logName,omitempty"` Timestamp string `json:"timestamp,omitempty"` Severity severity `json:"severity,omitempty"` - HTTPRequest *HttpRequest `json:"httpRequest"` + HTTPRequest *HttpRequest `json:"httpRequest,omitempty"` Trace string `json:"trace,omitempty"` ServiceContext *ServiceContext `json:"serviceContext,omitempty"` Message string `json:"message,omitempty"` @@ -163,9 +163,9 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { }, } - // if val, ok := e.Data["trace"]; ok { - // ee.Trace = val.(string) - // } + if val, ok := e.Data["trace"]; ok { + ee.Trace = val.(string) + } if val, ok := e.Data["httpRequest"]; ok { ee.HTTPRequest = val.(*HttpRequest) From a23b1a05fe4b2ed632b8e5d8ebb8d2549def0c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Alves?= Date: Wed, 16 May 2018 15:23:50 +0100 Subject: [PATCH 04/21] change response size type --- formatter.go | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/formatter.go b/formatter.go index adddc27..c3e5b3d 100644 --- a/formatter.go +++ b/formatter.go @@ -51,20 +51,21 @@ type Context struct { } type HttpRequest struct { - RequestMethod string `json:"requestMethod,omitempty"` - RequestUrl string `json:"requestUrl,omitempty"` - RequestSize string `json:"requestSize,omitempty"` - Status int `json:"status,omitempty"` - ResponseSize string `json:"responseSize,omitempty"` - UserAgent string `json:"userAgent,omitempty"` - ServerIp string `json:"serverIp,omitempty"` - Referer string `json:"referer,omitempty"` - Latency string `json:"latency,omitempty"` - CacheLookup bool `json:"cacheLookup,omitempty"` - CacheHit bool `json:"cacheHit,omitempty"` - CacheValidatedWithOriginServer bool `json:"cacheValidatedWithOriginServer,omitempty"` - CacheFillBytes string `json:"cacheFillBytes,omitempty"` - Protocol string `json:"protocol,omitempty"` + RequestMethod string `json:"requestMethod,omitempty"` + RequestUrl string `json:"requestUrl,omitempty"` + RequestSize string `json:"requestSize,omitempty"` + Status int `json:"status,omitempty"` + ResponseSize int64 `json:"responseSize,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + RemoteIp string `json:"remoteIp,omitempty"` + ServerIp string `json:"serverIp,omitempty"` + Referer string `json:"referer,omitempty"` + Latency time.Duration `json:"latency,omitempty"` + CacheLookup bool `json:"cacheLookup,omitempty"` + CacheHit bool `json:"cacheHit,omitempty"` + CacheValidatedWithOriginServer bool `json:"cacheValidatedWithOriginServer,omitempty"` + CacheFillBytes string `json:"cacheFillBytes,omitempty"` + Protocol string `json:"protocol,omitempty"` } type Entry struct { From d4a463cd3901621dd325d7d3a5353ab53d9b6fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Alves?= Date: Wed, 16 May 2018 17:06:08 +0100 Subject: [PATCH 05/21] change types of the http request struct --- formatter.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/formatter.go b/formatter.go index c3e5b3d..e482e61 100644 --- a/formatter.go +++ b/formatter.go @@ -51,21 +51,21 @@ type Context struct { } type HttpRequest struct { - RequestMethod string `json:"requestMethod,omitempty"` - RequestUrl string `json:"requestUrl,omitempty"` - RequestSize string `json:"requestSize,omitempty"` - Status int `json:"status,omitempty"` - ResponseSize int64 `json:"responseSize,omitempty"` - UserAgent string `json:"userAgent,omitempty"` - RemoteIp string `json:"remoteIp,omitempty"` - ServerIp string `json:"serverIp,omitempty"` - Referer string `json:"referer,omitempty"` - Latency time.Duration `json:"latency,omitempty"` - CacheLookup bool `json:"cacheLookup,omitempty"` - CacheHit bool `json:"cacheHit,omitempty"` - CacheValidatedWithOriginServer bool `json:"cacheValidatedWithOriginServer,omitempty"` - CacheFillBytes string `json:"cacheFillBytes,omitempty"` - Protocol string `json:"protocol,omitempty"` + RequestMethod string `json:"requestMethod,omitempty"` + RequestUrl string `json:"requestUrl,omitempty"` + RequestSize string `json:"requestSize,omitempty"` + Status string `json:"status,omitempty"` + ResponseSize string `json:"responseSize,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + RemoteIp string `json:"remoteIp,omitempty"` + ServerIp string `json:"serverIp,omitempty"` + Referer string `json:"referer,omitempty"` + Latency string `json:"latency,omitempty"` + CacheLookup bool `json:"cacheLookup,omitempty"` + CacheHit bool `json:"cacheHit,omitempty"` + CacheValidatedWithOriginServer bool `json:"cacheValidatedWithOriginServer,omitempty"` + CacheFillBytes string `json:"cacheFillBytes,omitempty"` + Protocol string `json:"protocol,omitempty"` } type Entry struct { From 2501d1c5a21e8f78badfbfa6e579b9e036ea3ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Alves?= Date: Wed, 16 May 2018 17:20:08 +0100 Subject: [PATCH 06/21] added projectID and logID to build the logName correctly --- formatter.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/formatter.go b/formatter.go index e482e61..56c06d5 100644 --- a/formatter.go +++ b/formatter.go @@ -84,6 +84,7 @@ type Entry struct { type Formatter struct { Service string Version string + ProjectID string StackSkip []string } @@ -104,6 +105,12 @@ func WithVersion(v string) Option { } } +func WithProjectID(i string) Option { + return func(f *Formatter) { + f.ProjectID = i + } +} + // WithStackSkip lets you configure which packages should be skipped for locating the error. func WithStackSkip(v string) Option { return func(f *Formatter) { @@ -172,8 +179,8 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { ee.HTTPRequest = val.(*HttpRequest) } - if val, ok := e.Data["logName"]; ok { - ee.LogName = val.(string) + if val, ok := e.Data["logID"]; ok { + ee.LogName = "projects/" + f.ProjectID + "/logs/" + val.(string) } if !skipTimestamp { From 5e4ed8a35eba925f79e184b48c3f0e73d0fcccb6 Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Sat, 23 Jun 2018 09:32:21 +0200 Subject: [PATCH 07/21] Format errors correctly Errors included in a logrus.Entry are not formatted correctly. This is caused by https://github.com/sirupsen/logrus/issues/137 --- formatter.go | 18 +++++++++++++++++- formatter_test.go | 30 ++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/formatter.go b/formatter.go index 9d36f4b..9077f66 100644 --- a/formatter.go +++ b/formatter.go @@ -129,6 +129,22 @@ func (f *Formatter) errorOrigin() (stack.Call, error) { } } +// taken from https://github.com/sirupsen/logrus/blob/master/json_formatter.go#L51 +func replaceErrors(source logrus.Fields) logrus.Fields { + data := make(logrus.Fields, len(source)) + for k, v := range source { + switch v := v.(type) { + case error: + // Otherwise errors are ignored by `encoding/json` + // https://github.com/sirupsen/logrus/issues/137 + data[k] = v.Error() + default: + data[k] = v + } + } + return data +} + // Format formats a logrus entry according to the Stackdriver specifications. func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { severity := levelsToSeverity[e.Level] @@ -138,7 +154,7 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { Message: e.Message, Severity: severity, Context: &context{ - Data: e.Data, + Data: replaceErrors(e.Data), }, } diff --git a/formatter_test.go b/formatter_test.go index 56c6544..d9728f1 100644 --- a/formatter_test.go +++ b/formatter_test.go @@ -54,6 +54,24 @@ var formatterTests = []struct { }, }, }, + { + run: func(logger *logrus.Logger) { + logger. + WithField("foo", "bar"). + WithError(errors.New("test error")). + Info("my log entry") + }, + out: map[string]interface{}{ + "severity": "INFO", + "message": "my log entry", + "context": map[string]interface{}{ + "data": map[string]interface{}{ + "foo": "bar", + "error": "test error", + }, + }, + }, + }, { run: func(logger *logrus.Logger) { logger.WithField("foo", "bar").Error("my log entry") @@ -71,8 +89,8 @@ var formatterTests = []struct { }, "reportLocation": map[string]interface{}{ "filePath": "github.com/TV4/logrus-stackdriver-formatter/formatter_test.go", - "lineNumber": 59.0, - "functionName": "glob..func2", + "lineNumber": 77.0, + "functionName": "glob..func3", }, }, }, @@ -97,8 +115,8 @@ var formatterTests = []struct { }, "reportLocation": map[string]interface{}{ "filePath": "github.com/TV4/logrus-stackdriver-formatter/formatter_test.go", - "lineNumber": 85.0, - "functionName": "glob..func3", + "lineNumber": 103.0, + "functionName": "glob..func4", }, }, }, @@ -130,8 +148,8 @@ var formatterTests = []struct { }, "reportLocation": map[string]interface{}{ "filePath": "github.com/TV4/logrus-stackdriver-formatter/formatter_test.go", - "lineNumber": 115.0, - "functionName": "glob..func4", + "lineNumber": 133.0, + "functionName": "glob..func5", }, }, }, From 1af0b4237e3063050b4e9b1d80691d6f5231d9dd Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Fri, 28 Dec 2018 22:33:17 +0000 Subject: [PATCH 08/21] Add deps --- go.mod | 6 ++++++ go.sum | 13 +++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..43d4a61 --- /dev/null +++ b/go.mod @@ -0,0 +1,6 @@ +module github.com/icco/logrus-stackdriver-formatter + +require ( + github.com/go-stack/stack v1.8.0 + github.com/sirupsen/logrus v1.2.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f14a3ff --- /dev/null +++ b/go.sum @@ -0,0 +1,13 @@ +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From a1ea5a778488e4e0fedb80465c0af997d3cd1530 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Fri, 28 Dec 2018 23:21:23 +0000 Subject: [PATCH 09/21] Remove final newline --- formatter.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/formatter.go b/formatter.go index d91eb0a..8f54f95 100644 --- a/formatter.go +++ b/formatter.go @@ -179,7 +179,6 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { severity := levelsToSeverity[e.Level] ee := Entry{ - Message: e.Message, Severity: severity, Context: &Context{ @@ -252,5 +251,5 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { return nil, err } - return append(b, '\n'), nil + return b, nil } From 69791ff2054a342131fc0089bf23026ef7c0b357 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Sat, 29 Dec 2018 04:28:11 +0000 Subject: [PATCH 10/21] readd newlines --- formatter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/formatter.go b/formatter.go index 8f54f95..0849511 100644 --- a/formatter.go +++ b/formatter.go @@ -251,5 +251,5 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { return nil, err } - return b, nil + return append(b, '\n'), nil } From 7742696d90d5d3acc146e8c7f1a37035a4bdd10b Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Sat, 29 Dec 2018 05:00:56 +0000 Subject: [PATCH 11/21] use nano timestamp --- formatter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/formatter.go b/formatter.go index 0849511..2267577 100644 --- a/formatter.go +++ b/formatter.go @@ -199,7 +199,7 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { } if !skipTimestamp { - ee.Timestamp = time.Now().UTC().Format(time.RFC3339) + ee.Timestamp = time.Now().UTC().Format(time.RFC3339Nano) } switch severity { From 933aa6fd9d0956064cd346fd4793c036a987b000 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Sat, 29 Dec 2018 06:31:38 +0000 Subject: [PATCH 12/21] Revert readme change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 80c1e73..072e578 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ package main import ( "github.com/sirupsen/logrus" - stackdriver "github.com/brpx/logrus-stackdriver-formatter" + stackdriver "github.com/TV4/logrus-stackdriver-formatter" ) var log = logrus.New() From 55862029344fd223175ba3ee5b12cc7938d1eca6 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 16:55:35 +0000 Subject: [PATCH 13/21] Fix all lint errors --- formatter.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/formatter.go b/formatter.go index 2267577..8f10527 100644 --- a/formatter.go +++ b/formatter.go @@ -33,32 +33,36 @@ var levelsToSeverity = map[logrus.Level]severity{ logrus.PanicLevel: severityAlert, } +// ServiceContext provides the data about the service we are sending to Google. type ServiceContext struct { Service string `json:"service,omitempty"` Version string `json:"version,omitempty"` } +// ReportLocation is the information about where an error occurred. type ReportLocation struct { FilePath string `json:"file,omitempty"` LineNumber int `json:"line,omitempty"` FunctionName string `json:"function,omitempty"` } +// Context is sent with every message to stackdriver. type Context struct { Data map[string]interface{} `json:"data,omitempty"` ReportLocation *ReportLocation `json:"reportLocation,omitempty"` HTTPRequest map[string]interface{} `json:"httpRequest,omitempty"` } -type HttpRequest struct { +// HTTPRequest defines details of a request and response to append to a log. +type HTTPRequest struct { RequestMethod string `json:"requestMethod,omitempty"` - RequestUrl string `json:"requestUrl,omitempty"` + RequestURL string `json:"requestUrl,omitempty"` RequestSize string `json:"requestSize,omitempty"` Status string `json:"status,omitempty"` ResponseSize string `json:"responseSize,omitempty"` UserAgent string `json:"userAgent,omitempty"` - RemoteIp string `json:"remoteIp,omitempty"` - ServerIp string `json:"serverIp,omitempty"` + RemoteIP string `json:"remoteIp,omitempty"` + ServerIP string `json:"serverIp,omitempty"` Referer string `json:"referer,omitempty"` Latency string `json:"latency,omitempty"` CacheLookup bool `json:"cacheLookup,omitempty"` @@ -68,11 +72,12 @@ type HttpRequest struct { Protocol string `json:"protocol,omitempty"` } +// Entry stores a log entry. type Entry struct { LogName string `json:"logName,omitempty"` Timestamp string `json:"timestamp,omitempty"` Severity severity `json:"severity,omitempty"` - HTTPRequest *HttpRequest `json:"httpRequest,omitempty"` + HTTPRequest *HTTPRequest `json:"httpRequest,omitempty"` Trace string `json:"trace,omitempty"` ServiceContext *ServiceContext `json:"serviceContext,omitempty"` Message string `json:"message,omitempty"` @@ -105,6 +110,7 @@ func WithVersion(v string) Option { } } +// WithProjectID makes sure all entries have your Project information. func WithProjectID(i string) Option { return func(f *Formatter) { f.ProjectID = i @@ -191,7 +197,7 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { } if val, ok := e.Data["httpRequest"]; ok { - ee.HTTPRequest = val.(*HttpRequest) + ee.HTTPRequest = val.(*HTTPRequest) } if val, ok := e.Data["logID"]; ok { From b834d7d9042519685532e9a1ace9b77d9a65696a Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 17:18:47 +0000 Subject: [PATCH 14/21] Seperate out logic --- formatter.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/formatter.go b/formatter.go index 8f10527..620aae0 100644 --- a/formatter.go +++ b/formatter.go @@ -180,8 +180,8 @@ func replaceErrors(source logrus.Fields) logrus.Fields { return data } -// Format formats a logrus entry according to the Stackdriver specifications. -func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { +// ToEntry formats a logrus entry to a stackdriver entry. +func (f *Formatter) ToEntry(e *logrus.Entry) (Entry, error) { severity := levelsToSeverity[e.Level] ee := Entry{ @@ -252,6 +252,16 @@ func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { } } + return ee, nil +} + +// Format formats a logrus entry according to the Stackdriver specifications. +func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { + ee, err := f.ToEntry(e) + if err != nil { + return nil, err + } + b, err := json.Marshal(ee) if err != nil { return nil, err From 99417c5feef3f7f942c3217298abd1a716395aae Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 17:42:22 +0000 Subject: [PATCH 15/21] Make formatter test simpler --- formatter_test.go | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/formatter_test.go b/formatter_test.go index d9728f1..99e7539 100644 --- a/formatter_test.go +++ b/formatter_test.go @@ -4,43 +4,43 @@ import ( "bytes" "encoding/json" "errors" - "reflect" "testing" - "github.com/kr/pretty" - "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" ) func TestFormatter(t *testing.T) { skipTimestamp = true for _, tt := range formatterTests { - var out bytes.Buffer - - logger := logrus.New() - logger.Out = &out - logger.Formatter = NewFormatter( - WithService("test"), - WithVersion("0.1"), - ) - - tt.run(logger) + t.Run(tt.name, func(t *testing.T) { + var out bytes.Buffer - var got map[string]interface{} - json.Unmarshal(out.Bytes(), &got) + logger := logrus.New() + logger.Out = &out + logger.Formatter = NewFormatter( + WithService("test"), + WithVersion("0.1"), + ) - if !reflect.DeepEqual(got, tt.out) { - t.Errorf("unexpected output = %# v; want = %# v", pretty.Formatter(got), pretty.Formatter(tt.out)) - } + tt.run(logger) + got, err := json.Marshal(tt.out) + if err != nil { + t.Error(err) + } + assert.JSONEq(t, out.String(), string(got)) + }) } } var formatterTests = []struct { - run func(*logrus.Logger) - out map[string]interface{} + run func(*logrus.Logger) + out map[string]interface{} + name string }{ { + name: "With Field", run: func(logger *logrus.Logger) { logger.WithField("foo", "bar").Info("my log entry") }, @@ -55,6 +55,7 @@ var formatterTests = []struct { }, }, { + name: "WithField and WithError", run: func(logger *logrus.Logger) { logger. WithField("foo", "bar"). @@ -73,6 +74,7 @@ var formatterTests = []struct { }, }, { + name: "WithField and Error", run: func(logger *logrus.Logger) { logger.WithField("foo", "bar").Error("my log entry") }, @@ -96,6 +98,7 @@ var formatterTests = []struct { }, }, { + name: "WithField, WithError and Error", run: func(logger *logrus.Logger) { logger. WithField("foo", "bar"). @@ -122,12 +125,13 @@ var formatterTests = []struct { }, }, { + name: "WithField, HTTPRequest and Error", run: func(logger *logrus.Logger) { logger. WithFields(logrus.Fields{ "foo": "bar", "httpRequest": map[string]interface{}{ - "method": "GET", + "requestMethod": "GET", }, }). Error("my log entry") From efa0e3118973056c00354c1a26c50e418d7f9a64 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 17:42:46 +0000 Subject: [PATCH 16/21] Error testing --- formatter.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/formatter.go b/formatter.go index 620aae0..1345aca 100644 --- a/formatter.go +++ b/formatter.go @@ -196,8 +196,13 @@ func (f *Formatter) ToEntry(e *logrus.Entry) (Entry, error) { ee.Trace = val.(string) } - if val, ok := e.Data["httpRequest"]; ok { - ee.HTTPRequest = val.(*HTTPRequest) + if val, exists := e.Data["httpRequest"]; exists { + r, ok := val.(*HTTPRequest) + if ok { + ee.HTTPRequest = r + } else { + return ee, fmt.Errorf("httpRequest is not valid") + } } if val, ok := e.Data["logID"]; ok { From b8620bb100615961be1f57bc43c75bb0b4114bb1 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 18:14:09 +0000 Subject: [PATCH 17/21] Fix tests --- formatter.go | 11 +++-------- formatter_test.go | 39 +++++++++++++++++++++++++++------------ go.mod | 3 +++ go.sum | 11 +++++++++++ 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/formatter.go b/formatter.go index 1345aca..0e44bac 100644 --- a/formatter.go +++ b/formatter.go @@ -50,7 +50,7 @@ type ReportLocation struct { type Context struct { Data map[string]interface{} `json:"data,omitempty"` ReportLocation *ReportLocation `json:"reportLocation,omitempty"` - HTTPRequest map[string]interface{} `json:"httpRequest,omitempty"` + HTTPRequest *HTTPRequest `json:"httpRequest,omitempty"` } // HTTPRequest defines details of a request and response to append to a log. @@ -200,8 +200,6 @@ func (f *Formatter) ToEntry(e *logrus.Entry) (Entry, error) { r, ok := val.(*HTTPRequest) if ok { ee.HTTPRequest = r - } else { - return ee, fmt.Errorf("httpRequest is not valid") } } @@ -233,7 +231,7 @@ func (f *Formatter) ToEntry(e *logrus.Entry) (Entry, error) { // As a convenience, when using supplying the httpRequest field, it // gets special care. if reqData, ok := ee.Context.Data["httpRequest"]; ok { - if req, ok := reqData.(map[string]interface{}); ok { + if req, ok := reqData.(*HTTPRequest); ok { ee.Context.HTTPRequest = req delete(ee.Context.Data, "httpRequest") } @@ -262,10 +260,7 @@ func (f *Formatter) ToEntry(e *logrus.Entry) (Entry, error) { // Format formats a logrus entry according to the Stackdriver specifications. func (f *Formatter) Format(e *logrus.Entry) ([]byte, error) { - ee, err := f.ToEntry(e) - if err != nil { - return nil, err - } + ee, _ := f.ToEntry(e) b, err := json.Marshal(ee) if err != nil { diff --git a/formatter_test.go b/formatter_test.go index 99e7539..7462fdf 100644 --- a/formatter_test.go +++ b/formatter_test.go @@ -90,11 +90,16 @@ var formatterTests = []struct { "foo": "bar", }, "reportLocation": map[string]interface{}{ - "filePath": "github.com/TV4/logrus-stackdriver-formatter/formatter_test.go", - "lineNumber": 77.0, - "functionName": "glob..func3", + "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", + "line": 263.0, + "function": "(*Formatter).Format", }, }, + "sourceLocation": map[string]interface{}{ + "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", + "line": 263.0, + "function": "(*Formatter).Format", + }, }, }, { @@ -117,11 +122,16 @@ var formatterTests = []struct { "foo": "bar", }, "reportLocation": map[string]interface{}{ - "filePath": "github.com/TV4/logrus-stackdriver-formatter/formatter_test.go", - "lineNumber": 103.0, - "functionName": "glob..func4", + "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", + "line": 263.0, + "function": "(*Formatter).Format", }, }, + "sourceLocation": map[string]interface{}{ + "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", + "line": 263.0, + "function": "(*Formatter).Format", + }, }, }, { @@ -146,16 +156,21 @@ var formatterTests = []struct { "context": map[string]interface{}{ "data": map[string]interface{}{ "foo": "bar", - }, - "httpRequest": map[string]interface{}{ - "method": "GET", + "httpRequest": map[string]interface{}{ + "requestMethod": "GET", + }, }, "reportLocation": map[string]interface{}{ - "filePath": "github.com/TV4/logrus-stackdriver-formatter/formatter_test.go", - "lineNumber": 133.0, - "functionName": "glob..func5", + "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", + "line": 263.0, + "function": "(*Formatter).Format", }, }, + "sourceLocation": map[string]interface{}{ + "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", + "line": 263.0, + "function": "(*Formatter).Format", + }, }, }, } diff --git a/go.mod b/go.mod index 43d4a61..15fffb4 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,9 @@ module github.com/icco/logrus-stackdriver-formatter require ( + github.com/TV4/logrus-stackdriver-formatter v0.1.0 github.com/go-stack/stack v1.8.0 + github.com/kr/pretty v0.1.0 github.com/sirupsen/logrus v1.2.0 + github.com/stretchr/testify v1.2.2 ) diff --git a/go.sum b/go.sum index f14a3ff..b63c9f3 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,22 @@ +github.com/TV4/logrus-stackdriver-formatter v0.1.0 h1:nFea8RiX7ecTnWPM+9FIqwZYJdcGo58CHMGIVdYzMXg= +github.com/TV4/logrus-stackdriver-formatter v0.1.0/go.mod h1:wwS7hOiBvP6SBD0UXCa767+VhHkaXrfX0MzUojYcN0Q= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= From ad8305911858c82be79fb6fb0ed1cf37d8305974 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 18:22:48 +0000 Subject: [PATCH 18/21] Add current package to stack skip --- formatter.go | 1 + 1 file changed, 1 insertion(+) diff --git a/formatter.go b/formatter.go index 0e44bac..528992e 100644 --- a/formatter.go +++ b/formatter.go @@ -129,6 +129,7 @@ func NewFormatter(options ...Option) *Formatter { fmtr := Formatter{ StackSkip: []string{ "github.com/sirupsen/logrus", + "github.com/icco/logrus-stackdriver-formatter", }, } for _, option := range options { From 0ff02a547fd41f6afe2bbb7ee8e4ab57de73c250 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 18:28:23 +0000 Subject: [PATCH 19/21] Fix stack tests --- formatter_test.go | 36 ++++++++++++++++++------------------ stackskip_test.go | 23 +++++++++++++---------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/formatter_test.go b/formatter_test.go index 7462fdf..b6cea19 100644 --- a/formatter_test.go +++ b/formatter_test.go @@ -90,15 +90,15 @@ var formatterTests = []struct { "foo": "bar", }, "reportLocation": map[string]interface{}{ - "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", - "line": 263.0, - "function": "(*Formatter).Format", + "file": "testing/testing.go", + "line": 827.0, + "function": "tRunner", }, }, "sourceLocation": map[string]interface{}{ - "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", - "line": 263.0, - "function": "(*Formatter).Format", + "file": "testing/testing.go", + "line": 827.0, + "function": "tRunner", }, }, }, @@ -122,15 +122,15 @@ var formatterTests = []struct { "foo": "bar", }, "reportLocation": map[string]interface{}{ - "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", - "line": 263.0, - "function": "(*Formatter).Format", + "file": "testing/testing.go", + "line": 827.0, + "function": "tRunner", }, }, "sourceLocation": map[string]interface{}{ - "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", - "line": 263.0, - "function": "(*Formatter).Format", + "file": "testing/testing.go", + "line": 827.0, + "function": "tRunner", }, }, }, @@ -161,15 +161,15 @@ var formatterTests = []struct { }, }, "reportLocation": map[string]interface{}{ - "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", - "line": 263.0, - "function": "(*Formatter).Format", + "file": "testing/testing.go", + "line": 827.0, + "function": "tRunner", }, }, "sourceLocation": map[string]interface{}{ - "file": "github.com/icco/logrus-stackdriver-formatter/formatter.go", - "line": 263.0, - "function": "(*Formatter).Format", + "file": "testing/testing.go", + "line": 827.0, + "function": "tRunner", }, }, }, diff --git a/stackskip_test.go b/stackskip_test.go index 8e1d837..263dd72 100644 --- a/stackskip_test.go +++ b/stackskip_test.go @@ -3,12 +3,11 @@ package stackdriver import ( "bytes" "encoding/json" - "reflect" "testing" "github.com/TV4/logrus-stackdriver-formatter/test" - "github.com/kr/pretty" "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" ) func TestStackSkip(t *testing.T) { @@ -28,9 +27,6 @@ func TestStackSkip(t *testing.T) { mylog.Error("my log entry") - var got map[string]interface{} - json.Unmarshal(out.Bytes(), &got) - want := map[string]interface{}{ "severity": "ERROR", "message": "my log entry", @@ -40,14 +36,21 @@ func TestStackSkip(t *testing.T) { }, "context": map[string]interface{}{ "reportLocation": map[string]interface{}{ - "filePath": "github.com/TV4/logrus-stackdriver-formatter/stackskip_test.go", - "lineNumber": 29.0, - "functionName": "TestStackSkip", + "file": "testing/testing.go", + "line": 827.0, + "function": "tRunner", }, }, + "sourceLocation": map[string]interface{}{ + "file": "testing/testing.go", + "line": 827.0, + "function": "tRunner", + }, } - if !reflect.DeepEqual(got, want) { - t.Errorf("unexpected output = %# v; want = %# v", pretty.Formatter(got), pretty.Formatter(want)) + got, err := json.Marshal(want) + if err != nil { + t.Error(err) } + assert.JSONEq(t, out.String(), string(got)) } From 63514eb85e8c99940ae9d115eb6440d50c4115fe Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 18:33:14 +0000 Subject: [PATCH 20/21] Move example --- example_test.go => example/example.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename example_test.go => example/example.go (97%) diff --git a/example_test.go b/example/example.go similarity index 97% rename from example_test.go rename to example/example.go index ee57a55..8321da8 100644 --- a/example_test.go +++ b/example/example.go @@ -1,4 +1,4 @@ -package stackdriver_test +package stackdriver_example import ( "os" From e586e52b9dfb098a3bc3f45630990ae4900a7b46 Mon Sep 17 00:00:00 2001 From: Nat Welch Date: Mon, 31 Dec 2018 18:36:26 +0000 Subject: [PATCH 21/21] expand travis config --- .travis.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3abdd22..e59a604 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,16 @@ language: go go: - - 1.9.2 + - "1.9.x" + - "1.10.x" + - "1.11.x" sudo: false -install: - - go get github.com/go-stack/stack - - go get github.com/sirupsen/logrus +before_script: - go get golang.org/x/lint/golint - - go get github.com/kr/pretty script: - golint -set_exit_status - go vet - - go test \ No newline at end of file + - go test -v ./...