Added whoami#42
Conversation
PR SummaryMedium Risk Overview Updates telemetry user identification: the tracker now defaults to Written by Cursor Bugbot for commit 04fc3f9. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Empty UserID causes Amplitude to silently drop events
- Initialized tracker with default 'anonymous' userID to ensure all events meet Amplitude's 5-character MinIDLength requirement and are not silently dropped.
Or push these changes by commenting:
@cursor push e2ae6dca7c
Preview (e2ae6dca7c)
diff --git a/tracking/tracking.go b/tracking/tracking.go
--- a/tracking/tracking.go
+++ b/tracking/tracking.go
@@ -41,12 +41,13 @@
return &Tracker{
client: amplitude.NewClient(ampConfig),
version: cfg.CLIVersion,
+ userID: "anonymous",
enabled: true,
}
}
// SetUserID sets the real user identity (e.g. "user_123") for all subsequent events.
-// If not called, events are sent with an empty UserID.
+// If not called, events are sent with UserID "anonymous".
func (t *Tracker) SetUserID(id string) {
t.userID = id
}|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Sim commands never resolve user identity for tracking
- Added customer ID resolution to simPreRun function to ensure sim commands properly identify users for analytics tracking since the sim command's PersistentPreRunE overrides the root command's hook.
Or push these changes by commenting:
@cursor push 694a644423
Preview (694a644423)
diff --git a/cli/root.go b/cli/root.go
--- a/cli/root.go
+++ b/cli/root.go
@@ -80,7 +80,7 @@
// Resolve customer identity for analytics (best-effort, never blocks the CLI).
if tr := cmdutil.TrackerFromCmd(cmd); tr != nil {
- if customerID := resolveCustomerID(client, env.APIKey); customerID != "" {
+ if customerID := ResolveCustomerID(client, env.APIKey); customerID != "" {
tr.SetUserID(customerID)
}
}
@@ -149,11 +149,11 @@
}
}
-// resolveCustomerID returns the customer_id associated with the given API key.
+// ResolveCustomerID returns the customer_id associated with the given API key.
// The customer_id may represent a user ("user_123") or a team ("team_456").
// It uses a local cache to avoid calling /api/whoami on every invocation.
// On any error it returns "" silently — analytics should never block the CLI.
-func resolveCustomerID(client dune.DuneClient, apiKey string) string {
+func ResolveCustomerID(client dune.DuneClient, apiKey string) string {
keyHash := authconfig.HashAPIKey(apiKey)
// Try the cache first.
diff --git a/cmd/sim/sim.go b/cmd/sim/sim.go
--- a/cmd/sim/sim.go
+++ b/cmd/sim/sim.go
@@ -8,6 +8,9 @@
"github.com/spf13/cobra"
+ "github.com/duneanalytics/duneapi-client-go/config"
+ "github.com/duneanalytics/duneapi-client-go/dune"
+
"github.com/duneanalytics/cli/authconfig"
"github.com/duneanalytics/cli/cmd/sim/evm"
"github.com/duneanalytics/cli/cmd/sim/svm"
@@ -50,6 +53,17 @@
// correct duration for telemetry.
cmdutil.SetStartTime(cmd, time.Now())
+ // Resolve customer identity for analytics (best-effort, never blocks the CLI).
+ // We try to resolve the Dune API key (not the Sim API key) to identify the user.
+ if tr := cmdutil.TrackerFromCmd(cmd); tr != nil {
+ if env := resolveDuneEnv(); env != nil {
+ client := dune.NewDuneClient(env)
+ if customerID := resolveCustomerIDForSim(client, env.APIKey); customerID != "" {
+ tr.SetUserID(customerID)
+ }
+ }
+ }
+
// Commands like `sim evm supported-chains` that hit public endpoints
// don't require an API key. Provide a bare (unauthenticated) client so
// they can still use the shared HTTP infrastructure and error handling.
@@ -103,3 +117,54 @@
}
return v.(*SimClient)
}
+
+// resolveDuneEnv attempts to resolve the Dune API key from environment variables
+// or the config file, returning a Dune environment configuration.
+// Returns nil if no Dune API key is available (this is not an error for sim commands).
+func resolveDuneEnv() *config.Env {
+ // Try environment variable first.
+ env, err := config.FromEnvVars()
+ if err == nil {
+ return env
+ }
+
+ // Try config file.
+ cfg, err := authconfig.Load()
+ if err != nil || cfg == nil {
+ return nil
+ }
+
+ key := strings.TrimSpace(cfg.APIKey)
+ if key == "" {
+ return nil
+ }
+
+ return config.FromAPIKey(key)
+}
+
+// resolveCustomerIDForSim is a wrapper around cli.ResolveCustomerID that
+// can be called from the sim package. It must be declared here to avoid
+// a circular import between cli and cmd/sim.
+func resolveCustomerIDForSim(client dune.DuneClient, apiKey string) string {
+ keyHash := authconfig.HashAPIKey(apiKey)
+
+ // Try the cache first.
+ cached, err := authconfig.LoadIdentity()
+ if err == nil && cached != nil && cached.APIKeyHash == keyHash && cached.CustomerID != "" {
+ return cached.CustomerID
+ }
+
+ // Cache miss or stale — call the API.
+ resp, err := client.WhoAmI()
+ if err != nil || resp == nil || resp.CustomerID == "" {
+ return ""
+ }
+
+ // Persist for next time (best-effort).
+ _ = authconfig.SaveIdentity(&authconfig.UserIdentity{
+ CustomerID: resp.CustomerID,
+ APIKeyHash: keyHash,
+ })
+
+ return resp.CustomerID
+}Comment @cursor review or bugbot run to trigger another review on this PR


Added new cli command
whoamiand added tracking of user actions (when enabled) that are based on the actual user/team ids