tracks.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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. }
  65. // UserCreateTrack returns a track for when a user is created
  66. func UserCreateTrack(opts *UserCreateTrackOpts) segmentTrack {
  67. additionalProps := make(map[string]interface{})
  68. additionalProps["email"] = opts.Email
  69. return getSegmentUserTrack(
  70. opts.UserScopedTrackOpts,
  71. getDefaultSegmentTrack(additionalProps, UserCreate),
  72. )
  73. }
  74. // UserCreateTrackOpts are the options for creating a track when a user's email is verified
  75. type UserVerifyEmailTrackOpts struct {
  76. *UserScopedTrackOpts
  77. Email string
  78. }
  79. // UserVerifyEmailTrack returns a track for when a user's email is verified
  80. func UserVerifyEmailTrack(opts *UserVerifyEmailTrackOpts) segmentTrack {
  81. additionalProps := make(map[string]interface{})
  82. additionalProps["email"] = opts.Email
  83. return getSegmentUserTrack(
  84. opts.UserScopedTrackOpts,
  85. getDefaultSegmentTrack(additionalProps, UserVerifyEmail),
  86. )
  87. }
  88. // ProjectCreateTrackOpts are the options for creating a track when a project is created
  89. type ProjectCreateTrackOpts struct {
  90. *ProjectScopedTrackOpts
  91. }
  92. // ProjectCreateTrack returns a track for when a project is created
  93. func ProjectCreateTrack(opts *ProjectCreateTrackOpts) segmentTrack {
  94. additionalProps := make(map[string]interface{})
  95. return getSegmentProjectTrack(
  96. opts.ProjectScopedTrackOpts,
  97. getDefaultSegmentTrack(additionalProps, ProjectCreate),
  98. )
  99. }
  100. // ClusterProvisioningStartTrackOpts are the options for creating a track when a cluster
  101. // has started provisioning
  102. type ClusterProvisioningStartTrackOpts struct {
  103. // note that this is a project-scoped track, since the cluster has not been created yet
  104. *ProjectScopedTrackOpts
  105. ClusterType types.InfraKind
  106. InfraID uint
  107. }
  108. // ClusterProvisioningStartTrack returns a track for when a cluster
  109. // has started provisioning
  110. func ClusterProvisioningStartTrack(opts *ClusterProvisioningStartTrackOpts) segmentTrack {
  111. additionalProps := make(map[string]interface{})
  112. additionalProps["cluster_type"] = opts.ClusterType
  113. additionalProps["infra_id"] = opts.InfraID
  114. return getSegmentProjectTrack(
  115. opts.ProjectScopedTrackOpts,
  116. getDefaultSegmentTrack(additionalProps, ClusterProvisioningStart),
  117. )
  118. }
  119. // ClusterProvisioningErrorTrackOpts are the options for creating a track when a cluster
  120. // has experienced a provisioning error
  121. type ClusterProvisioningErrorTrackOpts struct {
  122. // note that this is a project-scoped track, since the cluster has not been created yet
  123. *ProjectScopedTrackOpts
  124. ClusterType types.InfraKind
  125. InfraID uint
  126. }
  127. // ClusterProvisioningErrorTrack returns a track for when a cluster
  128. // has experienced a provisioning error
  129. func ClusterProvisioningErrorTrack(opts *ClusterProvisioningErrorTrackOpts) segmentTrack {
  130. additionalProps := make(map[string]interface{})
  131. additionalProps["cluster_type"] = opts.ClusterType
  132. additionalProps["infra_id"] = opts.InfraID
  133. return getSegmentProjectTrack(
  134. opts.ProjectScopedTrackOpts,
  135. getDefaultSegmentTrack(additionalProps, ClusterProvisioningError),
  136. )
  137. }
  138. // ClusterProvisioningSuccessTrackOpts are the options for creating a track when a cluster
  139. // has successfully provisioned
  140. type ClusterProvisioningSuccessTrackOpts struct {
  141. *ClusterScopedTrackOpts
  142. ClusterType types.InfraKind
  143. InfraID uint
  144. }
  145. // ClusterProvisioningSuccessTrack returns a new track for when a cluster
  146. // has successfully provisioned
  147. func ClusterProvisioningSuccessTrack(opts *ClusterProvisioningSuccessTrackOpts) segmentTrack {
  148. additionalProps := make(map[string]interface{})
  149. additionalProps["cluster_type"] = opts.ClusterType
  150. additionalProps["infra_id"] = opts.InfraID
  151. return getSegmentClusterTrack(
  152. opts.ClusterScopedTrackOpts,
  153. getDefaultSegmentTrack(additionalProps, ClusterProvisioningSuccess),
  154. )
  155. }
  156. // ClusterConnectionStartTrackOpts are the options for creating a track when a cluster
  157. // connection has started
  158. type ClusterConnectionStartTrackOpts struct {
  159. // note that this is a project-scoped track, since the cluster has not been created yet
  160. *ProjectScopedTrackOpts
  161. ClusterCandidateID uint
  162. }
  163. // ClusterConnectionStartTrack returns a new track for when a cluster
  164. // connection has started
  165. func ClusterConnectionStartTrack(opts *ClusterConnectionStartTrackOpts) segmentTrack {
  166. additionalProps := make(map[string]interface{})
  167. additionalProps["cc_id"] = opts.ClusterCandidateID
  168. return getSegmentProjectTrack(
  169. opts.ProjectScopedTrackOpts,
  170. getDefaultSegmentTrack(additionalProps, ClusterConnectionStart),
  171. )
  172. }
  173. // ClusterConnectionSuccessTrackOpts are the options for creating a track when a cluster
  174. // connection has finished
  175. type ClusterConnectionSuccessTrackOpts struct {
  176. *ClusterScopedTrackOpts
  177. ClusterCandidateID uint
  178. }
  179. // ClusterConnectionSuccessTrack returns a new track for when a cluster
  180. // connection has finished
  181. func ClusterConnectionSuccessTrack(opts *ClusterConnectionSuccessTrackOpts) segmentTrack {
  182. additionalProps := make(map[string]interface{})
  183. additionalProps["cc_id"] = opts.ClusterCandidateID
  184. return getSegmentClusterTrack(
  185. opts.ClusterScopedTrackOpts,
  186. getDefaultSegmentTrack(additionalProps, ClusterConnectionSuccess),
  187. )
  188. }
  189. // RegistryConnectionStartTrackOpts are the options for creating a track when a registry
  190. // connection has started
  191. type RegistryConnectionStartTrackOpts struct {
  192. // note that this is a project-scoped track, since the cluster has not been created yet
  193. *ProjectScopedTrackOpts
  194. // a random id assigned to this connection request
  195. FlowID string
  196. }
  197. // RegistryConnectionStartTrack returns a new track for when a registry
  198. // connection has started
  199. func RegistryConnectionStartTrack(opts *RegistryConnectionStartTrackOpts) segmentTrack {
  200. additionalProps := make(map[string]interface{})
  201. additionalProps["flow_id"] = opts.FlowID
  202. return getSegmentProjectTrack(
  203. opts.ProjectScopedTrackOpts,
  204. getDefaultSegmentTrack(additionalProps, RegistryConnectionStart),
  205. )
  206. }
  207. // RegistryConnectionSuccessTrackOpts are the options for creating a track when a registry
  208. // connection has completed
  209. type RegistryConnectionSuccessTrackOpts struct {
  210. *RegistryScopedTrackOpts
  211. // a random id assigned to this connection request
  212. FlowID string
  213. }
  214. // RegistryConnectionSuccessTrack returns a new track for when a registry
  215. // connection has completed
  216. func RegistryConnectionSuccessTrack(opts *RegistryConnectionSuccessTrackOpts) segmentTrack {
  217. additionalProps := make(map[string]interface{})
  218. additionalProps["flow_id"] = opts.FlowID
  219. return getSegmentRegistryTrack(
  220. opts.RegistryScopedTrackOpts,
  221. getDefaultSegmentTrack(additionalProps, RegistryConnectionSuccess),
  222. )
  223. }
  224. // GithubConnectionStartTrackOpts are the options for creating a track when a github account
  225. // connection has started
  226. type GithubConnectionStartTrackOpts struct {
  227. // note that this is a user-scoped track, since github repos are tied to the user
  228. *UserScopedTrackOpts
  229. }
  230. // GithubConnectionStartTrack returns a new track for when a github account
  231. // connection has started
  232. func GithubConnectionStartTrack(opts *GithubConnectionStartTrackOpts) segmentTrack {
  233. additionalProps := make(map[string]interface{})
  234. return getSegmentUserTrack(
  235. opts.UserScopedTrackOpts,
  236. getDefaultSegmentTrack(additionalProps, GithubConnectionStart),
  237. )
  238. }
  239. // GithubConnectionSuccessTrackOpts are the options for creating a track when a github account
  240. // connection has completed
  241. type GithubConnectionSuccessTrackOpts struct {
  242. // note that this is a user-scoped track, since github repos are tied to the user
  243. *UserScopedTrackOpts
  244. }
  245. // GithubConnectionSuccessTrack returns a new track when a github account
  246. // connection has completed
  247. func GithubConnectionSuccessTrack(opts *GithubConnectionSuccessTrackOpts) segmentTrack {
  248. additionalProps := make(map[string]interface{})
  249. return getSegmentUserTrack(
  250. opts.UserScopedTrackOpts,
  251. getDefaultSegmentTrack(additionalProps, GithubConnectionSuccess),
  252. )
  253. }
  254. // ApplicationLaunchStartTrackOpts are the options for creating a track when an application
  255. // launch has started
  256. type ApplicationLaunchStartTrackOpts struct {
  257. *ClusterScopedTrackOpts
  258. FlowID string
  259. }
  260. // ApplicationLaunchStartTrack returns a new track for when an application
  261. // launch has started
  262. func ApplicationLaunchStartTrack(opts *ApplicationLaunchStartTrackOpts) segmentTrack {
  263. additionalProps := make(map[string]interface{})
  264. additionalProps["flow_id"] = opts.FlowID
  265. return getSegmentClusterTrack(
  266. opts.ClusterScopedTrackOpts,
  267. getDefaultSegmentTrack(additionalProps, ApplicationLaunchStart),
  268. )
  269. }
  270. // ApplicationLaunchSuccessTrackOpts are the options for creating a track when an application
  271. // launch has completed
  272. type ApplicationLaunchSuccessTrackOpts struct {
  273. *ApplicationScopedTrackOpts
  274. FlowID string
  275. }
  276. // ApplicationLaunchSuccessTrack returns a new track for when an application
  277. // launch has completed
  278. func ApplicationLaunchSuccessTrack(opts *ApplicationLaunchSuccessTrackOpts) segmentTrack {
  279. additionalProps := make(map[string]interface{})
  280. additionalProps["flow_id"] = opts.FlowID
  281. return getSegmentApplicationTrack(
  282. opts.ApplicationScopedTrackOpts,
  283. getDefaultSegmentTrack(additionalProps, ApplicationLaunchSuccess),
  284. )
  285. }
  286. // ApplicationDeploymentWebhookTrackOpts are the options for creating a track when an application
  287. // launch has completed from a webhook
  288. type ApplicationDeploymentWebhookTrackOpts struct {
  289. *ApplicationScopedTrackOpts
  290. ImageURI string
  291. }
  292. // ApplicationDeploymentWebhookTrack returns a new track for when an application
  293. // launch has completed from a webhook
  294. func ApplicationDeploymentWebhookTrack(opts *ApplicationDeploymentWebhookTrackOpts) segmentTrack {
  295. additionalProps := make(map[string]interface{})
  296. additionalProps["image_uri"] = opts.ImageURI
  297. return getSegmentApplicationTrack(
  298. opts.ApplicationScopedTrackOpts,
  299. getDefaultSegmentTrack(additionalProps, ApplicationDeploymentWebhook),
  300. )
  301. }
  302. // RegistryProvisioningStartTrackOpts are the options for creating a track when a registry
  303. // provisioning has started
  304. type RegistryProvisioningStartTrackOpts struct {
  305. // note that this is a project-scoped track, since the registry has not been created yet
  306. *ProjectScopedTrackOpts
  307. RegistryType types.InfraKind
  308. InfraID uint
  309. }
  310. // RegistryProvisioningStartTrack returns a new track for when a registry
  311. // provisioning has started
  312. func RegistryProvisioningStartTrack(opts *RegistryProvisioningStartTrackOpts) segmentTrack {
  313. additionalProps := make(map[string]interface{})
  314. additionalProps["registry_type"] = opts.RegistryType
  315. additionalProps["infra_id"] = opts.InfraID
  316. return getSegmentProjectTrack(
  317. opts.ProjectScopedTrackOpts,
  318. getDefaultSegmentTrack(additionalProps, RegistryProvisioningStart),
  319. )
  320. }
  321. // RegistryProvisioningErrorTrackOpts are the options for creating a track when a registry
  322. // provisioning has failed
  323. type RegistryProvisioningErrorTrackOpts struct {
  324. // note that this is a project-scoped track, since the registry has not been created yet
  325. *ProjectScopedTrackOpts
  326. RegistryType types.InfraKind
  327. InfraID uint
  328. }
  329. // RegistryProvisioningErrorTrack returns a new track for when a registry
  330. // provisioning has failed
  331. func RegistryProvisioningErrorTrack(opts *RegistryProvisioningErrorTrackOpts) segmentTrack {
  332. additionalProps := make(map[string]interface{})
  333. additionalProps["registry_type"] = opts.RegistryType
  334. additionalProps["infra_id"] = opts.InfraID
  335. return getSegmentProjectTrack(
  336. opts.ProjectScopedTrackOpts,
  337. getDefaultSegmentTrack(additionalProps, RegistryProvisioningError),
  338. )
  339. }
  340. // RegistryProvisioningSuccessTrackOpts are the options for creating a track when a registry
  341. // provisioning has completed
  342. type RegistryProvisioningSuccessTrackOpts struct {
  343. *RegistryScopedTrackOpts
  344. RegistryType types.InfraKind
  345. InfraID uint
  346. }
  347. // RegistryProvisioningSuccessTrack returns a new track for when a registry
  348. // provisioning has completed
  349. func RegistryProvisioningSuccessTrack(opts *RegistryProvisioningSuccessTrackOpts) segmentTrack {
  350. additionalProps := make(map[string]interface{})
  351. additionalProps["registry_type"] = opts.RegistryType
  352. additionalProps["infra_id"] = opts.InfraID
  353. return getSegmentRegistryTrack(
  354. opts.RegistryScopedTrackOpts,
  355. getDefaultSegmentTrack(additionalProps, RegistryProvisioningSuccess),
  356. )
  357. }
  358. // ClusterDestroyingStartTrackOpts are the options for creating a track when a cluster
  359. // has started destroying
  360. type ClusterDestroyingStartTrackOpts struct {
  361. *ClusterScopedTrackOpts
  362. ClusterType types.InfraKind
  363. InfraID uint
  364. }
  365. // ClusterDestroyingStartTrack returns a track for when a cluster
  366. // has started destroying
  367. func ClusterDestroyingStartTrack(opts *ClusterDestroyingStartTrackOpts) segmentTrack {
  368. additionalProps := make(map[string]interface{})
  369. additionalProps["cluster_type"] = opts.ClusterType
  370. additionalProps["infra_id"] = opts.InfraID
  371. return getSegmentClusterTrack(
  372. opts.ClusterScopedTrackOpts,
  373. getDefaultSegmentTrack(additionalProps, ClusterDestroyingStart),
  374. )
  375. }
  376. // ClusterDestroyingSuccessTrackOpts are the options for creating a track when a cluster
  377. // has successfully provisioned
  378. type ClusterDestroyingSuccessTrackOpts struct {
  379. *ClusterScopedTrackOpts
  380. ClusterType types.InfraKind
  381. InfraID uint
  382. }
  383. // ClusterDestroyingSuccessTrack returns a new track for when a cluster
  384. // has successfully provisioned
  385. func ClusterDestroyingSuccessTrack(opts *ClusterDestroyingSuccessTrackOpts) segmentTrack {
  386. additionalProps := make(map[string]interface{})
  387. additionalProps["cluster_type"] = opts.ClusterType
  388. additionalProps["infra_id"] = opts.InfraID
  389. return getSegmentClusterTrack(
  390. opts.ClusterScopedTrackOpts,
  391. getDefaultSegmentTrack(additionalProps, ClusterDestroyingSuccess),
  392. )
  393. }