github.com/ddev/ddev@v1.23.2-0.20240519125000-d824ffe36ff3/third_party/ampli/ampli.go (about)

     1  // ampli.go
     2  //
     3  // Ampli - A strong typed wrapper for your Analytics
     4  //
     5  // This file is generated by Amplitude.
     6  // To update run 'ampli pull ddev'
     7  //
     8  // Required dependencies: github.com/amplitude/analytics-go@latest
     9  // Tracking Plan Version: 8
    10  // Build: 1.0.0
    11  // Runtime: go-ampli
    12  //
    13  // View Tracking Plan: https://data.amplitude.com/ddev/DDEV/events/main/latest
    14  //
    15  // Full Setup Instructions: https://data.amplitude.com/ddev/DDEV/implementation/main/latest/getting-started/ddev
    16  //
    17  
    18  package ampli
    19  
    20  import (
    21  	"log"
    22  	"sync"
    23  
    24  	"github.com/amplitude/analytics-go/amplitude"
    25  )
    26  
    27  type (
    28  	EventOptions  = amplitude.EventOptions
    29  	ExecuteResult = amplitude.ExecuteResult
    30  )
    31  
    32  const (
    33  	IdentifyEventType      = amplitude.IdentifyEventType
    34  	GroupIdentifyEventType = amplitude.GroupIdentifyEventType
    35  
    36  	ServerZoneUS = amplitude.ServerZoneUS
    37  	ServerZoneEU = amplitude.ServerZoneEU
    38  )
    39  
    40  var (
    41  	NewClientConfig = amplitude.NewConfig
    42  	NewClient       = amplitude.NewClient
    43  )
    44  
    45  var Instance = Ampli{}
    46  
    47  type Environment string
    48  
    49  const (
    50  	EnvironmentDevelopment Environment = `development`
    51  
    52  	EnvironmentProduction Environment = `production`
    53  )
    54  
    55  var APIKey = map[Environment]string{
    56  	EnvironmentDevelopment: ``,
    57  
    58  	EnvironmentProduction: ``,
    59  }
    60  
    61  // LoadClientOptions is Client options setting to initialize Ampli client.
    62  //
    63  // Params:
    64  //   - APIKey: the API key of Amplitude project
    65  //   - Instance: the core SDK instance used by Ampli client
    66  //   - Configuration: the core SDK client configuration instance
    67  type LoadClientOptions struct {
    68  	APIKey        string
    69  	Instance      amplitude.Client
    70  	Configuration amplitude.Config
    71  }
    72  
    73  // LoadOptions is options setting to initialize Ampli client.
    74  //
    75  // Params:
    76  //   - Environment: the environment of Amplitude Data project
    77  //   - Disabled: the flag of disabled Ampli client
    78  //   - Client: the LoadClientOptions struct
    79  type LoadOptions struct {
    80  	Environment Environment
    81  	Disabled    bool
    82  	Client      LoadClientOptions
    83  }
    84  
    85  type baseEvent struct {
    86  	eventType  string
    87  	properties map[string]interface{}
    88  }
    89  
    90  type Event interface {
    91  	ToAmplitudeEvent() amplitude.Event
    92  }
    93  
    94  func newBaseEvent(eventType string, properties map[string]interface{}) baseEvent {
    95  	return baseEvent{
    96  		eventType:  eventType,
    97  		properties: properties,
    98  	}
    99  }
   100  
   101  func (event baseEvent) ToAmplitudeEvent() amplitude.Event {
   102  	return amplitude.Event{
   103  		EventType:       event.eventType,
   104  		EventProperties: event.properties,
   105  	}
   106  }
   107  
   108  var Identify = struct {
   109  	Builder func() interface {
   110  		DdevEnvironment(ddevEnvironment string) interface {
   111  			DockerPlatform(dockerPlatform string) interface {
   112  				DockerVersion(dockerVersion string) interface {
   113  					Timezone(timezone string) IdentifyBuilder
   114  				}
   115  			}
   116  		}
   117  	}
   118  }{
   119  	Builder: func() interface {
   120  		DdevEnvironment(ddevEnvironment string) interface {
   121  			DockerPlatform(dockerPlatform string) interface {
   122  				DockerVersion(dockerVersion string) interface {
   123  					Timezone(timezone string) IdentifyBuilder
   124  				}
   125  			}
   126  		}
   127  	} {
   128  		return &identifyBuilder{
   129  			properties: map[string]interface{}{},
   130  		}
   131  	},
   132  }
   133  
   134  type IdentifyEvent interface {
   135  	Event
   136  	identify()
   137  }
   138  
   139  type identifyEvent struct {
   140  	baseEvent
   141  }
   142  
   143  func (e identifyEvent) identify() {
   144  }
   145  
   146  type IdentifyBuilder interface {
   147  	Build() IdentifyEvent
   148  	User(user string) IdentifyBuilder
   149  	WslDistro(wslDistro string) IdentifyBuilder
   150  }
   151  
   152  type identifyBuilder struct {
   153  	properties map[string]interface{}
   154  }
   155  
   156  func (b *identifyBuilder) DdevEnvironment(ddevEnvironment string) interface {
   157  	DockerPlatform(dockerPlatform string) interface {
   158  		DockerVersion(dockerVersion string) interface {
   159  			Timezone(timezone string) IdentifyBuilder
   160  		}
   161  	}
   162  } {
   163  	b.properties[`DDEV Environment`] = ddevEnvironment
   164  
   165  	return b
   166  }
   167  
   168  func (b *identifyBuilder) DockerPlatform(dockerPlatform string) interface {
   169  	DockerVersion(dockerVersion string) interface {
   170  		Timezone(timezone string) IdentifyBuilder
   171  	}
   172  } {
   173  	b.properties[`Docker Platform`] = dockerPlatform
   174  
   175  	return b
   176  }
   177  
   178  func (b *identifyBuilder) DockerVersion(dockerVersion string) interface {
   179  	Timezone(timezone string) IdentifyBuilder
   180  } {
   181  	b.properties[`Docker Version`] = dockerVersion
   182  
   183  	return b
   184  }
   185  
   186  func (b *identifyBuilder) Timezone(timezone string) IdentifyBuilder {
   187  	b.properties[`Timezone`] = timezone
   188  
   189  	return b
   190  }
   191  
   192  func (b *identifyBuilder) User(user string) IdentifyBuilder {
   193  	b.properties[`User`] = user
   194  
   195  	return b
   196  }
   197  
   198  func (b *identifyBuilder) WslDistro(wslDistro string) IdentifyBuilder {
   199  	b.properties[`WSL Distro`] = wslDistro
   200  
   201  	return b
   202  }
   203  
   204  func (b *identifyBuilder) Build() IdentifyEvent {
   205  	return &identifyEvent{
   206  		newBaseEvent(IdentifyEventType, b.properties),
   207  	}
   208  }
   209  
   210  func (e identifyEvent) ToAmplitudeEvent() amplitude.Event {
   211  	identify := amplitude.Identify{}
   212  	for name, value := range e.properties {
   213  		identify.Set(name, value)
   214  	}
   215  
   216  	return amplitude.Event{
   217  		EventType:      IdentifyEventType,
   218  		UserProperties: identify.Properties,
   219  	}
   220  }
   221  
   222  var Command = struct {
   223  	Builder func() interface {
   224  		Arguments(arguments []string) interface {
   225  			CalledAs(calledAs string) interface {
   226  				CommandName(commandName string) interface {
   227  					CommandPath(commandPath string) CommandBuilder
   228  				}
   229  			}
   230  		}
   231  	}
   232  }{
   233  	Builder: func() interface {
   234  		Arguments(arguments []string) interface {
   235  			CalledAs(calledAs string) interface {
   236  				CommandName(commandName string) interface {
   237  					CommandPath(commandPath string) CommandBuilder
   238  				}
   239  			}
   240  		}
   241  	} {
   242  		return &commandBuilder{
   243  			properties: map[string]interface{}{},
   244  		}
   245  	},
   246  }
   247  
   248  type CommandEvent interface {
   249  	Event
   250  	command()
   251  }
   252  
   253  type commandEvent struct {
   254  	baseEvent
   255  }
   256  
   257  func (e commandEvent) command() {
   258  }
   259  
   260  type CommandBuilder interface {
   261  	Build() CommandEvent
   262  }
   263  
   264  type commandBuilder struct {
   265  	properties map[string]interface{}
   266  }
   267  
   268  func (b *commandBuilder) Arguments(arguments []string) interface {
   269  	CalledAs(calledAs string) interface {
   270  		CommandName(commandName string) interface {
   271  			CommandPath(commandPath string) CommandBuilder
   272  		}
   273  	}
   274  } {
   275  	b.properties[`Arguments`] = arguments
   276  
   277  	return b
   278  }
   279  
   280  func (b *commandBuilder) CalledAs(calledAs string) interface {
   281  	CommandName(commandName string) interface {
   282  		CommandPath(commandPath string) CommandBuilder
   283  	}
   284  } {
   285  	b.properties[`Called As`] = calledAs
   286  
   287  	return b
   288  }
   289  
   290  func (b *commandBuilder) CommandName(commandName string) interface {
   291  	CommandPath(commandPath string) CommandBuilder
   292  } {
   293  	b.properties[`Command Name`] = commandName
   294  
   295  	return b
   296  }
   297  
   298  func (b *commandBuilder) CommandPath(commandPath string) CommandBuilder {
   299  	b.properties[`Command Path`] = commandPath
   300  
   301  	return b
   302  }
   303  
   304  func (b *commandBuilder) Build() CommandEvent {
   305  	return &commandEvent{
   306  		newBaseEvent(`Command`, b.properties),
   307  	}
   308  }
   309  
   310  var Project = struct {
   311  	Builder func() interface {
   312  		AddOns(addOns []string) interface {
   313  			Containers(containers []string) interface {
   314  				ContainersOmitted(containersOmitted []string) interface {
   315  					FailOnHookFail(failOnHookFail bool) interface {
   316  						Id(id string) interface {
   317  							NodejsVersion(nodejsVersion string) interface {
   318  								PerformanceMode(performanceMode string) interface {
   319  									PhpVersion(phpVersion string) interface {
   320  										ProjectType(projectType string) interface {
   321  											RouterDisabled(routerDisabled bool) interface {
   322  												WebserverType(webserverType string) ProjectBuilder
   323  											}
   324  										}
   325  									}
   326  								}
   327  							}
   328  						}
   329  					}
   330  				}
   331  			}
   332  		}
   333  	}
   334  }{
   335  	Builder: func() interface {
   336  		AddOns(addOns []string) interface {
   337  			Containers(containers []string) interface {
   338  				ContainersOmitted(containersOmitted []string) interface {
   339  					FailOnHookFail(failOnHookFail bool) interface {
   340  						Id(id string) interface {
   341  							NodejsVersion(nodejsVersion string) interface {
   342  								PerformanceMode(performanceMode string) interface {
   343  									PhpVersion(phpVersion string) interface {
   344  										ProjectType(projectType string) interface {
   345  											RouterDisabled(routerDisabled bool) interface {
   346  												WebserverType(webserverType string) ProjectBuilder
   347  											}
   348  										}
   349  									}
   350  								}
   351  							}
   352  						}
   353  					}
   354  				}
   355  			}
   356  		}
   357  	} {
   358  		return &projectBuilder{
   359  			properties: map[string]interface{}{},
   360  		}
   361  	},
   362  }
   363  
   364  type ProjectEvent interface {
   365  	Event
   366  	project()
   367  }
   368  
   369  type projectEvent struct {
   370  	baseEvent
   371  }
   372  
   373  func (e projectEvent) project() {
   374  }
   375  
   376  type ProjectBuilder interface {
   377  	Build() ProjectEvent
   378  	DatabaseType(databaseType string) ProjectBuilder
   379  	DatabaseVersion(databaseVersion string) ProjectBuilder
   380  	Router(router string) ProjectBuilder
   381  }
   382  
   383  type projectBuilder struct {
   384  	properties map[string]interface{}
   385  }
   386  
   387  func (b *projectBuilder) AddOns(addOns []string) interface {
   388  	Containers(containers []string) interface {
   389  		ContainersOmitted(containersOmitted []string) interface {
   390  			FailOnHookFail(failOnHookFail bool) interface {
   391  				Id(id string) interface {
   392  					NodejsVersion(nodejsVersion string) interface {
   393  						PerformanceMode(performanceMode string) interface {
   394  							PhpVersion(phpVersion string) interface {
   395  								ProjectType(projectType string) interface {
   396  									RouterDisabled(routerDisabled bool) interface {
   397  										WebserverType(webserverType string) ProjectBuilder
   398  									}
   399  								}
   400  							}
   401  						}
   402  					}
   403  				}
   404  			}
   405  		}
   406  	}
   407  } {
   408  	b.properties[`Add-ons`] = addOns
   409  
   410  	return b
   411  }
   412  
   413  func (b *projectBuilder) Containers(containers []string) interface {
   414  	ContainersOmitted(containersOmitted []string) interface {
   415  		FailOnHookFail(failOnHookFail bool) interface {
   416  			Id(id string) interface {
   417  				NodejsVersion(nodejsVersion string) interface {
   418  					PerformanceMode(performanceMode string) interface {
   419  						PhpVersion(phpVersion string) interface {
   420  							ProjectType(projectType string) interface {
   421  								RouterDisabled(routerDisabled bool) interface {
   422  									WebserverType(webserverType string) ProjectBuilder
   423  								}
   424  							}
   425  						}
   426  					}
   427  				}
   428  			}
   429  		}
   430  	}
   431  } {
   432  	b.properties[`Containers`] = containers
   433  
   434  	return b
   435  }
   436  
   437  func (b *projectBuilder) ContainersOmitted(containersOmitted []string) interface {
   438  	FailOnHookFail(failOnHookFail bool) interface {
   439  		Id(id string) interface {
   440  			NodejsVersion(nodejsVersion string) interface {
   441  				PerformanceMode(performanceMode string) interface {
   442  					PhpVersion(phpVersion string) interface {
   443  						ProjectType(projectType string) interface {
   444  							RouterDisabled(routerDisabled bool) interface {
   445  								WebserverType(webserverType string) ProjectBuilder
   446  							}
   447  						}
   448  					}
   449  				}
   450  			}
   451  		}
   452  	}
   453  } {
   454  	b.properties[`Containers Omitted`] = containersOmitted
   455  
   456  	return b
   457  }
   458  
   459  func (b *projectBuilder) FailOnHookFail(failOnHookFail bool) interface {
   460  	Id(id string) interface {
   461  		NodejsVersion(nodejsVersion string) interface {
   462  			PerformanceMode(performanceMode string) interface {
   463  				PhpVersion(phpVersion string) interface {
   464  					ProjectType(projectType string) interface {
   465  						RouterDisabled(routerDisabled bool) interface {
   466  							WebserverType(webserverType string) ProjectBuilder
   467  						}
   468  					}
   469  				}
   470  			}
   471  		}
   472  	}
   473  } {
   474  	b.properties[`Fail On Hook Fail`] = failOnHookFail
   475  
   476  	return b
   477  }
   478  
   479  func (b *projectBuilder) Id(id string) interface {
   480  	NodejsVersion(nodejsVersion string) interface {
   481  		PerformanceMode(performanceMode string) interface {
   482  			PhpVersion(phpVersion string) interface {
   483  				ProjectType(projectType string) interface {
   484  					RouterDisabled(routerDisabled bool) interface {
   485  						WebserverType(webserverType string) ProjectBuilder
   486  					}
   487  				}
   488  			}
   489  		}
   490  	}
   491  } {
   492  	b.properties[`ID`] = id
   493  
   494  	return b
   495  }
   496  
   497  func (b *projectBuilder) NodejsVersion(nodejsVersion string) interface {
   498  	PerformanceMode(performanceMode string) interface {
   499  		PhpVersion(phpVersion string) interface {
   500  			ProjectType(projectType string) interface {
   501  				RouterDisabled(routerDisabled bool) interface {
   502  					WebserverType(webserverType string) ProjectBuilder
   503  				}
   504  			}
   505  		}
   506  	}
   507  } {
   508  	b.properties[`Nodejs Version`] = nodejsVersion
   509  
   510  	return b
   511  }
   512  
   513  func (b *projectBuilder) PerformanceMode(performanceMode string) interface {
   514  	PhpVersion(phpVersion string) interface {
   515  		ProjectType(projectType string) interface {
   516  			RouterDisabled(routerDisabled bool) interface {
   517  				WebserverType(webserverType string) ProjectBuilder
   518  			}
   519  		}
   520  	}
   521  } {
   522  	b.properties[`Performance Mode`] = performanceMode
   523  
   524  	return b
   525  }
   526  
   527  func (b *projectBuilder) PhpVersion(phpVersion string) interface {
   528  	ProjectType(projectType string) interface {
   529  		RouterDisabled(routerDisabled bool) interface {
   530  			WebserverType(webserverType string) ProjectBuilder
   531  		}
   532  	}
   533  } {
   534  	b.properties[`PHP Version`] = phpVersion
   535  
   536  	return b
   537  }
   538  
   539  func (b *projectBuilder) ProjectType(projectType string) interface {
   540  	RouterDisabled(routerDisabled bool) interface {
   541  		WebserverType(webserverType string) ProjectBuilder
   542  	}
   543  } {
   544  	b.properties[`Project Type`] = projectType
   545  
   546  	return b
   547  }
   548  
   549  func (b *projectBuilder) RouterDisabled(routerDisabled bool) interface {
   550  	WebserverType(webserverType string) ProjectBuilder
   551  } {
   552  	b.properties[`Router Disabled`] = routerDisabled
   553  
   554  	return b
   555  }
   556  
   557  func (b *projectBuilder) WebserverType(webserverType string) ProjectBuilder {
   558  	b.properties[`Webserver Type`] = webserverType
   559  
   560  	return b
   561  }
   562  
   563  func (b *projectBuilder) DatabaseType(databaseType string) ProjectBuilder {
   564  	b.properties[`Database Type`] = databaseType
   565  
   566  	return b
   567  }
   568  
   569  func (b *projectBuilder) DatabaseVersion(databaseVersion string) ProjectBuilder {
   570  	b.properties[`Database Version`] = databaseVersion
   571  
   572  	return b
   573  }
   574  
   575  func (b *projectBuilder) Router(router string) ProjectBuilder {
   576  	b.properties[`Router`] = router
   577  
   578  	return b
   579  }
   580  
   581  func (b *projectBuilder) Build() ProjectEvent {
   582  	return &projectEvent{
   583  		newBaseEvent(`Project`, b.properties),
   584  	}
   585  }
   586  
   587  type Ampli struct {
   588  	Disabled bool
   589  	Client   amplitude.Client
   590  	mutex    sync.RWMutex
   591  }
   592  
   593  // Load initializes the Ampli wrapper.
   594  // Call once when your application starts.
   595  func (a *Ampli) Load(options LoadOptions) {
   596  	if a.Client != nil {
   597  		log.Print("Warn: Ampli is already initialized. Ampli.Load() should be called once at application start up.")
   598  
   599  		return
   600  	}
   601  
   602  	var apiKey string
   603  	switch {
   604  	case options.Client.APIKey != "":
   605  		apiKey = options.Client.APIKey
   606  	case options.Environment != "":
   607  		apiKey = APIKey[options.Environment]
   608  	default:
   609  		apiKey = options.Client.Configuration.APIKey
   610  	}
   611  
   612  	if apiKey == "" && options.Client.Instance == nil {
   613  		log.Print("Error: Ampli.Load() requires option.Environment, " +
   614  			"and apiKey from either options.Instance.APIKey or APIKey[options.Environment], " +
   615  			"or options.Instance.Instance")
   616  	}
   617  
   618  	clientConfig := options.Client.Configuration
   619  
   620  	if clientConfig.Plan == nil {
   621  		clientConfig.Plan = &amplitude.Plan{
   622  			Branch:    `main`,
   623  			Source:    `ddev`,
   624  			Version:   `8`,
   625  			VersionID: `48e9307f-858c-4b3e-ba94-80431d08f8d4`,
   626  		}
   627  	}
   628  
   629  	if clientConfig.IngestionMetadata == nil {
   630  		clientConfig.IngestionMetadata = &amplitude.IngestionMetadata{
   631  			SourceName:    `go-go-ampli`,
   632  			SourceVersion: `2.0.0`,
   633  		}
   634  	}
   635  
   636  	if options.Client.Instance != nil {
   637  		a.Client = options.Client.Instance
   638  	} else {
   639  		clientConfig.APIKey = apiKey
   640  		a.Client = amplitude.NewClient(clientConfig)
   641  	}
   642  
   643  	a.mutex.Lock()
   644  	a.Disabled = options.Disabled
   645  	a.mutex.Unlock()
   646  }
   647  
   648  // InitializedAndEnabled checks if Ampli is initialized and enabled.
   649  func (a *Ampli) InitializedAndEnabled() bool {
   650  	if a.Client == nil {
   651  		log.Print("Error: Ampli is not yet initialized. Have you called Ampli.Load() on app start?")
   652  
   653  		return false
   654  	}
   655  
   656  	a.mutex.RLock()
   657  	defer a.mutex.RUnlock()
   658  
   659  	return !a.Disabled
   660  }
   661  
   662  func (a *Ampli) setUserID(userID string, eventOptions *EventOptions) {
   663  	if userID != "" {
   664  		eventOptions.UserID = userID
   665  	}
   666  }
   667  
   668  // Track tracks an event.
   669  func (a *Ampli) Track(userID string, event Event, eventOptions ...EventOptions) {
   670  	if !a.InitializedAndEnabled() {
   671  		return
   672  	}
   673  
   674  	var options EventOptions
   675  	if len(eventOptions) > 0 {
   676  		options = eventOptions[0]
   677  	}
   678  
   679  	a.setUserID(userID, &options)
   680  
   681  	baseEvent := event.ToAmplitudeEvent()
   682  	baseEvent.EventOptions = options
   683  
   684  	a.Client.Track(baseEvent)
   685  }
   686  
   687  // Identify identifies a user and set user properties.
   688  func (a *Ampli) Identify(userID string, identify IdentifyEvent, eventOptions ...EventOptions) {
   689  	a.Track(userID, identify, eventOptions...)
   690  }
   691  
   692  // Flush flushes events waiting in buffer.
   693  func (a *Ampli) Flush() {
   694  	if !a.InitializedAndEnabled() {
   695  		return
   696  	}
   697  
   698  	a.Client.Flush()
   699  }
   700  
   701  // Shutdown disables and shutdowns Ampli Instance.
   702  func (a *Ampli) Shutdown() {
   703  	if !a.InitializedAndEnabled() {
   704  		return
   705  	}
   706  
   707  	a.mutex.Lock()
   708  	a.Disabled = true
   709  	a.mutex.Unlock()
   710  
   711  	a.Client.Shutdown()
   712  }
   713  
   714  func (a *Ampli) Command(userID string, event CommandEvent, eventOptions ...EventOptions) {
   715  	a.Track(userID, event, eventOptions...)
   716  }
   717  
   718  func (a *Ampli) Project(userID string, event ProjectEvent, eventOptions ...EventOptions) {
   719  	a.Track(userID, event, eventOptions...)
   720  }