77 "sync"
88 "time"
99
10+ "golang.org/x/exp/maps"
1011 "tailscale.com/tstime/rate"
1112
1213 "cdr.dev/slog"
@@ -20,7 +21,16 @@ func ReportCLITelemetry(log slog.Logger, rep telemetry.Reporter) func(http.Handl
2021
2122 // We send telemetry at most once per minute.
2223 limiter = rate .NewLimiter (rate .Every (time .Minute ), 1 )
23- queue []telemetry.CLIInvocation
24+
25+ // We map by timestamp to deduplicate invocations, since one invocation
26+ // will send multiple requests, each with a duplicate header. It's still
27+ // possible for duplicates to reach the telemetry service since requests
28+ // can get processed by different coderds, but our analysis tools
29+ // will deduplicate by timestamp as well.
30+ //
31+ // This approach just helps us reduce storage and ingest fees, and doesn't
32+ // change the correctness.
33+ queue = make (map [string ]telemetry.CLIInvocation )
2434 )
2535
2636 log = log .Named ("cli-telemetry" )
@@ -62,18 +72,18 @@ func ReportCLITelemetry(log slog.Logger, rep telemetry.Reporter) func(http.Handl
6272 mu .Lock ()
6373 defer mu .Unlock ()
6474
65- queue = append ( queue , inv )
75+ queue [ inv . InvokedAt . String ()] = inv
6676 if ! limiter .Allow () && len (queue ) < 1024 {
6777 return
6878 }
6979 rep .Report (& telemetry.Snapshot {
70- CLIInvocations : queue ,
80+ CLIInvocations : maps . Values ( queue ) ,
7181 })
7282 log .Debug (
7383 r .Context (),
7484 "report sent" , slog .F ("count" , len (queue )),
7585 )
76- queue = queue [: 0 ]
86+ maps . Clear ( queue )
7787 }()
7888 })
7989 }
0 commit comments