tracks.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. package analytics
  2. import (
  3. "github.com/porter-dev/porter/api/types"
  4. segment "gopkg.in/segmentio/analytics-go.v3"
  5. )
  6. type segmentTrack interface {
  7. getUserId() string
  8. getEvent() SegmentEvent
  9. getProperties() segment.Properties
  10. }
  11. type defaultTrackOpts struct {
  12. AdditionalProps map[string]interface{}
  13. }
  14. type defaultSegmentTrack struct {
  15. event SegmentEvent
  16. properties segmentProperties
  17. }
  18. func getDefaultSegmentTrack(additionalProps map[string]interface{}, event SegmentEvent) *defaultSegmentTrack {
  19. props := newSegmentProperties()
  20. props.addAdditionalProperties(additionalProps)
  21. return &defaultSegmentTrack{
  22. event: event,
  23. properties: props,
  24. }
  25. }
  26. func (t *defaultSegmentTrack) getEvent() SegmentEvent {
  27. return t.event
  28. }
  29. func (t *defaultSegmentTrack) getProperties() segment.Properties {
  30. props := segment.NewProperties()
  31. for key, val := range t.properties {
  32. props = props.Set(key, val)
  33. }
  34. return props
  35. }
  36. type segmentProperties map[string]interface{}
  37. func newSegmentProperties() segmentProperties {
  38. props := make(map[string]interface{})
  39. return props
  40. }
  41. func (p segmentProperties) addProjectProperties(opts *ProjectScopedTrackOpts) {
  42. p["proj_id"] = opts.ProjectID
  43. }
  44. func (p segmentProperties) addClusterProperties(opts *ClusterScopedTrackOpts) {
  45. p["cluster_id"] = opts.ClusterID
  46. }
  47. func (p segmentProperties) addRegistryProperties(opts *RegistryScopedTrackOpts) {
  48. p["registry_id"] = opts.RegistryID
  49. }
  50. func (p segmentProperties) addApplicationProperties(opts *ApplicationScopedTrackOpts) {
  51. p["app_name"] = opts.Name
  52. p["app_namespace"] = opts.Namespace
  53. p["chart_name"] = opts.ChartName
  54. }
  55. func (p segmentProperties) addAdditionalProperties(props map[string]interface{}) {
  56. for key, val := range props {
  57. p[key] = val
  58. }
  59. }
  60. // UserCreateTrackOpts are the options for creating a track when a user is created
  61. type UserCreateTrackOpts struct {
  62. *UserScopedTrackOpts
  63. Email string
  64. FirstName string
  65. LastName string
  66. CompanyName string
  67. }
  68. // UserCreateTrack returns a track for when a user is created
  69. func UserCreateTrack(opts *UserCreateTrackOpts) segmentTrack {
  70. additionalProps := make(map[string]interface{})
  71. additionalProps["email"] = opts.Email
  72. additionalProps["name"] = opts.FirstName + " " + opts.LastName
  73. additionalProps["company"] = opts.CompanyName
  74. return getSegmentUserTrack(
  75. opts.UserScopedTrackOpts,
  76. getDefaultSegmentTrack(additionalProps, UserCreate),
  77. )
  78. }
  79. // UserCreateTrackOpts are the options for creating a track when a user's email is verified
  80. type UserVerifyEmailTrackOpts struct {
  81. *UserScopedTrackOpts
  82. Email string
  83. }
  84. // UserVerifyEmailTrack returns a track for when a user's email is verified
  85. func UserVerifyEmailTrack(opts *UserVerifyEmailTrackOpts) segmentTrack {
  86. additionalProps := make(map[string]interface{})
  87. additionalProps["email"] = opts.Email
  88. return getSegmentUserTrack(
  89. opts.UserScopedTrackOpts,
  90. getDefaultSegmentTrack(additionalProps, UserVerifyEmail),
  91. )
  92. }
  93. // ProjectCreateTrackOpts are the options for creating a track when a project is created
  94. type ProjectCreateTrackOpts struct {
  95. *ProjectScopedTrackOpts
  96. }
  97. // ProjectCreateTrack returns a track for when a project is created
  98. func ProjectCreateTrack(opts *ProjectCreateTrackOpts) segmentTrack {
  99. additionalProps := make(map[string]interface{})
  100. return getSegmentProjectTrack(
  101. opts.ProjectScopedTrackOpts,
  102. getDefaultSegmentTrack(additionalProps, ProjectCreate),
  103. )
  104. }
  105. // ClusterProvisioningStartTrackOpts are the options for creating a track when a cluster
  106. // has started provisioning
  107. type ClusterProvisioningStartTrackOpts struct {
  108. // note that this is a project-scoped track, since the cluster has not been created yet
  109. *ProjectScopedTrackOpts
  110. ClusterType types.InfraKind
  111. InfraID uint
  112. }
  113. // ClusterProvisioningStartTrack returns a track for when a cluster
  114. // has started provisioning
  115. func ClusterProvisioningStartTrack(opts *ClusterProvisioningStartTrackOpts) segmentTrack {
  116. additionalProps := make(map[string]interface{})
  117. additionalProps["cluster_type"] = opts.ClusterType
  118. additionalProps["infra_id"] = opts.InfraID
  119. return getSegmentProjectTrack(
  120. opts.ProjectScopedTrackOpts,
  121. getDefaultSegmentTrack(additionalProps, ClusterProvisioningStart),
  122. )
  123. }
  124. // ClusterProvisioningErrorTrackOpts are the options for creating a track when a cluster
  125. // has experienced a provisioning error
  126. type ClusterProvisioningErrorTrackOpts struct {
  127. // note that this is a project-scoped track, since the cluster has not been created yet
  128. *ProjectScopedTrackOpts
  129. ClusterType types.InfraKind
  130. InfraID uint
  131. }
  132. // ClusterProvisioningErrorTrack returns a track for when a cluster
  133. // has experienced a provisioning error
  134. func ClusterProvisioningErrorTrack(opts *ClusterProvisioningErrorTrackOpts) segmentTrack {
  135. additionalProps := make(map[string]interface{})
  136. additionalProps["cluster_type"] = opts.ClusterType
  137. additionalProps["infra_id"] = opts.InfraID
  138. return getSegmentProjectTrack(
  139. opts.ProjectScopedTrackOpts,
  140. getDefaultSegmentTrack(additionalProps, ClusterProvisioningError),
  141. )
  142. }
  143. // ClusterProvisioningSuccessTrackOpts are the options for creating a track when a cluster
  144. // has successfully provisioned
  145. type ClusterProvisioningSuccessTrackOpts struct {
  146. *ClusterScopedTrackOpts
  147. ClusterType types.InfraKind
  148. InfraID uint
  149. }
  150. // ClusterProvisioningSuccessTrack returns a new track for when a cluster
  151. // has successfully provisioned
  152. func ClusterProvisioningSuccessTrack(opts *ClusterProvisioningSuccessTrackOpts) segmentTrack {
  153. additionalProps := make(map[string]interface{})
  154. additionalProps["cluster_type"] = opts.ClusterType
  155. additionalProps["infra_id"] = opts.InfraID
  156. return getSegmentClusterTrack(
  157. opts.ClusterScopedTrackOpts,
  158. getDefaultSegmentTrack(additionalProps, ClusterProvisioningSuccess),
  159. )
  160. }
  161. // ClusterConnectionStartTrackOpts are the options for creating a track when a cluster
  162. // connection has started
  163. type ClusterConnectionStartTrackOpts struct {
  164. // note that this is a project-scoped track, since the cluster has not been created yet
  165. *ProjectScopedTrackOpts
  166. ClusterCandidateID uint
  167. }
  168. // ClusterConnectionStartTrack returns a new track for when a cluster
  169. // connection has started
  170. func ClusterConnectionStartTrack(opts *ClusterConnectionStartTrackOpts) segmentTrack {
  171. additionalProps := make(map[string]interface{})
  172. additionalProps["cc_id"] = opts.ClusterCandidateID
  173. return getSegmentProjectTrack(
  174. opts.ProjectScopedTrackOpts,
  175. getDefaultSegmentTrack(additionalProps, ClusterConnectionStart),
  176. )
  177. }
  178. // ClusterConnectionSuccessTrackOpts are the options for creating a track when a cluster
  179. // connection has finished
  180. type ClusterConnectionSuccessTrackOpts struct {
  181. *ClusterScopedTrackOpts
  182. ClusterCandidateID uint
  183. }
  184. // ClusterConnectionSuccessTrack returns a new track for when a cluster
  185. // connection has finished
  186. func ClusterConnectionSuccessTrack(opts *ClusterConnectionSuccessTrackOpts) segmentTrack {
  187. additionalProps := make(map[string]interface{})
  188. additionalProps["cc_id"] = opts.ClusterCandidateID
  189. return getSegmentClusterTrack(
  190. opts.ClusterScopedTrackOpts,
  191. getDefaultSegmentTrack(additionalProps, ClusterConnectionSuccess),
  192. )
  193. }
  194. // RegistryConnectionStartTrackOpts are the options for creating a track when a registry
  195. // connection has started
  196. type RegistryConnectionStartTrackOpts struct {
  197. // note that this is a project-scoped track, since the cluster has not been created yet
  198. *ProjectScopedTrackOpts
  199. // a random id assigned to this connection request
  200. FlowID string
  201. }
  202. // RegistryConnectionStartTrack returns a new track for when a registry
  203. // connection has started
  204. func RegistryConnectionStartTrack(opts *RegistryConnectionStartTrackOpts) segmentTrack {
  205. additionalProps := make(map[string]interface{})
  206. additionalProps["flow_id"] = opts.FlowID
  207. return getSegmentProjectTrack(
  208. opts.ProjectScopedTrackOpts,
  209. getDefaultSegmentTrack(additionalProps, RegistryConnectionStart),
  210. )
  211. }
  212. // RegistryConnectionSuccessTrackOpts are the options for creating a track when a registry
  213. // connection has completed
  214. type RegistryConnectionSuccessTrackOpts struct {
  215. *RegistryScopedTrackOpts
  216. // a random id assigned to this connection request
  217. FlowID string
  218. }
  219. // RegistryConnectionSuccessTrack returns a new track for when a registry
  220. // connection has completed
  221. func RegistryConnectionSuccessTrack(opts *RegistryConnectionSuccessTrackOpts) segmentTrack {
  222. additionalProps := make(map[string]interface{})
  223. additionalProps["flow_id"] = opts.FlowID
  224. return getSegmentRegistryTrack(
  225. opts.RegistryScopedTrackOpts,
  226. getDefaultSegmentTrack(additionalProps, RegistryConnectionSuccess),
  227. )
  228. }
  229. // GithubConnectionStartTrackOpts are the options for creating a track when a github account
  230. // connection has started
  231. type GithubConnectionStartTrackOpts struct {
  232. // note that this is a user-scoped track, since github repos are tied to the user
  233. *UserScopedTrackOpts
  234. }
  235. // GithubConnectionStartTrack returns a new track for when a github account
  236. // connection has started
  237. func GithubConnectionStartTrack(opts *GithubConnectionStartTrackOpts) segmentTrack {
  238. additionalProps := make(map[string]interface{})
  239. return getSegmentUserTrack(
  240. opts.UserScopedTrackOpts,
  241. getDefaultSegmentTrack(additionalProps, GithubConnectionStart),
  242. )
  243. }
  244. // GithubConnectionSuccessTrackOpts are the options for creating a track when a github account
  245. // connection has completed
  246. type GithubConnectionSuccessTrackOpts struct {
  247. // note that this is a user-scoped track, since github repos are tied to the user
  248. *UserScopedTrackOpts
  249. }
  250. // GithubConnectionSuccessTrack returns a new track when a github account
  251. // connection has completed
  252. func GithubConnectionSuccessTrack(opts *GithubConnectionSuccessTrackOpts) segmentTrack {
  253. additionalProps := make(map[string]interface{})
  254. return getSegmentUserTrack(
  255. opts.UserScopedTrackOpts,
  256. getDefaultSegmentTrack(additionalProps, GithubConnectionSuccess),
  257. )
  258. }
  259. // ApplicationLaunchStartTrackOpts are the options for creating a track when an application
  260. // launch has started
  261. type ApplicationLaunchStartTrackOpts struct {
  262. *ClusterScopedTrackOpts
  263. FlowID string
  264. }
  265. // ApplicationLaunchStartTrack returns a new track for when an application
  266. // launch has started
  267. func ApplicationLaunchStartTrack(opts *ApplicationLaunchStartTrackOpts) segmentTrack {
  268. additionalProps := make(map[string]interface{})
  269. additionalProps["flow_id"] = opts.FlowID
  270. return getSegmentClusterTrack(
  271. opts.ClusterScopedTrackOpts,
  272. getDefaultSegmentTrack(additionalProps, ApplicationLaunchStart),
  273. )
  274. }
  275. // ApplicationLaunchSuccessTrackOpts are the options for creating a track when an application
  276. // launch has completed
  277. type ApplicationLaunchSuccessTrackOpts struct {
  278. *ApplicationScopedTrackOpts
  279. FlowID string
  280. }
  281. // ApplicationLaunchSuccessTrack returns a new track for when an application
  282. // launch has completed
  283. func ApplicationLaunchSuccessTrack(opts *ApplicationLaunchSuccessTrackOpts) segmentTrack {
  284. additionalProps := make(map[string]interface{})
  285. additionalProps["flow_id"] = opts.FlowID
  286. return getSegmentApplicationTrack(
  287. opts.ApplicationScopedTrackOpts,
  288. getDefaultSegmentTrack(additionalProps, ApplicationLaunchSuccess),
  289. )
  290. }
  291. // ApplicationDeploymentWebhookTrackOpts are the options for creating a track when an application
  292. // launch has completed from a webhook
  293. type ApplicationDeploymentWebhookTrackOpts struct {
  294. *ApplicationScopedTrackOpts
  295. ImageURI string
  296. }
  297. // ApplicationDeploymentWebhookTrack returns a new track for when an application
  298. // launch has completed from a webhook
  299. func ApplicationDeploymentWebhookTrack(opts *ApplicationDeploymentWebhookTrackOpts) segmentTrack {
  300. additionalProps := make(map[string]interface{})
  301. additionalProps["image_uri"] = opts.ImageURI
  302. return getSegmentApplicationTrack(
  303. opts.ApplicationScopedTrackOpts,
  304. getDefaultSegmentTrack(additionalProps, ApplicationDeploymentWebhook),
  305. )
  306. }
  307. // RegistryProvisioningStartTrackOpts are the options for creating a track when a registry
  308. // provisioning has started
  309. type RegistryProvisioningStartTrackOpts struct {
  310. // note that this is a project-scoped track, since the registry has not been created yet
  311. *ProjectScopedTrackOpts
  312. RegistryType types.InfraKind
  313. InfraID uint
  314. }
  315. // RegistryProvisioningStartTrack returns a new track for when a registry
  316. // provisioning has started
  317. func RegistryProvisioningStartTrack(opts *RegistryProvisioningStartTrackOpts) segmentTrack {
  318. additionalProps := make(map[string]interface{})
  319. additionalProps["registry_type"] = opts.RegistryType
  320. additionalProps["infra_id"] = opts.InfraID
  321. return getSegmentProjectTrack(
  322. opts.ProjectScopedTrackOpts,
  323. getDefaultSegmentTrack(additionalProps, RegistryProvisioningStart),
  324. )
  325. }
  326. // RegistryProvisioningErrorTrackOpts are the options for creating a track when a registry
  327. // provisioning has failed
  328. type RegistryProvisioningErrorTrackOpts struct {
  329. // note that this is a project-scoped track, since the registry has not been created yet
  330. *ProjectScopedTrackOpts
  331. RegistryType types.InfraKind
  332. InfraID uint
  333. }
  334. // RegistryProvisioningErrorTrack returns a new track for when a registry
  335. // provisioning has failed
  336. func RegistryProvisioningErrorTrack(opts *RegistryProvisioningErrorTrackOpts) segmentTrack {
  337. additionalProps := make(map[string]interface{})
  338. additionalProps["registry_type"] = opts.RegistryType
  339. additionalProps["infra_id"] = opts.InfraID
  340. return getSegmentProjectTrack(
  341. opts.ProjectScopedTrackOpts,
  342. getDefaultSegmentTrack(additionalProps, RegistryProvisioningError),
  343. )
  344. }
  345. // RegistryProvisioningSuccessTrackOpts are the options for creating a track when a registry
  346. // provisioning has completed
  347. type RegistryProvisioningSuccessTrackOpts struct {
  348. *RegistryScopedTrackOpts
  349. RegistryType types.InfraKind
  350. InfraID uint
  351. }
  352. // RegistryProvisioningSuccessTrack returns a new track for when a registry
  353. // provisioning has completed
  354. func RegistryProvisioningSuccessTrack(opts *RegistryProvisioningSuccessTrackOpts) segmentTrack {
  355. additionalProps := make(map[string]interface{})
  356. additionalProps["registry_type"] = opts.RegistryType
  357. additionalProps["infra_id"] = opts.InfraID
  358. return getSegmentRegistryTrack(
  359. opts.RegistryScopedTrackOpts,
  360. getDefaultSegmentTrack(additionalProps, RegistryProvisioningSuccess),
  361. )
  362. }
  363. // ClusterDestroyingStartTrackOpts are the options for creating a track when a cluster
  364. // has started destroying
  365. type ClusterDestroyingStartTrackOpts struct {
  366. *ClusterScopedTrackOpts
  367. ClusterType types.InfraKind
  368. InfraID uint
  369. }
  370. // ClusterDestroyingStartTrack returns a track for when a cluster
  371. // has started destroying
  372. func ClusterDestroyingStartTrack(opts *ClusterDestroyingStartTrackOpts) segmentTrack {
  373. additionalProps := make(map[string]interface{})
  374. additionalProps["cluster_type"] = opts.ClusterType
  375. additionalProps["infra_id"] = opts.InfraID
  376. return getSegmentClusterTrack(
  377. opts.ClusterScopedTrackOpts,
  378. getDefaultSegmentTrack(additionalProps, ClusterDestroyingStart),
  379. )
  380. }
  381. // ClusterDestroyingSuccessTrackOpts are the options for creating a track when a cluster
  382. // has successfully provisioned
  383. type ClusterDestroyingSuccessTrackOpts struct {
  384. *ClusterScopedTrackOpts
  385. ClusterType types.InfraKind
  386. InfraID uint
  387. }
  388. // ClusterDestroyingSuccessTrack returns a new track for when a cluster
  389. // has successfully provisioned
  390. func ClusterDestroyingSuccessTrack(opts *ClusterDestroyingSuccessTrackOpts) segmentTrack {
  391. additionalProps := make(map[string]interface{})
  392. additionalProps["cluster_type"] = opts.ClusterType
  393. additionalProps["infra_id"] = opts.InfraID
  394. return getSegmentClusterTrack(
  395. opts.ClusterScopedTrackOpts,
  396. getDefaultSegmentTrack(additionalProps, ClusterDestroyingSuccess),
  397. )
  398. }