From 343858d3ee27cc2d1c7672d64e537925ce349aaf Mon Sep 17 00:00:00 2001 From: Braden Bassingthwaite Date: Thu, 1 Feb 2024 08:38:39 -0600 Subject: [PATCH] Go HTTP Filter: Expose envoy concurrency and request worker_id in public API (#32107) Adds new functions to the Go SDK EnvoyConcurrency() and StreamInfo.WorkerID(). This information will allow Go HTTP plugins to optimize their performance in certain use cases. Follow up from #31987 cc @doujiang24 Commit Message: Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Signed-off-by: Braden Bassingthwaite --- contrib/golang/common/go/api/filter.go | 3 ++- .../filters/http/source/go/pkg/http/filter.go | 4 ++++ .../filters/http/source/go/pkg/http/shim.go | 19 +++++++++++++++++++ .../network/source/go/pkg/network/filter.go | 4 ++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/contrib/golang/common/go/api/filter.go b/contrib/golang/common/go/api/filter.go index 20e913cbb8ac..458193a77f76 100644 --- a/contrib/golang/common/go/api/filter.go +++ b/contrib/golang/common/go/api/filter.go @@ -139,7 +139,8 @@ type StreamInfo interface { FilterState() FilterState // VirtualClusterName returns the name of the virtual cluster which got matched VirtualClusterName() (string, bool) - + // WorkerID returns the ID of the Envoy worker thread + WorkerID() uint32 // Some fields in stream info can be fetched via GetProperty // For example, startTime() is equal to GetProperty("request.time") } diff --git a/contrib/golang/filters/http/source/go/pkg/http/filter.go b/contrib/golang/filters/http/source/go/pkg/http/filter.go index b90629b2330c..029ebf612198 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/filter.go +++ b/contrib/golang/filters/http/source/go/pkg/http/filter.go @@ -281,6 +281,10 @@ func (s *streamInfo) VirtualClusterName() (string, bool) { return cAPI.HttpGetStringValue(unsafe.Pointer(s.request), ValueVirtualClusterName) } +func (s *streamInfo) WorkerID() uint32 { + return uint32(s.request.req.worker_id) +} + type filterState struct { request *httpRequest } diff --git a/contrib/golang/filters/http/source/go/pkg/http/shim.go b/contrib/golang/filters/http/source/go/pkg/http/shim.go index 44767a4c1a79..b02284cdc1ee 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/shim.go +++ b/contrib/golang/filters/http/source/go/pkg/http/shim.go @@ -45,6 +45,23 @@ var ErrDupRequestKey = errors.New("dup request key") var Requests = &requestMap{} +var ( + initialized = false + envoyConcurrency uint32 +) + +// EnvoyConcurrency returns the concurrency Envoy was set to run at. This can be used to optimize HTTP filters that need +// memory per worker thread to avoid locks. +// +// Note: Do not use inside of an `init()` function, the value will not be populated yet. Use within the filters +// `StreamFilterConfigFactory` or `StreamFilterConfigParser` +func EnvoyConcurrency() uint32 { + if !initialized { + panic("concurrency has not yet been initialized, do not access within an init()") + } + return envoyConcurrency +} + type requestMap struct { initOnce sync.Once requests []map[*C.httpRequest]*httpRequest @@ -52,6 +69,8 @@ type requestMap struct { func (f *requestMap) initialize(concurrency uint32) { f.initOnce.Do(func() { + initialized = true + envoyConcurrency = concurrency f.requests = make([]map[*C.httpRequest]*httpRequest, concurrency) for i := uint32(0); i < concurrency; i++ { f.requests[i] = map[*C.httpRequest]*httpRequest{} diff --git a/contrib/golang/filters/network/source/go/pkg/network/filter.go b/contrib/golang/filters/network/source/go/pkg/network/filter.go index 6a113fd5c662..22d1cf9aa63f 100644 --- a/contrib/golang/filters/network/source/go/pkg/network/filter.go +++ b/contrib/golang/filters/network/source/go/pkg/network/filter.go @@ -113,6 +113,10 @@ func (n *connectionCallback) VirtualClusterName() (string, bool) { panic("implement me") } +func (n *connectionCallback) WorkerID() uint32 { + panic("implement me") +} + type filterState struct { wrapper unsafe.Pointer setFunc func(envoyFilter unsafe.Pointer, key string, value string, stateType api.StateType, lifeSpan api.LifeSpan, streamSharing api.StreamSharing)