tracks.go 13 KB

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