Skip to content

Commit

Permalink
feat(attributes): add default attributes (#24)
Browse files Browse the repository at this point in the history
Add fields:
    

application.session: an uuid that will be the same for all reports in
single application session.
    
    guid: unique machine identifier 

    uname.sysname - name of the operating system

backtrace.agent - name of the go library (this is a constant value set
to backtrace-go)

    backtrace.version - version of the go library 

    uname.version - version of the operating system

    hostname - current hostname

    cpu.arch - CPU arch

    cpu.brand - CPU brand

    application - current application name 

    process.id  - current process id
  • Loading branch information
MateuszKepczynskiSauce authored Nov 28, 2024
1 parent 0f1ae2e commit 7771f60
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 4 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/backtrace-labs/backtrace-go
go 1.22

require (
github.com/google/uuid v1.6.0
github.com/stretchr/testify v1.9.0
golang.org/x/sys v0.25.0
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
Expand Down
119 changes: 115 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,43 @@ import (
"encoding/json"
"fmt"
"io"
"log"
mathrand "math/rand"
"net/http"
"net/url"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"time"

"github.com/google/uuid"
)

const (
VersionMajor = 1
VersionMinor = 0
VersionPatch = 0
)

const VersionMajor = 0
const VersionMinor = 0
const VersionPatch = 0
var (
Version = fmt.Sprintf("%d.%d.%d", VersionMajor, VersionMinor, VersionPatch)

windowsGUIDCommand = []string{"reg", "query", "\"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Cryptography\"", "/v", "MachineGuid"}
linuxGUIDCommand = []string{"sh", "-c", "( cat /var/lib/dbus/machine-id /etc/machine-id 2> /dev/null || hostname ) | head -n 1 || :"}
freebsdGUIDCommand = []string{"sh", "-c", "kenv -q smbios.system.uuid || sysctl -n kern.hostuuid"}
darwinGUIDCommand = []string{"sh", "-c", "ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk -F'= \"' '{print $2}' | tr -d '\"'"}

var Version = fmt.Sprintf("%d.%d.%d", VersionMajor, VersionMinor, VersionPatch)
windowsCPUCommand = []string{"wmic", "CPU", "get", "NAME"}
linuxCPUCommand = []string{"sh", "-c", "lscpu | grep \"Model name\" | awk -F':' '{print $2}' | sed 's/^[[:space:]]*//'"}
darwinCPUCommand = []string{"sh", "-c", "sysctl -n machdep.cpu.brand_string"}
freebsdCPUCommand = []string{"sh", "-c", "sysctl -n hw.model"}

linuxOSVersionCommand = []string{"sh", "-c", "cat /etc/os-release | grep VERSION= | awk -F'=\"' '{print $2}' | tr -d '\"'"}
darwinOSVersionCommand = []string{"sh", "-c", "sw_vers | grep ProductVersion | awk -F':' '{print $2}' | tr -d '\t'"}
freebsdOSVersionCommand = []string{"sh", "-c", "cat /etc/os-release | grep VERSION= | awk -F'=\"' '{print $2}' | tr -d '\"'"}
)

type OptionsStruct struct {
Endpoint string
Expand Down Expand Up @@ -72,9 +95,97 @@ func init() {
randSource := mathrand.NewSource(seed)
rng = mathrand.New(randSource)

setDefaultAttributes()

go sendWorkerMain()
}

func setDefaultAttributes() {
if Options.Attributes == nil {
Options.Attributes = make(map[string]interface{})
}

hostName, _ := os.Hostname()
Options.Attributes["backtrace.version"] = Version
Options.Attributes["backtrace.agent"] = "backtrace-go"
Options.Attributes["hostname"] = hostName
Options.Attributes["uname.sysname"] = runtime.GOOS
Options.Attributes["cpu.arch"] = runtime.GOARCH
Options.Attributes["process.id"] = os.Getpid()
Options.Attributes["application.session"] = uuid.New()
Options.Attributes["application"] = filepath.Base(os.Args[0])

guiCommand := []string{}
cpuCommand := []string{}
osCommand := []string{}
switch runtime.GOOS {
case "windows":
guiCommand = windowsGUIDCommand
cpuCommand = windowsCPUCommand
case "linux":
guiCommand = linuxGUIDCommand
cpuCommand = linuxCPUCommand
osCommand = linuxOSVersionCommand
case "darwin":
guiCommand = darwinGUIDCommand
cpuCommand = darwinCPUCommand
osCommand = darwinOSVersionCommand
case "freebsd":
guiCommand = freebsdGUIDCommand
cpuCommand = freebsdCPUCommand
osCommand = freebsdOSVersionCommand
}

if len(guiCommand) > 0 {
if output := execCommand(guiCommand); output != "" {
if runtime.GOOS == "windows" {
// windows gives:
// HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography
// MachineGuid REG_SZ {XXXX-XXXX-XXXX-XXXX-XXXX}
if splitOutput := strings.Split(output, "{"); len(splitOutput) > 1 {
output = strings.TrimSuffix(splitOutput[1], "}")
}
}

Options.Attributes["guid"] = output
}
}

if len(cpuCommand) > 0 {
if output := execCommand(cpuCommand); output != "" {
if runtime.GOOS == "windows" {
// windows gives:
//NAME
//Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
if splitOutput := strings.Split(output, "\n"); len(splitOutput) > 1 {
output = splitOutput[1]
}
}

Options.Attributes["cpu.brand"] = output
}
}

if len(osCommand) > 0 {
if output := execCommand(osCommand); output != "" {
Options.Attributes["uname.version"] = output
}
}
}

// first value in array is command to exec, rest are arguments.
// e.g. []string{"sh", "-c", "sysctl -n foo_bar | grep foo_bar | tr -d "foo_var" "}
func execCommand(commands []string) string {
out, err := exec.Command(commands[0], commands[1:]...).Output()
if err != nil {
if Options.DebugBacktrace {
log.Println(err)
}
}

return string(out)
}

func Report(object interface{}, extraAttributes map[string]interface{}) {
if extraAttributes == nil {
extraAttributes = map[string]interface{}{}
Expand Down
7 changes: 7 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,11 @@ func causeErrorReport() {
go doSomething(make(chan int))
Report(errors.New("it broke"), nil)
finishSendingReports(false)

for _, v := range []string{"backtrace.version", "backtrace.agent", "hostname", "uname.sysname", "cpu.arch", "process.id", "application.session", "application"} {
if _, ok := Options.Attributes[v]; !ok {
panic(v + " - attribute not set")
}
}

}

0 comments on commit 7771f60

Please sign in to comment.