1919package emulator
2020
2121import (
22+ "crypto/sha256"
23+ "encoding/base64"
2224 "errors"
2325 "fmt"
26+ "net/http"
2427 "os"
28+ "os/user"
29+ "runtime"
2530 "sync"
2631
32+ "github.com/dukex/mixpanel"
2733 "github.com/onflow/flow-emulator/cmd/emulator/start"
2834 "github.com/onflow/flow-go-sdk/crypto"
2935 "github.com/spf13/afero"
@@ -32,12 +38,17 @@ import (
3238 "github.com/onflow/flowkit/v2"
3339 "github.com/onflow/flowkit/v2/config"
3440
41+ "github.com/onflow/flow-cli/build"
3542 "github.com/onflow/flow-cli/internal/command"
43+ "github.com/onflow/flow-cli/internal/settings"
3644 "github.com/onflow/flow-cli/internal/util"
3745)
3846
3947var Cmd * cobra.Command
4048
49+ // Mixpanel client to be reused on each http request of the middleware
50+ var mixpanelClient mixpanel.Mixpanel
51+
4152func configuredServiceKey (
4253 init bool ,
4354 _ crypto.SignatureAlgorithm ,
@@ -97,8 +108,45 @@ func configuredServiceKey(
97108 return * privateKey , serviceAccount .Key .SigAlgo (), serviceAccount .Key .HashAlgo ()
98109}
99110
111+ func trackRequestMiddleware (next http.Handler ) http.Handler {
112+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
113+ // Generate a unique user ID
114+ usr , _ := user .Current () // ignore err, just use empty string
115+ hash := sha256 .Sum256 ([]byte (fmt .Sprintf ("%s%s" , usr .Username , usr .Uid )))
116+ userID := base64 .StdEncoding .EncodeToString (hash [:])
117+
118+ // Track the request in Mixpanel
119+ _ = mixpanelClient .Track (userID , "emulator-request" , & mixpanel.Event {
120+ IP : "0" , // do not track IPs
121+ Properties : map [string ]any {
122+ "method" : r .Method ,
123+ "url" : r .URL .String (),
124+ "version" : build .Semver (),
125+ "os" : runtime .GOOS ,
126+ "ci" : os .Getenv ("CI" ) != "" , // CI is commonly set by CI providers
127+ },
128+ })
129+
130+ // Call the next handler
131+ next .ServeHTTP (w , r )
132+ })
133+ }
134+
100135func init () {
101- Cmd = start .Cmd (configuredServiceKey )
136+ // Initialize mixpanel client only if metrics are enabled and token is not empty
137+ if settings .MetricsEnabled () && command .MixpanelToken != "" {
138+ mixpanelClient = mixpanel .New (command .MixpanelToken , "" )
139+ Cmd = start .Cmd (start.StartConfig {
140+ GetServiceKey : configuredServiceKey ,
141+ RestMiddlewares : []start.HttpMiddleware {trackRequestMiddleware },
142+ })
143+ } else {
144+ Cmd = start .Cmd (start.StartConfig {
145+ GetServiceKey : configuredServiceKey ,
146+ RestMiddlewares : []start.HttpMiddleware {},
147+ })
148+ }
149+
102150 Cmd .Use = "emulator"
103151 Cmd .Short = "Run Flow network for development"
104152 Cmd .GroupID = "tools"
0 commit comments