7
7
"sync"
8
8
"time"
9
9
10
+ "golang.org/x/exp/maps"
10
11
"tailscale.com/tstime/rate"
11
12
12
13
"cdr.dev/slog"
@@ -20,7 +21,12 @@ func ReportCLITelemetry(log slog.Logger, rep telemetry.Reporter) func(http.Handl
20
21
21
22
// We send telemetry at most once per minute.
22
23
limiter = rate .NewLimiter (rate .Every (time .Minute ), 1 )
23
- queue []telemetry.CLIInvocation
24
+ // We map by timestamp to deduplicate invocations, since one invocation
25
+ // will send multiple requests, each with a duplicate header. It's still
26
+ // possible for duplicates to reach the telemetry server since requests
27
+ // can get processed by different servers, but our analysis server
28
+ // can deduplicate them as well.
29
+ queue = make (map [string ]telemetry.CLIInvocation )
24
30
)
25
31
26
32
log = log .Named ("cli-telemetry" )
@@ -62,18 +68,18 @@ func ReportCLITelemetry(log slog.Logger, rep telemetry.Reporter) func(http.Handl
62
68
mu .Lock ()
63
69
defer mu .Unlock ()
64
70
65
- queue = append ( queue , inv )
71
+ queue [ inv . InvokedAt . String ()] = inv
66
72
if ! limiter .Allow () && len (queue ) < 1024 {
67
73
return
68
74
}
69
75
rep .Report (& telemetry.Snapshot {
70
- CLIInvocations : queue ,
76
+ CLIInvocations : maps . Values ( queue ) ,
71
77
})
72
78
log .Debug (
73
79
r .Context (),
74
80
"report sent" , slog .F ("count" , len (queue )),
75
81
)
76
- queue = queue [: 0 ]
82
+ maps . Clear ( queue )
77
83
}()
78
84
})
79
85
}
0 commit comments