Skip to content

Commit

Permalink
feat: Make Environment Integration preserve existing context data (#261)
Browse files Browse the repository at this point in the history
The previous behavior was to always set "device", "os" and "runtime"
contexts overwriting any pre-populated data.

This change allows users to set their own key-value pairs in those
contexts, taking priority over the values set by the SDK.
  • Loading branch information
rhcarvalho authored Jul 20, 2020
1 parent 45b9cad commit 61e144f
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 14 deletions.
50 changes: 36 additions & 14 deletions integrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,27 +70,49 @@ func (ei *environmentIntegration) SetupOnce(client *Client) {
}

func (ei *environmentIntegration) processor(event *Event, hint *EventHint) *Event {
// Initialize maps as necessary.
if event.Contexts == nil {
event.Contexts = make(map[string]interface{})
}

event.Contexts["device"] = map[string]interface{}{
"arch": runtime.GOARCH,
"num_cpu": runtime.NumCPU(),
for _, name := range []string{"device", "os", "runtime"} {
if event.Contexts[name] == nil {
event.Contexts[name] = make(map[string]interface{})
}
}

event.Contexts["os"] = map[string]interface{}{
"name": runtime.GOOS,
// Set contextual information preserving existing data. For each context, if
// the existing value is not of type map[string]interface{}, then no
// additional information is added.
if deviceContext, ok := event.Contexts["device"].(map[string]interface{}); ok {
if _, ok := deviceContext["arch"]; !ok {
deviceContext["arch"] = runtime.GOARCH
}
if _, ok := deviceContext["num_cpu"]; !ok {
deviceContext["num_cpu"] = runtime.NumCPU()
}
}

event.Contexts["runtime"] = map[string]interface{}{
"name": "go",
"version": runtime.Version(),
"go_numroutines": runtime.NumGoroutine(),
"go_maxprocs": runtime.GOMAXPROCS(0),
"go_numcgocalls": runtime.NumCgoCall(),
if osContext, ok := event.Contexts["os"].(map[string]interface{}); ok {
if _, ok := osContext["name"]; !ok {
osContext["name"] = runtime.GOOS
}
}
if runtimeContext, ok := event.Contexts["runtime"].(map[string]interface{}); ok {
if _, ok := runtimeContext["name"]; !ok {
runtimeContext["name"] = "go"
}
if _, ok := runtimeContext["version"]; !ok {
runtimeContext["version"] = runtime.Version()
}
if _, ok := runtimeContext["go_numroutines"]; !ok {
runtimeContext["go_numroutines"] = runtime.NumGoroutine()
}
if _, ok := runtimeContext["go_maxprocs"]; !ok {
runtimeContext["go_maxprocs"] = runtime.GOMAXPROCS(0)
}
if _, ok := runtimeContext["go_numcgocalls"]; !ok {
runtimeContext["go_numcgocalls"] = runtime.NumCgoCall()
}
}

return event
}

Expand Down
46 changes: 46 additions & 0 deletions integrations_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sentry

import (
"encoding/json"
"path/filepath"
"regexp"
"runtime/debug"
Expand Down Expand Up @@ -342,3 +343,48 @@ func TestExtractModules(t *testing.T) {
})
}
}

func TestEnvironmentIntegrationDoesNotOverrideExistingContexts(t *testing.T) {
transport := &TransportMock{}
client, err := NewClient(ClientOptions{
Transport: transport,
Integrations: func([]Integration) []Integration {
return []Integration{new(environmentIntegration)}
},
})
if err != nil {
t.Fatal(err)
}
scope := NewScope()

scope.contexts["device"] = map[string]interface{}{
"foo": "bar",
}
scope.contexts["os"] = map[string]interface{}{
"name": "test",
}
scope.contexts["custom"] = "value"
hub := NewHub(client, scope)
hub.CaptureMessage("test event")

events := transport.Events()
if len(events) != 1 {
b, err := json.MarshalIndent(events, "", " ")
if err != nil {
t.Fatal(err)
}
t.Fatalf("events = %s\ngot %d events, want 1", b, len(events))
}

contexts := events[0].Contexts

if contexts["device"].(map[string]interface{})["foo"] != "bar" {
t.Errorf(`contexts["device"] = %#v, want contexts["device"]["foo"] == "bar"`, contexts["device"])
}
if contexts["os"].(map[string]interface{})["name"] != "test" {
t.Errorf(`contexts["os"] = %#v, want contexts["os"]["name"] == "test"`, contexts["os"])
}
if contexts["custom"] != "value" {
t.Errorf(`contexts["custom"] = %#v, want "value"`, contexts["custom"])
}
}

0 comments on commit 61e144f

Please sign in to comment.