feat: add posthog analytics support (#52)

* feat: add posthog analytics events

* Update internal/analytics/analytics.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sahil Bansal <bansalsahil315@gmail.com>

---------

Signed-off-by: Sahil Bansal <bansalsahil315@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Sahil Bansal
2025-06-30 09:47:14 +05:30
committed by GitHub
co-authored by Copilot
parent 0a62473e9a
commit 0e17378d3e
12 changed files with 234 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
package analytics
import (
"log"
"os"
"strconv"
"time"
"github.com/google/uuid"
"github.com/posthog/posthog-go"
)
const (
postHogApiKey = "phc_ckrojb22DtoIMBhIC3k3hh7tmRw0ng11gSaLUXSqwSt" // gitleaks:allow
postHogEventEndpoint = "https://us.i.posthog.com"
telemetryDisableEnvKey = "PMG_DISABLE_TELEMETRY"
)
var (
globalPosthogClient posthog.Client
// This is the distinct ID to anonymously identify an invocation of the CLI.
globalDistinctId string
)
func init() {
if isTelemetryDisabled() {
return
}
client, err := posthog.NewWithConfig(postHogApiKey, posthog.Config{
Endpoint: postHogEventEndpoint,
})
if err != nil {
log.Fatalf("Failed to initialize posthog client: %v", err)
}
globalPosthogClient = client
randomUUID, err := uuid.NewRandom()
if err != nil {
log.Fatalf("Failed to generate random UUID: %v", err)
}
globalDistinctId = randomUUID.String()
}
func isTelemetryDisabled() bool {
val := os.Getenv(telemetryDisableEnvKey)
if booleanVal, err := strconv.ParseBool(val); err == nil {
return booleanVal
}
return false
}
func IsDisabled() bool {
return isTelemetryDisabled()
}
// We want to ensure that we do not collect any telemetry if the user has disabled them.
func Track(distinctId string, event string, properties posthog.Properties) {
if isTelemetryDisabled() {
return
}
if globalPosthogClient == nil {
return
}
_ = globalPosthogClient.Enqueue(&posthog.Capture{
DistinctId: distinctId,
Event: event,
Properties: properties,
Timestamp: time.Now(),
})
}
func TrackEvent(event string) {
Track(globalDistinctId, event,
posthog.NewProperties().
Set("$process_person_profile", false))
}
func Close() {
if globalPosthogClient == nil {
return
}
_ = globalPosthogClient.Close()
globalPosthogClient = nil
}
+29
View File
@@ -0,0 +1,29 @@
package analytics
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsDisabled(t *testing.T) {
t.Run("returns true if PMG_DISABLE_TELEMETRY is set to true", func(t *testing.T) {
os.Setenv(telemetryDisableEnvKey, "true")
defer os.Unsetenv(telemetryDisableEnvKey)
assert.True(t, IsDisabled())
})
t.Run("returns false if PMG_DISABLE_TELEMETRY is not set", func(t *testing.T) {
assert.False(t, IsDisabled())
})
}
func TestCloseIsImmutable(t *testing.T) {
Close()
assert.Nil(t, globalPosthogClient)
Close()
assert.Nil(t, globalPosthogClient)
}
+43
View File
@@ -0,0 +1,43 @@
package analytics
import "os"
type environmentType string
const (
environmentTypeGitHubActions environmentType = "github_actions"
environmentTypeGitLabCI environmentType = "gitlab_ci"
environmentTypeDocker environmentType = "docker"
)
// Map of environment variables which if set will determine environments
var ciEnvVars = map[string]environmentType{
"GITHUB_ACTION": environmentTypeGitHubActions,
"GITHUB_WORKFLOW": environmentTypeGitHubActions,
"GITLAB_CI": environmentTypeGitLabCI,
"CI_COMMIT_BRANCH": environmentTypeGitLabCI,
}
func TrackCI() {
uniqueTypes := make(map[environmentType]bool)
for envVar, envVarType := range ciEnvVars {
if os.Getenv(envVar) != "" {
uniqueTypes[envVarType] = true
}
}
for envVarType := range uniqueTypes {
trackCiEvent(envVarType)
}
}
func trackCiEvent(envVarType environmentType) {
switch envVarType {
case environmentTypeGitHubActions:
TrackCommandGenerateEnvGitHubActions()
case environmentTypeGitLabCI:
TrackCommandGenerateEnvGitLabCI()
case environmentTypeDocker:
TrackCommandGenerateEnvDocker()
}
}
+3
View File
@@ -0,0 +1,3 @@
// analytics package is for internal utility functions for tracking
// anonymous usage analytics.
package analytics
+40
View File
@@ -0,0 +1,40 @@
package analytics
const (
eventRun = "pmg_command_run"
eventCommandNpm = "pmg_command_npm"
eventCommandPnpm = "pmg_command_pnpm"
eventCommandPip = "pmg_command_pip"
eventPmgGenerateEnvDocker = "pmg_command_generate_env_docker"
eventPmgGenerateEnvGitHubActions = "pmg_command_generate_env_github_actions"
eventPmgGenerateEnvGitLabCI = "pmg_command_generate_env_gitlab_ci"
)
func TrackCommandRun() {
TrackEvent(eventRun)
}
func TrackCommandNpm() {
TrackEvent(eventCommandNpm)
}
func TrackCommandPnpm() {
TrackEvent(eventCommandPnpm)
}
func TrackCommandPip() {
TrackEvent(eventCommandPip)
}
func TrackCommandGenerateEnvDocker() {
TrackEvent(eventPmgGenerateEnvDocker)
}
func TrackCommandGenerateEnvGitHubActions() {
TrackEvent(eventPmgGenerateEnvGitHubActions)
}
func TrackCommandGenerateEnvGitLabCI() {
TrackEvent(eventPmgGenerateEnvGitLabCI)
}