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 = &litude.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 = &litude.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 }