Skip to content

Commit

Permalink
v1.5.3
Browse files Browse the repository at this point in the history
Release v1.5.3
  • Loading branch information
kinbiko authored Jul 11, 2019
2 parents ab96e50 + fccb434 commit 3b0dbb7
Show file tree
Hide file tree
Showing 16 changed files with 162 additions and 25 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ jobs:
script: make ci
go: "1.7"
- script: make ci
env: GO_VERSION=1.8
go: "1.8"
- script: make ci
env: GO_VERSION=1.9
go: "1.9"
- script: make ci
go: "1.10"
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 1.5.3 (2019-07-11)

This release adds runtime version data to the report and session payloads, which will show up under the Device tab in the Bugsnag dashboard.

### Enhancements

* Ignore Gin unit tests when running against the latest version of Gin on Go versions below 1.10 as Gin has dropped support for these versions.
[#121](https://github.com/bugsnag/bugsnag-go/pull/121)
* Introduce runtime version data to the report and session payloads. Additionally adds the OS name to reports.
[#122](https://github.com/bugsnag/bugsnag-go/pull/122)

## 1.5.2 (2019-05-20)

This release adds `"access_token"` to the default list of keys to filter and introduces filtering of URL query parameters under the request tab.
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ updatedeps:
test: alldeps
@#TODO: 2018-09-20 Not testing the 'errors' package as it relies on some very runtime-specific implementation details.
@# The testing of 'errors' needs to be revisited
@# Additionally skipping Gin if the Go version is 1.7, as the latest version of Gin has dropped support.
@if [ "$(GO_VERSION)" = "1.7" ]; then \
@# Additionally skipping Gin if the Go version is lower than 1.9, as the latest version of Gin has dropped support for these versions.
@if [ "$(GO_VERSION)" = "1.7" ] || [ "$(GO_VERSION)" = "1.8" ] || [ "$(GO_VERSION)" = "1.9" ]; then \
go test . ./martini ./negroni ./sessions ./headers; \
else \
go test . ./gin ./martini ./negroni ./sessions ./headers; \
Expand Down
2 changes: 1 addition & 1 deletion bugsnag.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
)

// VERSION defines the version of this Bugsnag notifier
const VERSION = "1.5.2"
const VERSION = "1.5.3"

var panicHandlerOnce sync.Once
var sessionTrackerOnce sync.Once
Expand Down
50 changes: 50 additions & 0 deletions device/runtimeversions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package device

import (
"runtime"
)

// Cached runtime versions that can be updated globally by framework
// integrations through AddVersion.
var versions *RuntimeVersions

// RuntimeVersions define the various versions of Go and any framework that may
// be in use.
// As a user of the notifier you're unlikely to need to modify this struct.
// As such, the authors reserve the right to introduce breaking changes to the
// properties in this struct. In particular the framework versions are liable
// to change in new versions of the notifier in minor/patch versions.
type RuntimeVersions struct {
Go string `json:"go"`

Gin string `json:"gin,omitempty"`
Martini string `json:"martini,omitempty"`
Negroni string `json:"negroni,omitempty"`
Revel string `json:"revel,omitempty"`
}

// GetRuntimeVersions retrieves the recorded runtime versions in a goroutine-safe manner.
func GetRuntimeVersions() *RuntimeVersions {
if versions == nil {
versions = &RuntimeVersions{Go: runtime.Version()}
}
return versions
}

// AddVersion permits a framework to register its version, assuming it's one of
// the officially supported frameworks.
func AddVersion(framework, version string) {
if versions == nil {
versions = &RuntimeVersions{Go: runtime.Version()}
}
switch framework {
case "Martini":
versions.Martini = version
case "Gin":
versions.Gin = version
case "Negroni":
versions.Negroni = version
case "Revel":
versions.Revel = version
}
}
43 changes: 43 additions & 0 deletions device/runtimeversions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package device

import (
"runtime"
"testing"
)

func TestPristineRuntimeVersions(t *testing.T) {
versions = nil // reset global variable
rv := GetRuntimeVersions()
for _, tc := range []struct{ name, got, exp string }{
{name: "Go", got: rv.Go, exp: runtime.Version()},
{name: "Gin", got: rv.Gin, exp: ""},
{name: "Martini", got: rv.Martini, exp: ""},
{name: "Negroni", got: rv.Negroni, exp: ""},
{name: "Revel", got: rv.Revel, exp: ""},
} {
if tc.got != tc.exp {
t.Errorf("expected pristine '%s' runtime version to be '%s' but was '%s'", tc.name, tc.exp, tc.got)
}
}
}

func TestModifiedRuntimeVersions(t *testing.T) {
versions = nil // reset global variable
rv := GetRuntimeVersions()
AddVersion("Gin", "1.2.1")
AddVersion("Martini", "1.0.0")
AddVersion("Negroni", "1.0.2")
AddVersion("Revel", "0.20.1")
for _, tc := range []struct{ name, got, exp string }{
{name: "Go", got: rv.Go, exp: runtime.Version()},
{name: "Gin", got: rv.Gin, exp: "1.2.1"},
{name: "Martini", got: rv.Martini, exp: "1.0.0"},
{name: "Negroni", got: rv.Negroni, exp: "1.0.2"},
{name: "Revel", got: rv.Revel, exp: "0.20.1"},
} {
if tc.got != tc.exp {
t.Errorf("expected modified '%s' runtime version to be '%s' but was '%s'", tc.name, tc.exp, tc.got)
}
}

}
2 changes: 1 addition & 1 deletion examples/revelapp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The key files for integrating Bugsnag are:

## Run the example

1. Change the API key in `conf.app` to a project you've created in [Bugsnag](https://app.bugsnag.com).
1. Change the API key in `app.conf` to a project you've created in [Bugsnag](https://app.bugsnag.com).
1. Inside `bugsnag-go/examples/revelapp` do:
```bash
revel run
Expand Down
2 changes: 2 additions & 0 deletions gin/bugsnaggin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bugsnaggin

import (
"github.com/bugsnag/bugsnag-go"
"github.com/bugsnag/bugsnag-go/device"
"github.com/gin-gonic/gin"
)

Expand All @@ -20,6 +21,7 @@ func AutoNotify(rawData ...interface{}) gin.HandlerFunc {
}
}

device.AddVersion(FrameworkName, gin.Version)
state := bugsnag.HandledState{
SeverityReason: bugsnag.SeverityReasonUnhandledMiddlewareError,
OriginalSeverity: bugsnag.SeverityError,
Expand Down
2 changes: 2 additions & 0 deletions martini/bugsnagmiddleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"net/http"

"github.com/bugsnag/bugsnag-go"
"github.com/bugsnag/bugsnag-go/device"
"github.com/go-martini/martini"
)

Expand All @@ -47,6 +48,7 @@ const FrameworkName string = "Martini"
func AutoNotify(rawData ...interface{}) martini.Handler {
updateGlobalConfig(rawData...)

device.AddVersion(FrameworkName, "v1.0") // The latest martini release from 2014
state := bugsnag.HandledState{
SeverityReason: bugsnag.SeverityReasonUnhandledMiddlewareError,
OriginalSeverity: bugsnag.SeverityError,
Expand Down
2 changes: 2 additions & 0 deletions negroni/bugsnagnegroni.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"net/http"

"github.com/bugsnag/bugsnag-go"
"github.com/bugsnag/bugsnag-go/device"
"github.com/urfave/negroni"
)

Expand All @@ -17,6 +18,7 @@ type handler struct {
// AutoNotify sends any panics to bugsnag, and then re-raises them.
func AutoNotify(rawData ...interface{}) negroni.Handler {
updateGlobalConfig(rawData...)
device.AddVersion(FrameworkName, "unknown") // Negroni exposes no version prop.
state := bugsnag.HandledState{
SeverityReason: bugsnag.SeverityReasonUnhandledMiddlewareError,
OriginalSeverity: bugsnag.SeverityError,
Expand Down
8 changes: 7 additions & 1 deletion payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"encoding/json"
"fmt"
"net/http"
"runtime"
"sync"
"time"

"github.com/bugsnag/bugsnag-go/device"
"github.com/bugsnag/bugsnag-go/headers"
"github.com/bugsnag/bugsnag-go/sessions"
)
Expand Down Expand Up @@ -69,7 +71,11 @@ func (p *payload) MarshalJSON() ([]byte, error) {
Version: p.AppVersion,
},
Context: p.Context,
Device: &deviceJSON{Hostname: p.Hostname},
Device: &deviceJSON{
Hostname: p.Hostname,
OsName: runtime.GOOS,
RuntimeVersions: device.GetRuntimeVersions(),
},
Request: p.Request,
Exceptions: []exceptionJSON{
exceptionJSON{
Expand Down
21 changes: 13 additions & 8 deletions payload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,40 @@ package bugsnag

import (
"context"
"fmt"
"runtime"
"strings"
"testing"

"github.com/bugsnag/bugsnag-go/errors"
"github.com/bugsnag/bugsnag-go/sessions"
)

const expSmall = `{"apiKey":"","events":[{"app":{"releaseStage":""},"device":{},"exceptions":[{"errorClass":"","message":"","stacktrace":null}],"metaData":{},"payloadVersion":"4","severity":"","unhandled":false}],"notifier":{"name":"Bugsnag Go","url":"https://github.com/bugsnag/bugsnag-go","version":"1.5.2"}}`
const expSmall = `{"apiKey":"","events":[{"app":{"releaseStage":""},"device":{"osName":"%s","runtimeVersions":{"go":"%s"}},"exceptions":[{"errorClass":"","message":"","stacktrace":null}],"metaData":{},"payloadVersion":"4","severity":"","unhandled":false}],"notifier":{"name":"Bugsnag Go","url":"https://github.com/bugsnag/bugsnag-go","version":"1.5.3"}}`

// The large payload has a timestamp in it which makes it awkward to assert against.
// Instead, assert that the timestamp property exist, along with the rest of the expected payload
const expLargePre = `{"apiKey":"166f5ad3590596f9aa8d601ea89af845","events":[{"app":{"releaseStage":"mega-production","type":"gin","version":"1.5.2"},"context":"/api/v2/albums","device":{"hostname":"super.duper.site"},"exceptions":[{"errorClass":"error class","message":"error message goes here","stacktrace":[{"method":"doA","file":"a.go","lineNumber":65},{"method":"fetchB","file":"b.go","lineNumber":99,"inProject":true},{"method":"incrementI","file":"i.go","lineNumber":651}]}],"groupingHash":"custom grouping hash","metaData":{"custom tab":{"my key":"my value"}},"payloadVersion":"4","session":{"startedAt":"`
const expLargePost = `,"severity":"info","severityReason":{"type":"unhandledError"},"unhandled":true,"user":{"id":"1234baerg134","name":"Kool Kidz on da bus","email":"typo@busgang.com"}}],"notifier":{"name":"Bugsnag Go","url":"https://github.com/bugsnag/bugsnag-go","version":"1.5.2"}}`
const expLargePre = `{"apiKey":"166f5ad3590596f9aa8d601ea89af845","events":[{"app":{"releaseStage":"mega-production","type":"gin","version":"1.5.3"},"context":"/api/v2/albums","device":{"hostname":"super.duper.site","osName":"%s","runtimeVersions":{"go":"%s"}},"exceptions":[{"errorClass":"error class","message":"error message goes here","stacktrace":[{"method":"doA","file":"a.go","lineNumber":65},{"method":"fetchB","file":"b.go","lineNumber":99,"inProject":true},{"method":"incrementI","file":"i.go","lineNumber":651}]}],"groupingHash":"custom grouping hash","metaData":{"custom tab":{"my key":"my value"}},"payloadVersion":"4","session":{"startedAt":"`
const expLargePost = `,"severity":"info","severityReason":{"type":"unhandledError"},"unhandled":true,"user":{"id":"1234baerg134","name":"Kool Kidz on da bus","email":"typo@busgang.com"}}],"notifier":{"name":"Bugsnag Go","url":"https://github.com/bugsnag/bugsnag-go","version":"1.5.3"}}`

func TestMarshalEmptyPayload(t *testing.T) {
sessionTracker = sessions.NewSessionTracker(&sessionTrackingConfig)
p := payload{&Event{Ctx: context.Background()}, &Configuration{}}
bytes, _ := p.MarshalJSON()
if got := string(bytes[:]); got != expSmall {
t.Errorf("Payload different to what was expected. \nGot: %s\nExp: %s", got, expSmall)
exp := fmt.Sprintf(expSmall, runtime.GOOS, runtime.Version())
if got := string(bytes[:]); got != exp {
t.Errorf("Payload different to what was expected. \nGot: %s\nExp: %s", got, exp)
}
}

func TestMarshalLargePayload(t *testing.T) {
payload := makeLargePayload()
bytes, _ := payload.MarshalJSON()
got := string(bytes[:])
if !strings.Contains(got, expLargePre) {
t.Errorf("Expected large payload to contain\n'%s'\n but was\n'%s'", expLargePre, got)
expPre := fmt.Sprintf(expLargePre, runtime.GOOS, runtime.Version())
if !strings.Contains(got, expPre) {
t.Errorf("Expected large payload to contain\n'%s'\n but was\n'%s'", expPre, got)

}
if !strings.Contains(got, expLargePost) {
t.Errorf("Expected large payload to contain\n'%s'\n but was\n'%s'", expLargePost, got)
Expand Down Expand Up @@ -80,7 +85,7 @@ func makeLargePayload() *payload {
APIKey: testAPIKey,
ReleaseStage: "mega-production",
AppType: "gin",
AppVersion: "1.5.2",
AppVersion: "1.5.3",
Hostname: "super.duper.site",
}
return &payload{&event, &config}
Expand Down
4 changes: 4 additions & 0 deletions report.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bugsnag

import (
"github.com/bugsnag/bugsnag-go/device"
"github.com/bugsnag/bugsnag-go/sessions"
uuid "github.com/gofrs/uuid"
)
Expand Down Expand Up @@ -57,6 +58,9 @@ type severityReasonJSON struct {

type deviceJSON struct {
Hostname string `json:"hostname,omitempty"`
OsName string `json:"osName,omitempty"`

RuntimeVersions *device.RuntimeVersions `json:"runtimeVersions,omitempty"`
}

// RequestJSON is the request information that populates the Request tab in the dashboard.
Expand Down
2 changes: 2 additions & 0 deletions revel/bugsnagrevel.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"

"github.com/bugsnag/bugsnag-go"
"github.com/bugsnag/bugsnag-go/device"
"github.com/revel/revel"
)

Expand Down Expand Up @@ -109,6 +110,7 @@ func init() {
Logger: new(bugsnagRevelLogger),
Synchronous: c.BoolDefault("bugsnag.synchronous", config.Synchronous),
})
device.AddVersion(FrameworkName, revel.Version)
}, order)
}

Expand Down
25 changes: 15 additions & 10 deletions sessions/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,24 @@ func TestStartSession(t *testing.T) {
tt := []struct {
prop string
exp interface{}
got interface{}
}{
{got: getString(json, "notifier.name"), prop: "notifier.name", exp: "Bugsnag Go"},
{got: getString(json, "notifier.url"), prop: "notifier.url", exp: "https://github.com/bugsnag/bugsnag-go"},
{got: getString(json, "notifier.version"), prop: "notifier.version", exp: bugsnag.VERSION},
{got: getString(json, "app.releaseStage"), prop: "app.releaseStage", exp: "production"},
{got: getString(json, "app.version"), prop: "app.version", exp: ""},
{got: getString(json, "device.osName"), prop: "device.osName", exp: runtime.GOOS},
{got: getString(json, "device.hostname"), prop: "device.hostname", exp: hostname},
{prop: "notifier.name", exp: "Bugsnag Go"},
{prop: "notifier.url", exp: "https://github.com/bugsnag/bugsnag-go"},
{prop: "notifier.version", exp: bugsnag.VERSION},
{prop: "app.releaseStage", exp: "production"},
{prop: "app.version", exp: ""},
{prop: "device.osName", exp: runtime.GOOS},
{prop: "device.hostname", exp: hostname},
{prop: "device.runtimeVersions.go", exp: runtime.Version()},
{prop: "device.runtimeVersions.gin", exp: ""},
{prop: "device.runtimeVersions.martini", exp: ""},
{prop: "device.runtimeVersions.negroni", exp: ""},
{prop: "device.runtimeVersions.revel", exp: ""},
}
for _, tc := range tt {
if tc.got != tc.exp {
t.Errorf("Expected '%s' to be '%s' but was %s", tc.prop, tc.exp, tc.got)
got := getString(json, tc.prop)
if got != tc.exp {
t.Errorf("Expected '%s' to be '%s' but was '%s'", tc.prop, tc.exp, got)
}
}
sessionCounts := getIndex(json, "sessionCounts", 0)
Expand Down
7 changes: 5 additions & 2 deletions sessions/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ type appPayload struct {
type devicePayload struct {
OsName string `json:"osName,omitempty"`
Hostname string `json:"hostname,omitempty"`

RuntimeVersions *device.RuntimeVersions `json:"runtimeVersions"`
}

// sessionCountsPayload defines the .sessionCounts subobject of the payload
Expand Down Expand Up @@ -64,8 +66,9 @@ func makeSessionPayload(sessions []*Session, config *SessionTrackingConfiguratio
ReleaseStage: releaseStage,
},
Device: &devicePayload{
OsName: runtime.GOOS,
Hostname: hostname,
OsName: runtime.GOOS,
Hostname: hostname,
RuntimeVersions: device.GetRuntimeVersions(),
},
SessionCounts: []sessionCountsPayload{
{
Expand Down

0 comments on commit 3b0dbb7

Please sign in to comment.