Skip to content

Commit 9eb6658

Browse files
middleware: Use map for external dependencies
1 parent 8bcf34c commit 9eb6658

File tree

2 files changed

+24
-30
lines changed

2 files changed

+24
-30
lines changed

http/middleware/external_dependency.go

+16-30
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ package middleware
55
import (
66
"context"
77
"fmt"
8+
"maps"
89
"net/http"
10+
"slices"
911
"strconv"
1012
"strings"
1113
"sync"
@@ -14,9 +16,6 @@ import (
1416
"github.com/pace/bricks/maintenance/log"
1517
)
1618

17-
// depFormat is the format of a single dependency report
18-
const depFormat = "%s:%d"
19-
2019
// ExternalDependencyHeaderName name of the HTTP header that is used for reporting
2120
const ExternalDependencyHeaderName = "External-Dependencies"
2221

@@ -85,30 +84,29 @@ func ExternalDependencyContextFromContext(ctx context.Context) *ExternalDependen
8584
// during the request livecycle
8685
type ExternalDependencyContext struct {
8786
mu sync.RWMutex
88-
dependencies []externalDependency
87+
dependencies map[string]time.Duration
8988
}
9089

9190
func (c *ExternalDependencyContext) AddDependency(name string, duration time.Duration) {
9291
c.mu.Lock()
93-
c.dependencies = append(c.dependencies, externalDependency{
94-
Name: name,
95-
Duration: duration,
96-
})
97-
c.mu.Unlock()
92+
defer c.mu.Unlock()
93+
94+
if c.dependencies == nil {
95+
c.dependencies = make(map[string]time.Duration)
96+
}
97+
98+
c.dependencies[name] += duration
9899
}
99100

100-
// String formats all external dependencies
101+
// String formats all external dependencies. The format is "name:duration[,name:duration]..." and sorted by name.
101102
func (c *ExternalDependencyContext) String() string {
102103
var b strings.Builder
103-
sep := len(c.dependencies) - 1
104-
for _, dep := range c.dependencies {
105-
b.WriteString(dep.String())
106-
if sep > 0 {
107-
b.WriteByte(',')
108-
sep--
109-
}
104+
105+
for _, key := range slices.Sorted(maps.Keys(c.dependencies)) {
106+
b.WriteString(fmt.Sprintf("%s:%d,", key, c.dependencies[key].Milliseconds()))
110107
}
111-
return b.String()
108+
109+
return strings.TrimRight(b.String(), ",")
112110
}
113111

114112
// Parse a external dependency value
@@ -127,15 +125,3 @@ func (c *ExternalDependencyContext) Parse(s string) {
127125
c.AddDependency(value[:index], time.Millisecond*time.Duration(dur))
128126
}
129127
}
130-
131-
// externalDependency represents one external dependency that
132-
// was involved in the process to creating a response
133-
type externalDependency struct {
134-
Name string // canonical name of the source
135-
Duration time.Duration // time spend with the external dependency
136-
}
137-
138-
// String returns a formated single external dependency
139-
func (r externalDependency) String() string {
140-
return fmt.Sprintf(depFormat, r.Name, r.Duration.Milliseconds())
141-
}

http/middleware/external_dependency_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ func Test_ExternalDependencyContext_String(t *testing.T) {
5656

5757
edc.AddDependency("test4", time.Millisecond*123)
5858
assert.EqualValues(t, "test1:1,test2:0,test3:1000,test4:123", edc.String())
59+
60+
// This should overwrite the previous value
61+
edc.AddDependency("test4", time.Millisecond*123)
62+
assert.EqualValues(t, "test1:1,test2:0,test3:1000,test4:246", edc.String())
5963
}
6064

6165
func Test_ExternalDependencyContext_Parse(t *testing.T) {
@@ -78,4 +82,8 @@ func Test_ExternalDependencyContext_Parse(t *testing.T) {
7882

7983
edc.Parse("test3:1000,test4:123")
8084
assert.EqualValues(t, "test1:1,test2:0,test3:1000,test4:123", edc.String())
85+
86+
// This should overwrite the previous value
87+
edc.Parse("test3:1000")
88+
assert.EqualValues(t, "test1:1,test2:0,test3:2000,test4:123", edc.String())
8189
}

0 commit comments

Comments
 (0)