Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Improve speed and reduce allocations when adding fields #402

Closed
wants to merge 10 commits into from
23 changes: 21 additions & 2 deletions beeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"github.com/honeycombio/beeline-go/sample"
"github.com/honeycombio/beeline-go/trace"
libhoney "github.com/honeycombio/libhoney-go"

lru "github.com/hashicorp/golang-lru/v2"
)

const (
Expand Down Expand Up @@ -100,6 +102,11 @@ type Config struct {
PprofTagging bool
}

var (
// fieldNameCache is a LRU cache of namespaced keys to avoid allocating new strings
fieldNameCache *lru.Cache[string, string]
)

func IsClassicKey(config Config) bool {
// classic key has 32 characters
return len(config.WriteKey) == 32
Expand Down Expand Up @@ -244,6 +251,7 @@ func Init(config Config) {
propagation.GlobalConfig.PropagateDataset = false
}
trace.GlobalConfig.PprofTagging = config.PprofTagging
fieldNameCache, _ = lru.New[string, string](1000)
return
}

Expand Down Expand Up @@ -280,7 +288,7 @@ func AddField(ctx context.Context, key string, val interface{}) {
span := trace.GetSpanFromContext(ctx)
if span != nil {
if val != nil {
namespacedKey := "app." + key // Avoid excess parsing/allocation work
namespacedKey := getNamespacedKey(key)
if valErr, ok := val.(error); ok {
// treat errors specially because it's a pain to have to
// remember to stringify them
Expand All @@ -300,7 +308,7 @@ func AddField(ctx context.Context, key string, val interface{}) {
// eg user IDs, globally relevant feature flags, errors, etc. Fields added here
// are prefixed with `app.`
func AddFieldToTrace(ctx context.Context, key string, val interface{}) {
namespacedKey := "app." + key // Avoid excess parsing/allocation work
namespacedKey := getNamespacedKey(key)
tr := trace.GetTraceFromContext(ctx)
if tr != nil {
tr.AddField(namespacedKey, val)
Expand Down Expand Up @@ -354,3 +362,14 @@ func readResponses(responses chan transmission.Response) {
}
}
}

// getNamespacedKey returns a namespaced key for the given key. It will return
// the cached value if it exists, otherwise it will create a new one and cache
func getNamespacedKey(key string) string {
if val, ok := fieldNameCache.Get(key); ok {
return val
}
val := "app." + key
fieldNameCache.Add(key, val)
return val
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/gobuffalo/pop/v6 v6.1.1
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/honeycombio/libhoney-go v1.20.0
github.com/jmoiron/sqlx v1.3.5
github.com/julienschmidt/httprouter v1.3.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/honeycombio/libhoney-go v1.20.0 h1:PL54R0P9vxIyb28H3twbLb+DCqQlJdMQM55VZg1abKA=
github.com/honeycombio/libhoney-go v1.20.0/go.mod h1:RIaurCpfg5NDWSEV8t3QLcda9dUAiVNyWeHRAaSpN90=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
Expand Down