From e5addef19bf4d9304d00423244a47709e4f70fd8 Mon Sep 17 00:00:00 2001 From: George Goldberg Date: Mon, 22 Jun 2020 08:35:03 +0100 Subject: [PATCH] MM-23574: Remove Segment. (#14712) * MM-23574: Eliminate Segment. * Update dependencies. * Fix review suggestions. --- app/diagnostics.go | 28 +- app/diagnostics_test.go | 215 +-------- app/server.go | 43 +- go.mod | 1 - go.sum | 2 - utils/subpath.go | 4 +- utils/subpath_test.go | 10 +- .../segmentio/analytics-go/.gitignore | 32 -- .../segmentio/analytics-go/.gitmodules | 6 - .../segmentio/analytics-go/History.md | 88 ---- .../segmentio/analytics-go/License.md | 21 - .../segmentio/analytics-go/Makefile | 31 -- .../segmentio/analytics-go/Readme.md | 55 --- .../segmentio/analytics-go/alias.go | 44 -- .../segmentio/analytics-go/analytics.go | 431 ------------------ .../segmentio/analytics-go/config.go | 173 ------- .../segmentio/analytics-go/context.go | 148 ------ .../segmentio/analytics-go/error.go | 60 --- .../segmentio/analytics-go/executor.go | 53 --- .../segmentio/analytics-go/group.go | 46 -- .../segmentio/analytics-go/identify.go | 37 -- .../segmentio/analytics-go/integrations.go | 44 -- .../github.com/segmentio/analytics-go/json.go | 87 ---- .../segmentio/analytics-go/logger.go | 47 -- .../segmentio/analytics-go/message.go | 131 ------ .../github.com/segmentio/analytics-go/page.go | 38 -- .../segmentio/analytics-go/properties.go | 117 ----- .../segmentio/analytics-go/screen.go | 38 -- .../segmentio/analytics-go/timeout_15.go | 16 - .../segmentio/analytics-go/timeout_16.go | 10 - .../segmentio/analytics-go/track.go | 46 -- .../segmentio/analytics-go/traits.go | 89 ---- vendor/modules.txt | 3 - web/handlers.go | 2 +- web/handlers_test.go | 10 +- 35 files changed, 22 insertions(+), 2184 deletions(-) delete mode 100644 vendor/github.com/segmentio/analytics-go/.gitignore delete mode 100644 vendor/github.com/segmentio/analytics-go/.gitmodules delete mode 100644 vendor/github.com/segmentio/analytics-go/History.md delete mode 100644 vendor/github.com/segmentio/analytics-go/License.md delete mode 100644 vendor/github.com/segmentio/analytics-go/Makefile delete mode 100644 vendor/github.com/segmentio/analytics-go/Readme.md delete mode 100644 vendor/github.com/segmentio/analytics-go/alias.go delete mode 100644 vendor/github.com/segmentio/analytics-go/analytics.go delete mode 100644 vendor/github.com/segmentio/analytics-go/config.go delete mode 100644 vendor/github.com/segmentio/analytics-go/context.go delete mode 100644 vendor/github.com/segmentio/analytics-go/error.go delete mode 100644 vendor/github.com/segmentio/analytics-go/executor.go delete mode 100644 vendor/github.com/segmentio/analytics-go/group.go delete mode 100644 vendor/github.com/segmentio/analytics-go/identify.go delete mode 100644 vendor/github.com/segmentio/analytics-go/integrations.go delete mode 100644 vendor/github.com/segmentio/analytics-go/json.go delete mode 100644 vendor/github.com/segmentio/analytics-go/logger.go delete mode 100644 vendor/github.com/segmentio/analytics-go/message.go delete mode 100644 vendor/github.com/segmentio/analytics-go/page.go delete mode 100644 vendor/github.com/segmentio/analytics-go/properties.go delete mode 100644 vendor/github.com/segmentio/analytics-go/screen.go delete mode 100644 vendor/github.com/segmentio/analytics-go/timeout_15.go delete mode 100644 vendor/github.com/segmentio/analytics-go/timeout_16.go delete mode 100644 vendor/github.com/segmentio/analytics-go/track.go delete mode 100644 vendor/github.com/segmentio/analytics-go/traits.go diff --git a/app/diagnostics.go b/app/diagnostics.go index fda944ac2c..3daaf2469e 100644 --- a/app/diagnostics.go +++ b/app/diagnostics.go @@ -8,16 +8,13 @@ import ( "runtime" "strings" - rudder "github.com/rudderlabs/analytics-go" - "github.com/segmentio/analytics-go" - "github.com/mattermost/mattermost-server/v5/mlog" "github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/store" + rudder "github.com/rudderlabs/analytics-go" ) const ( - SEGMENT_KEY = "placeholder_segment_key" RUDDER_KEY = "placeholder_rudder_key" RUDDER_DATAPLANE_URL = "placeholder_rudder_dataplane_url" @@ -75,21 +72,8 @@ func (s *Server) SendDailyDiagnostics() { } func (s *Server) sendDailyDiagnostics(override bool) { - if *s.Config().LogSettings.EnableDiagnostics && s.IsLeader() && (!strings.Contains(SEGMENT_KEY, "placeholder") || override) { - s.initDiagnostics("") - s.trackActivity() - s.trackConfig() - s.trackLicense() - s.trackPlugins() - s.trackServer() - s.trackPermissions() - s.trackElasticsearch() - s.trackGroups() - s.trackChannelModeration() - } - if *s.Config().LogSettings.EnableDiagnostics && s.IsLeader() && ((!strings.Contains(RUDDER_KEY, "placeholder") && !strings.Contains(RUDDER_DATAPLANE_URL, "placeholder")) || override) { - s.initRudder(RUDDER_DATAPLANE_URL) + s.initDiagnostics(RUDDER_DATAPLANE_URL) s.trackActivity() s.trackConfig() s.trackLicense() @@ -103,14 +87,6 @@ func (s *Server) sendDailyDiagnostics(override bool) { } func (s *Server) SendDiagnostic(event string, properties map[string]interface{}) { - if s.diagnosticClient != nil { - s.diagnosticClient.Enqueue(analytics.Track{ - Event: event, - UserId: s.diagnosticId, - Properties: properties, - }) - } - if s.rudderClient != nil { s.rudderClient.Enqueue(rudder.Track{ Event: event, diff --git a/app/diagnostics_test.go b/app/diagnostics_test.go index 5b9681a7ad..cda58cc122 100644 --- a/app/diagnostics_test.go +++ b/app/diagnostics_test.go @@ -63,219 +63,6 @@ func TestPluginVersion(t *testing.T) { assert.Empty(t, pluginVersion(plugins, "unknown.plugin")) } -func TestSegmentDiagnostics(t *testing.T) { - if testing.Short() { - t.SkipNow() - } - - th := SetupWithCustomConfig(t, func(config *model.Config) { - *config.PluginSettings.Enable = false - }) - defer th.TearDown() - - type payload struct { - MessageId string - SentAt time.Time - Batch []struct { - MessageId string - UserId string - Event string - Timestamp time.Time - Properties map[string]interface{} - } - Context struct { - Library struct { - Name string - Version string - } - } - } - - data := make(chan payload, 100) - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, err := ioutil.ReadAll(r.Body) - require.NoError(t, err) - - var p payload - err = json.Unmarshal(body, &p) - require.NoError(t, err) - - data <- p - })) - defer server.Close() - - diagnosticID := "test-diagnostic-id-12345" - th.App.SetDiagnosticId(diagnosticID) - th.Server.initDiagnostics(server.URL) - - assertPayload := func(t *testing.T, actual payload, event string, properties map[string]interface{}) { - assert.NotEmpty(t, actual.MessageId) - assert.False(t, actual.SentAt.IsZero()) - if assert.Len(t, actual.Batch, 1) { - assert.NotEmpty(t, actual.Batch[0].MessageId, "message id should not be empty") - assert.Equal(t, diagnosticID, actual.Batch[0].UserId) - if event != "" { - assert.Equal(t, event, actual.Batch[0].Event) - } - assert.False(t, actual.Batch[0].Timestamp.IsZero(), "batch timestamp should not be the zero value") - if properties != nil { - assert.Equal(t, properties, actual.Batch[0].Properties) - } - } - assert.Equal(t, "analytics-go", actual.Context.Library.Name) - assert.Equal(t, "3.0.0", actual.Context.Library.Version) - } - - // Should send a client identify message - select { - case identifyMessage := <-data: - assertPayload(t, identifyMessage, "", nil) - case <-time.After(time.Second * 1): - require.Fail(t, "Did not receive ID message") - } - - t.Run("Send", func(t *testing.T) { - testValue := "test-send-value-6789" - th.App.Srv().SendDiagnostic("Testing Diagnostic", map[string]interface{}{ - "hey": testValue, - }) - select { - case result := <-data: - assertPayload(t, result, "Testing Diagnostic", map[string]interface{}{ - "hey": testValue, - }) - case <-time.After(time.Second * 1): - require.Fail(t, "Did not receive diagnostic") - } - }) - - // Plugins remain disabled at this point - t.Run("SendDailyDiagnosticsPluginsDisabled", func(t *testing.T) { - th.App.Srv().sendDailyDiagnostics(true) - - var info []string - // Collect the info sent. - Loop: - for { - select { - case result := <-data: - assertPayload(t, result, "", nil) - info = append(info, result.Batch[0].Event) - case <-time.After(time.Second * 1): - break Loop - } - } - - for _, item := range []string{ - TRACK_CONFIG_SERVICE, - TRACK_CONFIG_TEAM, - TRACK_CONFIG_SQL, - TRACK_CONFIG_LOG, - TRACK_CONFIG_AUDIT, - TRACK_CONFIG_NOTIFICATION_LOG, - TRACK_CONFIG_FILE, - TRACK_CONFIG_RATE, - TRACK_CONFIG_EMAIL, - TRACK_CONFIG_PRIVACY, - TRACK_CONFIG_OAUTH, - TRACK_CONFIG_LDAP, - TRACK_CONFIG_COMPLIANCE, - TRACK_CONFIG_LOCALIZATION, - TRACK_CONFIG_SAML, - TRACK_CONFIG_PASSWORD, - TRACK_CONFIG_CLUSTER, - TRACK_CONFIG_METRICS, - TRACK_CONFIG_SUPPORT, - TRACK_CONFIG_NATIVEAPP, - TRACK_CONFIG_EXPERIMENTAL, - TRACK_CONFIG_ANALYTICS, - TRACK_CONFIG_PLUGIN, - TRACK_ACTIVITY, - TRACK_SERVER, - TRACK_CONFIG_MESSAGE_EXPORT, - // TRACK_PLUGINS, - } { - require.Contains(t, info, item) - } - }) - - // Enable plugins for the remainder of the tests. - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true }) - - t.Run("SendDailyDiagnostics", func(t *testing.T) { - th.App.Srv().sendDailyDiagnostics(true) - - var info []string - // Collect the info sent. - Loop: - for { - select { - case result := <-data: - assertPayload(t, result, "", nil) - info = append(info, result.Batch[0].Event) - case <-time.After(time.Second * 1): - break Loop - } - } - - for _, item := range []string{ - TRACK_CONFIG_SERVICE, - TRACK_CONFIG_TEAM, - TRACK_CONFIG_SQL, - TRACK_CONFIG_LOG, - TRACK_CONFIG_AUDIT, - TRACK_CONFIG_NOTIFICATION_LOG, - TRACK_CONFIG_FILE, - TRACK_CONFIG_RATE, - TRACK_CONFIG_EMAIL, - TRACK_CONFIG_PRIVACY, - TRACK_CONFIG_OAUTH, - TRACK_CONFIG_LDAP, - TRACK_CONFIG_COMPLIANCE, - TRACK_CONFIG_LOCALIZATION, - TRACK_CONFIG_SAML, - TRACK_CONFIG_PASSWORD, - TRACK_CONFIG_CLUSTER, - TRACK_CONFIG_METRICS, - TRACK_CONFIG_SUPPORT, - TRACK_CONFIG_NATIVEAPP, - TRACK_CONFIG_EXPERIMENTAL, - TRACK_CONFIG_ANALYTICS, - TRACK_CONFIG_PLUGIN, - TRACK_ACTIVITY, - TRACK_SERVER, - TRACK_CONFIG_MESSAGE_EXPORT, - TRACK_PLUGINS, - } { - require.Contains(t, info, item) - } - }) - - t.Run("SendDailyDiagnosticsNoSegmentKey", func(t *testing.T) { - th.App.Srv().SendDailyDiagnostics() - - select { - case <-data: - require.Fail(t, "Should not send diagnostics when the segment key is not set") - case <-time.After(time.Second * 1): - // Did not receive diagnostics - } - }) - - t.Run("SendDailyDiagnosticsDisabled", func(t *testing.T) { - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.LogSettings.EnableDiagnostics = false }) - - th.App.Srv().sendDailyDiagnostics(true) - - select { - case <-data: - require.Fail(t, "Should not send diagnostics when they are disabled") - case <-time.After(time.Second * 1): - // Did not receive diagnostics - } - }) -} - func TestRudderDiagnostics(t *testing.T) { if testing.Short() { t.SkipNow() @@ -319,7 +106,7 @@ func TestRudderDiagnostics(t *testing.T) { diagnosticID := "test-diagnostic-id-12345" th.App.SetDiagnosticId(diagnosticID) - th.Server.initRudder(server.URL) + th.Server.initDiagnostics(server.URL) assertPayload := func(t *testing.T, actual payload, event string, properties map[string]interface{}) { t.Helper() diff --git a/app/server.go b/app/server.go index 664357f6aa..9aeec92bdc 100644 --- a/app/server.go +++ b/app/server.go @@ -24,7 +24,6 @@ import ( "github.com/pkg/errors" "github.com/rs/cors" rudder "github.com/rudderlabs/analytics-go" - analytics "github.com/segmentio/analytics-go" "github.com/throttled/throttled" "golang.org/x/crypto/acme/autocert" @@ -132,9 +131,8 @@ type Server struct { clientConfigHash atomic.Value limitedClientConfig atomic.Value - diagnosticId string - diagnosticClient analytics.Client - rudderClient rudder.Client + diagnosticId string + rudderClient rudder.Client phase2PermissionsMigrationComplete bool @@ -1158,26 +1156,8 @@ func (s *Server) stopSearchEngine() { } } +// initDiagnostics initialises the Rudder client for the diagnostics system. func (s *Server) initDiagnostics(endpoint string) { - if s.diagnosticClient == nil { - config := analytics.Config{} - config.Logger = analytics.StdLogger(s.Log.StdLog(mlog.String("source", "segment"))) - // For testing - if endpoint != "" { - config.Endpoint = endpoint - config.Verbose = true - config.BatchSize = 1 - } - client, _ := analytics.NewWithConfig(SEGMENT_KEY, config) - client.Enqueue(analytics.Identify{ - UserId: s.diagnosticId, - }) - - s.diagnosticClient = client - } -} - -func (s *Server) initRudder(endpoint string) { if s.rudderClient == nil { config := rudder.Config{} config.Logger = rudder.StdLogger(s.Log.StdLog(mlog.String("source", "rudder"))) @@ -1200,24 +1180,13 @@ func (s *Server) initRudder(endpoint string) { } } -// shutdownDiagnostics closes the diagnostic client. +// shutdownDiagnostics closes the diagnostics system Rudder client. func (s *Server) shutdownDiagnostics() error { - var segmentErr, rudderErr error - if s.diagnosticClient != nil { - segmentErr = s.diagnosticClient.Close() - } - if s.rudderClient != nil { - rudderErr = s.rudderClient.Close() + return s.rudderClient.Close() } - if segmentErr != nil && rudderErr != nil { - return errors.New(fmt.Sprintf("%s, %s", segmentErr.Error(), rudderErr.Error())) - } else if segmentErr != nil { - return segmentErr - } - - return rudderErr + return nil } // GetHubs returns the list of hubs. This method is safe diff --git a/go.mod b/go.mod index 410e102329..c312e2b954 100644 --- a/go.mod +++ b/go.mod @@ -92,7 +92,6 @@ require ( github.com/rudderlabs/analytics-go v3.2.1+incompatible github.com/russellhaering/goxmldsig v0.0.0-20180430223755-7acd5e4a6ef7 github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd - github.com/segmentio/analytics-go v3.1.0+incompatible github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3 // indirect github.com/sirupsen/logrus v1.5.0 github.com/smartystreets/assertions v1.0.0 // indirect diff --git a/go.sum b/go.sum index 000f8a8d2d..102f5a1d3d 100644 --- a/go.sum +++ b/go.sum @@ -604,8 +604,6 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/segmentio/analytics-go v3.1.0+incompatible h1:IyiOfUgQFVHvsykKKbdI7ZsH374uv3/DfZUo9+G0Z80= -github.com/segmentio/analytics-go v3.1.0+incompatible/go.mod h1:C7CYBtQWk4vRk2RyLu0qOcbHJ18E3F1HV2C/8JvKN48= github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3 h1:ZuhckGJ10ulaKkdvJtiAqsLTiPrLaXSdnVgXJKJkTxE= github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= diff --git a/utils/subpath.go b/utils/subpath.go index a79bb04c4d..6bfccad5f3 100644 --- a/utils/subpath.go +++ b/utils/subpath.go @@ -85,13 +85,13 @@ func UpdateAssetsSubpath(subpath string) error { newRootHtml := string(oldRootHtml) - reCSP := regexp.MustCompile(``) + reCSP := regexp.MustCompile(``) if results := reCSP.FindAllString(newRootHtml, -1); len(results) == 0 { return fmt.Errorf("failed to find 'Content-Security-Policy' meta tag to rewrite") } newRootHtml = reCSP.ReplaceAllLiteralString(newRootHtml, fmt.Sprintf( - ``, + ``, GetSubpathScriptHash(subpath), )) diff --git a/utils/subpath_test.go b/utils/subpath_test.go index b83192a25e..bb5e1082cb 100644 --- a/utils/subpath_test.go +++ b/utils/subpath_test.go @@ -268,19 +268,19 @@ func sToP(s string) *string { return &s } -const contentSecurityPolicyNotFoundHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const contentSecurityPolicyNotFoundHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` -const contentSecurityPolicyNotFound2Html = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const contentSecurityPolicyNotFound2Html = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` -const baseRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const baseRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` const baseCss = `@font-face{font-family:FontAwesome;src:url(/static/files/674f50d287a8c48dc19ba404d20fe713.eot);src:url(/static/files/674f50d287a8c48dc19ba404d20fe713.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(/static/files/af7ae505a9eed503f8b8e6982036873e.woff2) format("woff2"),url(/static/files/fee66e712a8a08eef5805a46892932ad.woff) format("woff"),url(/static/files/b06871f281fee6b241d60582ae9369b9.ttf) format("truetype"),url(/static/files/677433a0892aaed7b7d2628c313c9775.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}` -const subpathRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const subpathRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` const subpathCss = `@font-face{font-family:FontAwesome;src:url(/subpath/static/files/674f50d287a8c48dc19ba404d20fe713.eot);src:url(/subpath/static/files/674f50d287a8c48dc19ba404d20fe713.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(/subpath/static/files/af7ae505a9eed503f8b8e6982036873e.woff2) format("woff2"),url(/subpath/static/files/fee66e712a8a08eef5805a46892932ad.woff) format("woff"),url(/subpath/static/files/b06871f281fee6b241d60582ae9369b9.ttf) format("truetype"),url(/subpath/static/files/677433a0892aaed7b7d2628c313c9775.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}` -const newSubpathRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` +const newSubpathRootHtml = ` Mattermost

Cannot connect to Mattermost


We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not work, please verify that your computer is connected to the internet.


` const newSubpathCss = `@font-face{font-family:FontAwesome;src:url(/nested/subpath/static/files/674f50d287a8c48dc19ba404d20fe713.eot);src:url(/nested/subpath/static/files/674f50d287a8c48dc19ba404d20fe713.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(/nested/subpath/static/files/af7ae505a9eed503f8b8e6982036873e.woff2) format("woff2"),url(/nested/subpath/static/files/fee66e712a8a08eef5805a46892932ad.woff) format("woff"),url(/nested/subpath/static/files/b06871f281fee6b241d60582ae9369b9.ttf) format("truetype"),url(/nested/subpath/static/files/677433a0892aaed7b7d2628c313c9775.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}` diff --git a/vendor/github.com/segmentio/analytics-go/.gitignore b/vendor/github.com/segmentio/analytics-go/.gitignore deleted file mode 100644 index 942678bd91..0000000000 --- a/vendor/github.com/segmentio/analytics-go/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - -# Emacs -*~ -\#* -.\#* - -# Artifacts -tmp/* diff --git a/vendor/github.com/segmentio/analytics-go/.gitmodules b/vendor/github.com/segmentio/analytics-go/.gitmodules deleted file mode 100644 index b2150b3427..0000000000 --- a/vendor/github.com/segmentio/analytics-go/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "vendor/github.com/segmentio/backo-go"] - path = vendor/github.com/segmentio/backo-go - url = https://github.com/segmentio/backo-go -[submodule "vendor/github.com/xtgo/uuid"] - path = vendor/github.com/xtgo/uuid - url = https://github.com/xtgo/uuid diff --git a/vendor/github.com/segmentio/analytics-go/History.md b/vendor/github.com/segmentio/analytics-go/History.md deleted file mode 100644 index d01214e65c..0000000000 --- a/vendor/github.com/segmentio/analytics-go/History.md +++ /dev/null @@ -1,88 +0,0 @@ - -v3.1.0 / 2019-09-20 -=================== - - * add consistent panic error message - * Expose the Message interface Validate method - * return error if a custom type is enqueued - * Handle pointer types in Enqueue() - * message: update maxMessageBytes to 32KB - -v3.0.1 / 2018-10-02 -=================== - -* Migrate from Circle V1 format to Circle V2 -* Adds CLI for sending segment events -* Vendor packages back-go and uuid instead of using gitsubmodules - - -v3.0.0 / 2016-06-02 -=================== - - * 3.0 is a significant rewrite with multiple breaking changes. - * [Quickstart](https://segment.com/docs/sources/server/go/quickstart/). - * [Documentation](https://segment.com/docs/sources/server/go/). - * [GoDocs](https://godoc.org/gopkg.in/segmentio/analytics-go.v3). - * [What's New in v3](https://segment.com/docs/sources/server/go/#what-s-new-in-v3). - - -v2.1.0 / 2015-12-28 -=================== - - * Add ability to set custom timestamps for messages. - * Add ability to set a custom `net/http` client. - * Add ability to set a custom logger. - * Fix edge case when client would try to upload no messages. - * Properly upload in-flight messages when client is asked to shutdown. - * Add ability to set `.integrations` field on messages. - * Fix resource leak with interval ticker after shutdown. - * Add retries and back-off when uploading messages. - * Add ability to set custom flush interval. - -v2.0.0 / 2015-02-03 -=================== - - * rewrite with breaking API changes - -v1.2.0 / 2014-09-03 -================== - - * add public .Flush() method - * rename .Stop() to .Close() - -v1.1.0 / 2014-09-02 -================== - - * add client.Stop() to flash/wait. Closes #7 - -v1.0.0 / 2014-08-26 -================== - - * fix response close - * change comments to be more go-like - * change uuid libraries - -0.1.2 / 2014-06-11 -================== - - * add runnable example - * fix: close body - -0.1.1 / 2014-05-31 -================== - - * refactor locking - -0.1.0 / 2014-05-22 -================== - - * replace Debug option with debug package - -0.0.2 / 2014-05-20 -================== - - * add .Start() - * add mutexes - * rename BufferSize to FlushAt and FlushInterval to FlushAfter - * lower FlushInterval to 5 seconds - * lower BufferSize to 20 to match other clients diff --git a/vendor/github.com/segmentio/analytics-go/License.md b/vendor/github.com/segmentio/analytics-go/License.md deleted file mode 100644 index f452c5d0fd..0000000000 --- a/vendor/github.com/segmentio/analytics-go/License.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Segment, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/segmentio/analytics-go/Makefile b/vendor/github.com/segmentio/analytics-go/Makefile deleted file mode 100644 index 9de0d1ba74..0000000000 --- a/vendor/github.com/segmentio/analytics-go/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -ifndef CIRCLE_ARTIFACTS -CIRCLE_ARTIFACTS=tmp -endif - -bootstrap: - .buildscript/bootstrap.sh - -dependencies: - @go get -v -t ./... - -vet: - @go vet ./... - -test: vet - @mkdir -p ${CIRCLE_ARTIFACTS} - @go test -race -coverprofile=${CIRCLE_ARTIFACTS}/cover.out . - @go tool cover -func ${CIRCLE_ARTIFACTS}/cover.out -o ${CIRCLE_ARTIFACTS}/cover.txt - @go tool cover -html ${CIRCLE_ARTIFACTS}/cover.out -o ${CIRCLE_ARTIFACTS}/cover.html - -build: test - @go build ./... - -e2e: - @if [ "$(RUN_E2E_TESTS)" != "true" ]; then \ - echo "Skipping end to end tests."; else \ - go get github.com/segmentio/library-e2e-tester/cmd/tester; \ - tester -segment-write-key=$(SEGMENT_WRITE_KEY) -webhook-auth-username=$(WEBHOOK_AUTH_USERNAME) -webhook-bucket=$(WEBHOOK_BUCKET) -path='cli' -concurrency=2 -skip='advance|alias'; fi - -ci: dependencies test e2e - -.PHONY: bootstrap dependencies vet test e2e ci diff --git a/vendor/github.com/segmentio/analytics-go/Readme.md b/vendor/github.com/segmentio/analytics-go/Readme.md deleted file mode 100644 index 7d369c16e8..0000000000 --- a/vendor/github.com/segmentio/analytics-go/Readme.md +++ /dev/null @@ -1,55 +0,0 @@ -# analytics-go [![Circle CI](https://circleci.com/gh/segmentio/analytics-go/tree/master.svg?style=shield)](https://circleci.com/gh/segmentio/analytics-go/tree/master) [![go-doc](https://godoc.org/github.com/segmentio/analytics-go?status.svg)](https://godoc.org/github.com/segmentio/analytics-go) - -Segment analytics client for Go. - -## Installation - -The package can be simply installed via go get, we recommend that you use a -package version management system like the Go vendor directory or a tool like -Godep to avoid issues related to API breaking changes introduced between major -versions of the library. - -To install it in the GOPATH: -``` -go get https://github.com/segmentio/analytics-go -``` - -## Documentation - -The links bellow should provide all the documentation needed to make the best -use of the library and the Segment API: - -- [Documentation](https://segment.com/docs/libraries/go/) -- [godoc](https://godoc.org/gopkg.in/segmentio/analytics-go.v3) -- [API](https://segment.com/docs/libraries/http/) -- [Specs](https://segment.com/docs/spec/) - -## Usage - -```go -package main - -import ( - "os" - - "github.com/segmentio/analytics-go" -) - -func main() { - // Instantiates a client to use send messages to the segment API. - client := analytics.New(os.Getenv("SEGMENT_WRITE_KEY")) - - // Enqueues a track event that will be sent asynchronously. - client.Enqueue(analytics.Track{ - UserId: "test-user", - Event: "test-snippet", - }) - - // Flushes any queued messages and closes the client. - client.Close() -} -``` - -## License - -The library is released under the [MIT license](License.md). diff --git a/vendor/github.com/segmentio/analytics-go/alias.go b/vendor/github.com/segmentio/analytics-go/alias.go deleted file mode 100644 index e9dbe85aa0..0000000000 --- a/vendor/github.com/segmentio/analytics-go/alias.go +++ /dev/null @@ -1,44 +0,0 @@ -package analytics - -import "time" - -var _ Message = (*Alias)(nil) - -// This type represents object sent in a alias call as described in -// https://segment.com/docs/libraries/http/#alias -type Alias struct { - // This field is exported for serialization purposes and shouldn't be set by - // the application, its value is always overwritten by the library. - Type string `json:"type,omitempty"` - - MessageId string `json:"messageId,omitempty"` - PreviousId string `json:"previousId"` - UserId string `json:"userId"` - Timestamp time.Time `json:"timestamp,omitempty"` - Context *Context `json:"context,omitempty"` - Integrations Integrations `json:"integrations,omitempty"` -} - -func (msg Alias) internal() { - panic(unimplementedError) -} - -func (msg Alias) Validate() error { - if len(msg.UserId) == 0 { - return FieldError{ - Type: "analytics.Alias", - Name: "UserId", - Value: msg.UserId, - } - } - - if len(msg.PreviousId) == 0 { - return FieldError{ - Type: "analytics.Alias", - Name: "PreviousId", - Value: msg.PreviousId, - } - } - - return nil -} diff --git a/vendor/github.com/segmentio/analytics-go/analytics.go b/vendor/github.com/segmentio/analytics-go/analytics.go deleted file mode 100644 index d0f089fb6c..0000000000 --- a/vendor/github.com/segmentio/analytics-go/analytics.go +++ /dev/null @@ -1,431 +0,0 @@ -package analytics - -import ( - "fmt" - "io" - "io/ioutil" - "sync" - - "bytes" - "encoding/json" - "net/http" - "time" -) - -// Version of the client. -const Version = "3.0.0" -const unimplementedError = "not implemented" - -// This interface is the main API exposed by the analytics package. -// Values that satsify this interface are returned by the client constructors -// provided by the package and provide a way to send messages via the HTTP API. -type Client interface { - io.Closer - - // Queues a message to be sent by the client when the conditions for a batch - // upload are met. - // This is the main method you'll be using, a typical flow would look like - // this: - // - // client := analytics.New(writeKey) - // ... - // client.Enqueue(analytics.Track{ ... }) - // ... - // client.Close() - // - // The method returns an error if the message queue not be queued, which - // happens if the client was already closed at the time the method was - // called or if the message was malformed. - Enqueue(Message) error -} - -type client struct { - Config - key string - - // This channel is where the `Enqueue` method writes messages so they can be - // picked up and pushed by the backend goroutine taking care of applying the - // batching rules. - msgs chan Message - - // These two channels are used to synchronize the client shutting down when - // `Close` is called. - // The first channel is closed to signal the backend goroutine that it has - // to stop, then the second one is closed by the backend goroutine to signal - // that it has finished flushing all queued messages. - quit chan struct{} - shutdown chan struct{} - - // This HTTP client is used to send requests to the backend, it uses the - // HTTP transport provided in the configuration. - http http.Client -} - -// Instantiate a new client that uses the write key passed as first argument to -// send messages to the backend. -// The client is created with the default configuration. -func New(writeKey string) Client { - // Here we can ignore the error because the default config is always valid. - c, _ := NewWithConfig(writeKey, Config{}) - return c -} - -// Instantiate a new client that uses the write key and configuration passed as -// arguments to send messages to the backend. -// The function will return an error if the configuration contained impossible -// values (like a negative flush interval for example). -// When the function returns an error the returned client will always be nil. -func NewWithConfig(writeKey string, config Config) (cli Client, err error) { - if err = config.validate(); err != nil { - return - } - - c := &client{ - Config: makeConfig(config), - key: writeKey, - msgs: make(chan Message, 100), - quit: make(chan struct{}), - shutdown: make(chan struct{}), - http: makeHttpClient(config.Transport), - } - - go c.loop() - - cli = c - return -} - -func makeHttpClient(transport http.RoundTripper) http.Client { - httpClient := http.Client{ - Transport: transport, - } - if supportsTimeout(transport) { - httpClient.Timeout = 10 * time.Second - } - return httpClient -} - -func dereferenceMessage(msg Message) Message { - switch m := msg.(type) { - case *Alias: - if m == nil { - return nil - } - return *m - case *Group: - if m == nil { - return nil - } - return *m - case *Identify: - if m == nil { - return nil - } - return *m - case *Page: - if m == nil { - return nil - } - return *m - case *Screen: - if m == nil { - return nil - } - return *m - case *Track: - if m == nil { - return nil - } - return *m - } - - return msg -} - -func (c *client) Enqueue(msg Message) (err error) { - msg = dereferenceMessage(msg) - if err = msg.Validate(); err != nil { - return - } - - var id = c.uid() - var ts = c.now() - - switch m := msg.(type) { - case Alias: - m.Type = "alias" - m.MessageId = makeMessageId(m.MessageId, id) - m.Timestamp = makeTimestamp(m.Timestamp, ts) - msg = m - - case Group: - m.Type = "group" - m.MessageId = makeMessageId(m.MessageId, id) - m.Timestamp = makeTimestamp(m.Timestamp, ts) - msg = m - - case Identify: - m.Type = "identify" - m.MessageId = makeMessageId(m.MessageId, id) - m.Timestamp = makeTimestamp(m.Timestamp, ts) - msg = m - - case Page: - m.Type = "page" - m.MessageId = makeMessageId(m.MessageId, id) - m.Timestamp = makeTimestamp(m.Timestamp, ts) - msg = m - - case Screen: - m.Type = "screen" - m.MessageId = makeMessageId(m.MessageId, id) - m.Timestamp = makeTimestamp(m.Timestamp, ts) - msg = m - - case Track: - m.Type = "track" - m.MessageId = makeMessageId(m.MessageId, id) - m.Timestamp = makeTimestamp(m.Timestamp, ts) - msg = m - - default: - err = fmt.Errorf("messages with custom types cannot be enqueued: %T", msg) - return - } - - defer func() { - // When the `msgs` channel is closed writing to it will trigger a panic. - // To avoid letting the panic propagate to the caller we recover from it - // and instead report that the client has been closed and shouldn't be - // used anymore. - if recover() != nil { - err = ErrClosed - } - }() - - c.msgs <- msg - return -} - -// Close and flush metrics. -func (c *client) Close() (err error) { - defer func() { - // Always recover, a panic could be raised if `c`.quit was closed which - // means the method was called more than once. - if recover() != nil { - err = ErrClosed - } - }() - close(c.quit) - <-c.shutdown - return -} - -// Asychronously send a batched requests. -func (c *client) sendAsync(msgs []message, wg *sync.WaitGroup, ex *executor) { - wg.Add(1) - - if !ex.do(func() { - defer wg.Done() - defer func() { - // In case a bug is introduced in the send function that triggers - // a panic, we don't want this to ever crash the application so we - // catch it here and log it instead. - if err := recover(); err != nil { - c.errorf("panic - %s", err) - } - }() - c.send(msgs) - }) { - wg.Done() - c.errorf("sending messages failed - %s", ErrTooManyRequests) - c.notifyFailure(msgs, ErrTooManyRequests) - } -} - -// Send batch request. -func (c *client) send(msgs []message) { - const attempts = 10 - - b, err := json.Marshal(batch{ - MessageId: c.uid(), - SentAt: c.now(), - Messages: msgs, - Context: c.DefaultContext, - }) - - if err != nil { - c.errorf("marshalling messages - %s", err) - c.notifyFailure(msgs, err) - return - } - - for i := 0; i != attempts; i++ { - if err = c.upload(b); err == nil { - c.notifySuccess(msgs) - return - } - - // Wait for either a retry timeout or the client to be closed. - select { - case <-time.After(c.RetryAfter(i)): - case <-c.quit: - c.errorf("%d messages dropped because they failed to be sent and the client was closed", len(msgs)) - c.notifyFailure(msgs, err) - return - } - } - - c.errorf("%d messages dropped because they failed to be sent after %d attempts", len(msgs), attempts) - c.notifyFailure(msgs, err) -} - -// Upload serialized batch message. -func (c *client) upload(b []byte) error { - url := c.Endpoint + "/v1/batch" - req, err := http.NewRequest("POST", url, bytes.NewReader(b)) - if err != nil { - c.errorf("creating request - %s", err) - return err - } - - req.Header.Add("User-Agent", "analytics-go (version: "+Version+")") - req.Header.Add("Content-Type", "application/json") - req.Header.Add("Content-Length", string(len(b))) - req.SetBasicAuth(c.key, "") - - res, err := c.http.Do(req) - - if err != nil { - c.errorf("sending request - %s", err) - return err - } - - defer res.Body.Close() - return c.report(res) -} - -// Report on response body. -func (c *client) report(res *http.Response) (err error) { - var body []byte - - if res.StatusCode < 300 { - c.debugf("response %s", res.Status) - return - } - - if body, err = ioutil.ReadAll(res.Body); err != nil { - c.errorf("response %d %s - %s", res.StatusCode, res.Status, err) - return - } - - c.logf("response %d %s – %s", res.StatusCode, res.Status, string(body)) - return fmt.Errorf("%d %s", res.StatusCode, res.Status) -} - -// Batch loop. -func (c *client) loop() { - defer close(c.shutdown) - - wg := &sync.WaitGroup{} - defer wg.Wait() - - tick := time.NewTicker(c.Interval) - defer tick.Stop() - - ex := newExecutor(c.maxConcurrentRequests) - defer ex.close() - - mq := messageQueue{ - maxBatchSize: c.BatchSize, - maxBatchBytes: c.maxBatchBytes(), - } - - for { - select { - case msg := <-c.msgs: - c.push(&mq, msg, wg, ex) - - case <-tick.C: - c.flush(&mq, wg, ex) - - case <-c.quit: - c.debugf("exit requested – draining messages") - - // Drain the msg channel, we have to close it first so no more - // messages can be pushed and otherwise the loop would never end. - close(c.msgs) - for msg := range c.msgs { - c.push(&mq, msg, wg, ex) - } - - c.flush(&mq, wg, ex) - c.debugf("exit") - return - } - } -} - -func (c *client) push(q *messageQueue, m Message, wg *sync.WaitGroup, ex *executor) { - var msg message - var err error - - if msg, err = makeMessage(m, maxMessageBytes); err != nil { - c.errorf("%s - %v", err, m) - c.notifyFailure([]message{{m, nil}}, err) - return - } - - c.debugf("buffer (%d/%d) %v", len(q.pending), c.BatchSize, m) - - if msgs := q.push(msg); msgs != nil { - c.debugf("exceeded messages batch limit with batch of %d messages – flushing", len(msgs)) - c.sendAsync(msgs, wg, ex) - } -} - -func (c *client) flush(q *messageQueue, wg *sync.WaitGroup, ex *executor) { - if msgs := q.flush(); msgs != nil { - c.debugf("flushing %d messages", len(msgs)) - c.sendAsync(msgs, wg, ex) - } -} - -func (c *client) debugf(format string, args ...interface{}) { - if c.Verbose { - c.logf(format, args...) - } -} - -func (c *client) logf(format string, args ...interface{}) { - c.Logger.Logf(format, args...) -} - -func (c *client) errorf(format string, args ...interface{}) { - c.Logger.Errorf(format, args...) -} - -func (c *client) maxBatchBytes() int { - b, _ := json.Marshal(batch{ - MessageId: c.uid(), - SentAt: c.now(), - Context: c.DefaultContext, - }) - return maxBatchBytes - len(b) -} - -func (c *client) notifySuccess(msgs []message) { - if c.Callback != nil { - for _, m := range msgs { - c.Callback.Success(m.msg) - } - } -} - -func (c *client) notifyFailure(msgs []message, err error) { - if c.Callback != nil { - for _, m := range msgs { - c.Callback.Failure(m.msg, err) - } - } -} diff --git a/vendor/github.com/segmentio/analytics-go/config.go b/vendor/github.com/segmentio/analytics-go/config.go deleted file mode 100644 index c167757304..0000000000 --- a/vendor/github.com/segmentio/analytics-go/config.go +++ /dev/null @@ -1,173 +0,0 @@ -package analytics - -import ( - "net/http" - "time" - - "github.com/segmentio/backo-go" - "github.com/xtgo/uuid" -) - -// Instances of this type carry the different configuration options that may -// be set when instantiating a client. -// -// Each field's zero-value is either meaningful or interpreted as using the -// default value defined by the library. -type Config struct { - - // The endpoint to which the client connect and send their messages, set to - // `DefaultEndpoint` by default. - Endpoint string - - // The flushing interval of the client. Messages will be sent when they've - // been queued up to the maximum batch size or when the flushing interval - // timer triggers. - Interval time.Duration - - // The HTTP transport used by the client, this allows an application to - // redefine how requests are being sent at the HTTP level (for example, - // to change the connection pooling policy). - // If none is specified the client uses `http.DefaultTransport`. - Transport http.RoundTripper - - // The logger used by the client to output info or error messages when that - // are generated by background operations. - // If none is specified the client uses a standard logger that outputs to - // `os.Stderr`. - Logger Logger - - // The callback object that will be used by the client to notify the - // application when messages sends to the backend API succeeded or failed. - Callback Callback - - // The maximum number of messages that will be sent in one API call. - // Messages will be sent when they've been queued up to the maximum batch - // size or when the flushing interval timer triggers. - // Note that the API will still enforce a 500KB limit on each HTTP request - // which is independent from the number of embedded messages. - BatchSize int - - // When set to true the client will send more frequent and detailed messages - // to its logger. - Verbose bool - - // The default context set on each message sent by the client. - DefaultContext *Context - - // The retry policy used by the client to resend requests that have failed. - // The function is called with how many times the operation has been retried - // and is expected to return how long the client should wait before trying - // again. - // If not set the client will fallback to use a default retry policy. - RetryAfter func(int) time.Duration - - // A function called by the client to generate unique message identifiers. - // The client uses a UUID generator if none is provided. - // This field is not exported and only exposed internally to let unit tests - // mock the id generation. - uid func() string - - // A function called by the client to get the current time, `time.Now` is - // used by default. - // This field is not exported and only exposed internally to let unit tests - // mock the current time. - now func() time.Time - - // The maximum number of goroutines that will be spawned by a client to send - // requests to the backend API. - // This field is not exported and only exposed internally to let unit tests - // mock the current time. - maxConcurrentRequests int -} - -// This constant sets the default endpoint to which client instances send -// messages if none was explictly set. -const DefaultEndpoint = "https://api.segment.io" - -// This constant sets the default flush interval used by client instances if -// none was explicitly set. -const DefaultInterval = 5 * time.Second - -// This constant sets the default batch size used by client instances if none -// was explicitly set. -const DefaultBatchSize = 250 - -// Verifies that fields that don't have zero-values are set to valid values, -// returns an error describing the problem if a field was invalid. -func (c *Config) validate() error { - if c.Interval < 0 { - return ConfigError{ - Reason: "negative time intervals are not supported", - Field: "Interval", - Value: c.Interval, - } - } - - if c.BatchSize < 0 { - return ConfigError{ - Reason: "negative batch sizes are not supported", - Field: "BatchSize", - Value: c.BatchSize, - } - } - - return nil -} - -// Given a config object as argument the function will set all zero-values to -// their defaults and return the modified object. -func makeConfig(c Config) Config { - if len(c.Endpoint) == 0 { - c.Endpoint = DefaultEndpoint - } - - if c.Interval == 0 { - c.Interval = DefaultInterval - } - - if c.Transport == nil { - c.Transport = http.DefaultTransport - } - - if c.Logger == nil { - c.Logger = newDefaultLogger() - } - - if c.BatchSize == 0 { - c.BatchSize = DefaultBatchSize - } - - if c.DefaultContext == nil { - c.DefaultContext = &Context{} - } - - if c.RetryAfter == nil { - c.RetryAfter = backo.DefaultBacko().Duration - } - - if c.uid == nil { - c.uid = uid - } - - if c.now == nil { - c.now = time.Now - } - - if c.maxConcurrentRequests == 0 { - c.maxConcurrentRequests = 1000 - } - - // We always overwrite the 'library' field of the default context set on the - // client because we want this information to be accurate. - c.DefaultContext.Library = LibraryInfo{ - Name: "analytics-go", - Version: Version, - } - return c -} - -// This function returns a string representation of a UUID, it's the default -// function used for generating unique IDs. -func uid() string { - return uuid.NewRandom().String() -} diff --git a/vendor/github.com/segmentio/analytics-go/context.go b/vendor/github.com/segmentio/analytics-go/context.go deleted file mode 100644 index 7a30c1b98d..0000000000 --- a/vendor/github.com/segmentio/analytics-go/context.go +++ /dev/null @@ -1,148 +0,0 @@ -package analytics - -import ( - "encoding/json" - "net" - "reflect" -) - -// This type provides the representation of the `context` object as defined in -// https://segment.com/docs/spec/common/#context -type Context struct { - App AppInfo `json:"app,omitempty"` - Campaign CampaignInfo `json:"campaign,omitempty"` - Device DeviceInfo `json:"device,omitempty"` - Library LibraryInfo `json:"library,omitempty"` - Location LocationInfo `json:"location,omitempty"` - Network NetworkInfo `json:"network,omitempty"` - OS OSInfo `json:"os,omitempty"` - Page PageInfo `json:"page,omitempty"` - Referrer ReferrerInfo `json:"referrer,omitempty"` - Screen ScreenInfo `json:"screen,omitempty"` - IP net.IP `json:"ip,omitempty"` - Locale string `json:"locale,omitempty"` - Timezone string `json:"timezone,omitempty"` - UserAgent string `json:"userAgent,omitempty"` - Traits Traits `json:"traits,omitempty"` - - // This map is used to allow extensions to the context specifications that - // may not be documented or could be introduced in the future. - // The fields of this map are inlined in the serialized context object, - // there is no actual "extra" field in the JSON representation. - Extra map[string]interface{} `json:"-"` -} - -// This type provides the representation of the `context.app` object as defined -// in https://segment.com/docs/spec/common/#context -type AppInfo struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` - Build string `json:"build,omitempty"` - Namespace string `json:"namespace,omitempty"` -} - -// This type provides the representation of the `context.campaign` object as -// defined in https://segment.com/docs/spec/common/#context -type CampaignInfo struct { - Name string `json:"name,omitempty"` - Source string `json:"source,omitempty"` - Medium string `json:"medium,omitempty"` - Term string `json:"term,omitempty"` - Content string `json:"content,omitempty"` -} - -// This type provides the representation of the `context.device` object as -// defined in https://segment.com/docs/spec/common/#context -type DeviceInfo struct { - Id string `json:"id,omitempty"` - Manufacturer string `json:"manufacturer,omitempty"` - Model string `json:"model,omitempty"` - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - Version string `json:"version,omitempty"` - AdvertisingID string `json:"advertisingId,omitempty"` -} - -// This type provides the representation of the `context.library` object as -// defined in https://segment.com/docs/spec/common/#context -type LibraryInfo struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` -} - -// This type provides the representation of the `context.location` object as -// defined in https://segment.com/docs/spec/common/#context -type LocationInfo struct { - City string `json:"city,omitempty"` - Country string `json:"country,omitempty"` - Region string `json:"region,omitempty"` - Latitude float64 `json:"latitude,omitempty"` - Longitude float64 `json:"longitude,omitempty"` - Speed float64 `json:"speed,omitempty"` -} - -// This type provides the representation of the `context.network` object as -// defined in https://segment.com/docs/spec/common/#context -type NetworkInfo struct { - Bluetooth bool `json:"bluetooth,omitempty"` - Cellular bool `json:"cellular,omitempty"` - WIFI bool `json:"wifi,omitempty"` - Carrier string `json:"carrier,omitempty"` -} - -// This type provides the representation of the `context.os` object as defined -// in https://segment.com/docs/spec/common/#context -type OSInfo struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` -} - -// This type provides the representation of the `context.page` object as -// defined in https://segment.com/docs/spec/common/#context -type PageInfo struct { - Hash string `json:"hash,omitempty"` - Path string `json:"path,omitempty"` - Referrer string `json:"referrer,omitempty"` - Search string `json:"search,omitempty"` - Title string `json:"title,omitempty"` - URL string `json:"url,omitempty"` -} - -// This type provides the representation of the `context.referrer` object as -// defined in https://segment.com/docs/spec/common/#context -type ReferrerInfo struct { - Type string `json:"type,omitempty"` - Name string `json:"name,omitempty"` - URL string `json:"url,omitempty"` - Link string `json:"link,omitempty"` -} - -// This type provides the representation of the `context.screen` object as -// defined in https://segment.com/docs/spec/common/#context -type ScreenInfo struct { - Density int `json:"density,omitempty"` - Width int `json:"width,omitempty"` - Height int `json:"height,omitempty"` -} - -// Satisfy the `json.Marshaler` interface. We have to flatten out the `Extra` -// field but the standard json package doesn't support it yet. -// Implementing this interface allows us to override the default marshaling of -// the context object and to the inlining ourselves. -// -// Related discussion: https://github.com/golang/go/issues/6213 -func (ctx Context) MarshalJSON() ([]byte, error) { - v := reflect.ValueOf(ctx) - n := v.NumField() - m := make(map[string]interface{}, n+len(ctx.Extra)) - - // Copy the `Extra` map into the map representation of the context, it is - // important to do this operation before going through the actual struct - // fields so the latter take precendence and override duplicated values - // that would be set in the extensions. - for name, value := range ctx.Extra { - m[name] = value - } - - return json.Marshal(structToMap(v, m)) -} diff --git a/vendor/github.com/segmentio/analytics-go/error.go b/vendor/github.com/segmentio/analytics-go/error.go deleted file mode 100644 index d5503864e9..0000000000 --- a/vendor/github.com/segmentio/analytics-go/error.go +++ /dev/null @@ -1,60 +0,0 @@ -package analytics - -import ( - "errors" - "fmt" -) - -// Returned by the `NewWithConfig` function when the one of the configuration -// fields was set to an impossible value (like a negative duration). -type ConfigError struct { - - // A human-readable message explaining why the configuration field's value - // is invalid. - Reason string - - // The name of the configuration field that was carrying an invalid value. - Field string - - // The value of the configuration field that caused the error. - Value interface{} -} - -func (e ConfigError) Error() string { - return fmt.Sprintf("analytics.NewWithConfig: %s (analytics.Config.%s: %#v)", e.Reason, e.Field, e.Value) -} - -// Instances of this type are used to represent errors returned when a field was -// no initialize properly in a structure passed as argument to one of the -// functions of this package. -type FieldError struct { - - // The human-readable representation of the type of structure that wasn't - // initialized properly. - Type string - - // The name of the field that wasn't properly initialized. - Name string - - // The value of the field that wasn't properly initialized. - Value interface{} -} - -func (e FieldError) Error() string { - return fmt.Sprintf("%s.%s: invalid field value: %#v", e.Type, e.Name, e.Value) -} - -var ( - // This error is returned by methods of the `Client` interface when they are - // called after the client was already closed. - ErrClosed = errors.New("the client was already closed") - - // This error is used to notify the application that too many requests are - // already being sent and no more messages can be accepted. - ErrTooManyRequests = errors.New("too many requests are already in-flight") - - // This error is used to notify the client callbacks that a message send - // failed because the JSON representation of a message exceeded the upper - // limit. - ErrMessageTooBig = errors.New("the message exceeds the maximum allowed size") -) diff --git a/vendor/github.com/segmentio/analytics-go/executor.go b/vendor/github.com/segmentio/analytics-go/executor.go deleted file mode 100644 index 405ee98eef..0000000000 --- a/vendor/github.com/segmentio/analytics-go/executor.go +++ /dev/null @@ -1,53 +0,0 @@ -package analytics - -import "sync" - -type executor struct { - queue chan func() - mutex sync.Mutex - size int - cap int -} - -func newExecutor(cap int) *executor { - e := &executor{ - queue: make(chan func(), 1), - cap: cap, - } - go e.loop() - return e -} - -func (e *executor) do(task func()) (ok bool) { - e.mutex.Lock() - - if e.size != e.cap { - e.queue <- task - e.size++ - ok = true - } - - e.mutex.Unlock() - return -} - -func (e *executor) close() { - close(e.queue) -} - -func (e *executor) loop() { - for task := range e.queue { - go e.run(task) - } -} - -func (e *executor) run(task func()) { - defer e.done() - task() -} - -func (e *executor) done() { - e.mutex.Lock() - e.size-- - e.mutex.Unlock() -} diff --git a/vendor/github.com/segmentio/analytics-go/group.go b/vendor/github.com/segmentio/analytics-go/group.go deleted file mode 100644 index 1da00faaa9..0000000000 --- a/vendor/github.com/segmentio/analytics-go/group.go +++ /dev/null @@ -1,46 +0,0 @@ -package analytics - -import "time" - -var _ Message = (*Group)(nil) - -// This type represents object sent in a group call as described in -// https://segment.com/docs/libraries/http/#group -type Group struct { - // This field is exported for serialization purposes and shouldn't be set by - // the application, its value is always overwritten by the library. - Type string `json:"type,omitempty"` - - MessageId string `json:"messageId,omitempty"` - AnonymousId string `json:"anonymousId,omitempty"` - UserId string `json:"userId,omitempty"` - GroupId string `json:"groupId"` - Timestamp time.Time `json:"timestamp,omitempty"` - Context *Context `json:"context,omitempty"` - Traits Traits `json:"traits,omitempty"` - Integrations Integrations `json:"integrations,omitempty"` -} - -func (msg Group) internal() { - panic(unimplementedError) -} - -func (msg Group) Validate() error { - if len(msg.GroupId) == 0 { - return FieldError{ - Type: "analytics.Group", - Name: "GroupId", - Value: msg.GroupId, - } - } - - if len(msg.UserId) == 0 && len(msg.AnonymousId) == 0 { - return FieldError{ - Type: "analytics.Group", - Name: "UserId", - Value: msg.UserId, - } - } - - return nil -} diff --git a/vendor/github.com/segmentio/analytics-go/identify.go b/vendor/github.com/segmentio/analytics-go/identify.go deleted file mode 100644 index ab078aa088..0000000000 --- a/vendor/github.com/segmentio/analytics-go/identify.go +++ /dev/null @@ -1,37 +0,0 @@ -package analytics - -import "time" - -var _ Message = (*Identify)(nil) - -// This type represents object sent in an identify call as described in -// https://segment.com/docs/libraries/http/#identify -type Identify struct { - // This field is exported for serialization purposes and shouldn't be set by - // the application, its value is always overwritten by the library. - Type string `json:"type,omitempty"` - - MessageId string `json:"messageId,omitempty"` - AnonymousId string `json:"anonymousId,omitempty"` - UserId string `json:"userId,omitempty"` - Timestamp time.Time `json:"timestamp,omitempty"` - Context *Context `json:"context,omitempty"` - Traits Traits `json:"traits,omitempty"` - Integrations Integrations `json:"integrations,omitempty"` -} - -func (msg Identify) internal() { - panic(unimplementedError) -} - -func (msg Identify) Validate() error { - if len(msg.UserId) == 0 && len(msg.AnonymousId) == 0 { - return FieldError{ - Type: "analytics.Identify", - Name: "UserId", - Value: msg.UserId, - } - } - - return nil -} diff --git a/vendor/github.com/segmentio/analytics-go/integrations.go b/vendor/github.com/segmentio/analytics-go/integrations.go deleted file mode 100644 index 407b4912bc..0000000000 --- a/vendor/github.com/segmentio/analytics-go/integrations.go +++ /dev/null @@ -1,44 +0,0 @@ -package analytics - -// This type is used to represent integrations in messages that support it. -// It is a free-form where values are most often booleans that enable or -// disable integrations. -// Here's a quick example of how this type is meant to be used: -// -// analytics.Track{ -// UserId: "0123456789", -// Integrations: analytics.NewIntegrations() -// .EnableAll() -// .Disable("Salesforce") -// .Disable("Marketo"), -// } -// -// The specifications can be found at https://segment.com/docs/spec/common/#integrations -type Integrations map[string]interface{} - -func NewIntegrations() Integrations { - return make(Integrations, 10) -} - -func (i Integrations) EnableAll() Integrations { - return i.Enable("all") -} - -func (i Integrations) DisableAll() Integrations { - return i.Disable("all") -} - -func (i Integrations) Enable(name string) Integrations { - return i.Set(name, true) -} - -func (i Integrations) Disable(name string) Integrations { - return i.Set(name, false) -} - -// Sets an integration named by the first argument to the specified value, any -// value other than `false` will be interpreted as enabling the integration. -func (i Integrations) Set(name string, value interface{}) Integrations { - i[name] = value - return i -} diff --git a/vendor/github.com/segmentio/analytics-go/json.go b/vendor/github.com/segmentio/analytics-go/json.go deleted file mode 100644 index cd3b1752ef..0000000000 --- a/vendor/github.com/segmentio/analytics-go/json.go +++ /dev/null @@ -1,87 +0,0 @@ -package analytics - -import ( - "reflect" - "strings" -) - -// Imitate what what the JSON package would do when serializing a struct value, -// the only difference is we we don't serialize zero-value struct fields as well. -// Note that this function doesn't recursively convert structures to maps, only -// the value passed as argument is transformed. -func structToMap(v reflect.Value, m map[string]interface{}) map[string]interface{} { - t := v.Type() - n := t.NumField() - - if m == nil { - m = make(map[string]interface{}, n) - } - - for i := 0; i != n; i++ { - field := t.Field(i) - value := v.Field(i) - name, omitempty := parseJsonTag(field.Tag.Get("json"), field.Name) - - if name != "-" && !(omitempty && isZeroValue(value)) { - m[name] = value.Interface() - } - } - - return m -} - -// Parses a JSON tag the way the json package would do it, returing the expected -// name of the field once serialized and if empty values should be omitted. -func parseJsonTag(tag string, defName string) (name string, omitempty bool) { - args := strings.Split(tag, ",") - - if len(args) == 0 || len(args[0]) == 0 { - name = defName - } else { - name = args[0] - } - - if len(args) > 1 && args[1] == "omitempty" { - omitempty = true - } - - return -} - -// Checks if the value given as argument is a zero-value, it is based on the -// isEmptyValue function in https://golang.org/src/encoding/json/encode.go -// but also checks struct types recursively. -func isZeroValue(v reflect.Value) bool { - switch v.Kind() { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - return v.Len() == 0 - - case reflect.Bool: - return !v.Bool() - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - - case reflect.Interface, reflect.Ptr: - return v.IsNil() - - case reflect.Struct: - for i, n := 0, v.NumField(); i != n; i++ { - if !isZeroValue(v.Field(i)) { - return false - } - } - return true - - case reflect.Invalid: - return true - } - - return false -} diff --git a/vendor/github.com/segmentio/analytics-go/logger.go b/vendor/github.com/segmentio/analytics-go/logger.go deleted file mode 100644 index 54190c5f39..0000000000 --- a/vendor/github.com/segmentio/analytics-go/logger.go +++ /dev/null @@ -1,47 +0,0 @@ -package analytics - -import ( - "log" - "os" -) - -// Instances of types implementing this interface can be used to define where -// the analytics client logs are written. -type Logger interface { - - // Analytics clients call this method to log regular messages about the - // operations they perform. - // Messages logged by this method are usually tagged with an `INFO` log - // level in common logging libraries. - Logf(format string, args ...interface{}) - - // Analytics clients call this method to log errors they encounter while - // sending events to the backend servers. - // Messages logged by this method are usually tagged with an `ERROR` log - // level in common logging libraries. - Errorf(format string, args ...interface{}) -} - -// This function instantiate an object that statisfies the analytics.Logger -// interface and send logs to standard logger passed as argument. -func StdLogger(logger *log.Logger) Logger { - return stdLogger{ - logger: logger, - } -} - -type stdLogger struct { - logger *log.Logger -} - -func (l stdLogger) Logf(format string, args ...interface{}) { - l.logger.Printf("INFO: "+format, args...) -} - -func (l stdLogger) Errorf(format string, args ...interface{}) { - l.logger.Printf("ERROR: "+format, args...) -} - -func newDefaultLogger() Logger { - return StdLogger(log.New(os.Stderr, "segment ", log.LstdFlags)) -} diff --git a/vendor/github.com/segmentio/analytics-go/message.go b/vendor/github.com/segmentio/analytics-go/message.go deleted file mode 100644 index a4999c6458..0000000000 --- a/vendor/github.com/segmentio/analytics-go/message.go +++ /dev/null @@ -1,131 +0,0 @@ -package analytics - -import ( - "encoding/json" - "time" -) - -// Values implementing this interface are used by analytics clients to notify -// the application when a message send succeeded or failed. -// -// Callback methods are called by a client's internal goroutines, there are no -// guarantees on which goroutine will trigger the callbacks, the calls can be -// made sequentially or in parallel, the order doesn't depend on the order of -// messages were queued to the client. -// -// Callback methods must return quickly and not cause long blocking operations -// to avoid interferring with the client's internal work flow. -type Callback interface { - - // This method is called for every message that was successfully sent to - // the API. - Success(Message) - - // This method is called for every message that failed to be sent to the - // API and will be discarded by the client. - Failure(Message, error) -} - -// This interface is used to represent analytics objects that can be sent via -// a client. -// -// Types like analytics.Track, analytics.Page, etc... implement this interface -// and therefore can be passed to the analytics.Client.Send method. -type Message interface { - - // Validate validates the internal structure of the message, the method must return - // nil if the message is valid, or an error describing what went wrong. - Validate() error - - // internal is an unexposed interface function to ensure only types defined within this package can satisfy the Message interface. Invoking this method will panic. - internal() -} - -// Takes a message id as first argument and returns it, unless it's the zero- -// value, in that case the default id passed as second argument is returned. -func makeMessageId(id string, def string) string { - if len(id) == 0 { - return def - } - return id -} - -// Returns the time value passed as first argument, unless it's the zero-value, -// in that case the default value passed as second argument is returned. -func makeTimestamp(t time.Time, def time.Time) time.Time { - if t == (time.Time{}) { - return def - } - return t -} - -// This structure represents objects sent to the /v1/batch endpoint. We don't -// export this type because it's only meant to be used internally to send groups -// of messages in one API call. -type batch struct { - MessageId string `json:"messageId"` - SentAt time.Time `json:"sentAt"` - Messages []message `json:"batch"` - Context *Context `json:"context"` -} - -type message struct { - msg Message - json []byte -} - -func makeMessage(m Message, maxBytes int) (msg message, err error) { - if msg.json, err = json.Marshal(m); err == nil { - if len(msg.json) > maxBytes { - err = ErrMessageTooBig - } else { - msg.msg = m - } - } - return -} - -func (m message) MarshalJSON() ([]byte, error) { - return m.json, nil -} - -func (m message) size() int { - // The `+ 1` is for the comma that sits between each items of a JSON array. - return len(m.json) + 1 -} - -type messageQueue struct { - pending []message - bytes int - maxBatchSize int - maxBatchBytes int -} - -func (q *messageQueue) push(m message) (b []message) { - if (q.bytes + m.size()) > q.maxBatchBytes { - b = q.flush() - } - - if q.pending == nil { - q.pending = make([]message, 0, q.maxBatchSize) - } - - q.pending = append(q.pending, m) - q.bytes += len(m.json) - - if b == nil && len(q.pending) == q.maxBatchSize { - b = q.flush() - } - - return -} - -func (q *messageQueue) flush() (msgs []message) { - msgs, q.pending, q.bytes = q.pending, nil, 0 - return -} - -const ( - maxBatchBytes = 500000 - maxMessageBytes = 32000 -) diff --git a/vendor/github.com/segmentio/analytics-go/page.go b/vendor/github.com/segmentio/analytics-go/page.go deleted file mode 100644 index 5a3b231f54..0000000000 --- a/vendor/github.com/segmentio/analytics-go/page.go +++ /dev/null @@ -1,38 +0,0 @@ -package analytics - -import "time" - -var _ Message = (*Page)(nil) - -// This type represents object sent in a page call as described in -// https://segment.com/docs/libraries/http/#page -type Page struct { - // This field is exported for serialization purposes and shouldn't be set by - // the application, its value is always overwritten by the library. - Type string `json:"type,omitempty"` - - MessageId string `json:"messageId,omitempty"` - AnonymousId string `json:"anonymousId,omitempty"` - UserId string `json:"userId,omitempty"` - Name string `json:"name,omitempty"` - Timestamp time.Time `json:"timestamp,omitempty"` - Context *Context `json:"context,omitempty"` - Properties Properties `json:"properties,omitempty"` - Integrations Integrations `json:"integrations,omitempty"` -} - -func (msg Page) internal() { - panic(unimplementedError) -} - -func (msg Page) Validate() error { - if len(msg.UserId) == 0 && len(msg.AnonymousId) == 0 { - return FieldError{ - Type: "analytics.Page", - Name: "UserId", - Value: msg.UserId, - } - } - - return nil -} diff --git a/vendor/github.com/segmentio/analytics-go/properties.go b/vendor/github.com/segmentio/analytics-go/properties.go deleted file mode 100644 index 8b218aebdc..0000000000 --- a/vendor/github.com/segmentio/analytics-go/properties.go +++ /dev/null @@ -1,117 +0,0 @@ -package analytics - -// This type is used to represent properties in messages that support it. -// It is a free-form object so the application can set any value it sees fit but -// a few helper method are defined to make it easier to instantiate properties with -// common fields. -// Here's a quick example of how this type is meant to be used: -// -// analytics.Page{ -// UserId: "0123456789", -// Properties: analytics.NewProperties() -// .SetRevenue(10.0) -// .SetCurrency("USD"), -// } -// -type Properties map[string]interface{} - -func NewProperties() Properties { - return make(Properties, 10) -} - -func (p Properties) SetRevenue(revenue float64) Properties { - return p.Set("revenue", revenue) -} - -func (p Properties) SetCurrency(currency string) Properties { - return p.Set("currency", currency) -} - -func (p Properties) SetValue(value float64) Properties { - return p.Set("value", value) -} - -func (p Properties) SetPath(path string) Properties { - return p.Set("path", path) -} - -func (p Properties) SetReferrer(referrer string) Properties { - return p.Set("referrer", referrer) -} - -func (p Properties) SetTitle(title string) Properties { - return p.Set("title", title) -} - -func (p Properties) SetURL(url string) Properties { - return p.Set("url", url) -} - -func (p Properties) SetName(name string) Properties { - return p.Set("name", name) -} - -func (p Properties) SetCategory(category string) Properties { - return p.Set("category", category) -} - -func (p Properties) SetSKU(sku string) Properties { - return p.Set("sku", sku) -} - -func (p Properties) SetPrice(price float64) Properties { - return p.Set("price", price) -} - -func (p Properties) SetProductId(id string) Properties { - return p.Set("id", id) -} - -func (p Properties) SetOrderId(id string) Properties { - return p.Set("orderId", id) -} - -func (p Properties) SetTotal(total float64) Properties { - return p.Set("total", total) -} - -func (p Properties) SetSubtotal(subtotal float64) Properties { - return p.Set("subtotal", subtotal) -} - -func (p Properties) SetShipping(shipping float64) Properties { - return p.Set("shipping", shipping) -} - -func (p Properties) SetTax(tax float64) Properties { - return p.Set("tax", tax) -} - -func (p Properties) SetDiscount(discount float64) Properties { - return p.Set("discount", discount) -} - -func (p Properties) SetCoupon(coupon string) Properties { - return p.Set("coupon", coupon) -} - -func (p Properties) SetProducts(products ...Product) Properties { - return p.Set("products", products) -} - -func (p Properties) SetRepeat(repeat bool) Properties { - return p.Set("repeat", repeat) -} - -func (p Properties) Set(name string, value interface{}) Properties { - p[name] = value - return p -} - -// This type represents products in the E-commerce API. -type Product struct { - ID string `json:"id,omitempty"` - SKU string `json:"sky,omitempty"` - Name string `json:"name,omitempty"` - Price float64 `json:"price"` -} diff --git a/vendor/github.com/segmentio/analytics-go/screen.go b/vendor/github.com/segmentio/analytics-go/screen.go deleted file mode 100644 index e810e79daa..0000000000 --- a/vendor/github.com/segmentio/analytics-go/screen.go +++ /dev/null @@ -1,38 +0,0 @@ -package analytics - -import "time" - -var _ Message = (*Screen)(nil) - -// This type represents object sent in a screen call as described in -// https://segment.com/docs/libraries/http/#screen -type Screen struct { - // This field is exported for serialization purposes and shouldn't be set by - // the application, its value is always overwritten by the library. - Type string `json:"type,omitempty"` - - MessageId string `json:"messageId,omitempty"` - AnonymousId string `json:"anonymousId,omitempty"` - UserId string `json:"userId,omitempty"` - Name string `json:"name,omitempty"` - Timestamp time.Time `json:"timestamp,omitempty"` - Context *Context `json:"context,omitempty"` - Properties Properties `json:"properties,omitempty"` - Integrations Integrations `json:"integrations,omitempty"` -} - -func (msg Screen) internal() { - panic(unimplementedError) -} - -func (msg Screen) Validate() error { - if len(msg.UserId) == 0 && len(msg.AnonymousId) == 0 { - return FieldError{ - Type: "analytics.Screen", - Name: "UserId", - Value: msg.UserId, - } - } - - return nil -} diff --git a/vendor/github.com/segmentio/analytics-go/timeout_15.go b/vendor/github.com/segmentio/analytics-go/timeout_15.go deleted file mode 100644 index 12b963eddb..0000000000 --- a/vendor/github.com/segmentio/analytics-go/timeout_15.go +++ /dev/null @@ -1,16 +0,0 @@ -// +build !go1.6 - -package analytics - -import "net/http" - -// http clients on versions of go before 1.6 only support timeout if the -// transport implements the `CancelRequest` method. -func supportsTimeout(transport http.RoundTripper) bool { - _, ok := transport.(requestCanceler) - return ok -} - -type requestCanceler interface { - CancelRequest(*http.Request) -} diff --git a/vendor/github.com/segmentio/analytics-go/timeout_16.go b/vendor/github.com/segmentio/analytics-go/timeout_16.go deleted file mode 100644 index 1115cafb77..0000000000 --- a/vendor/github.com/segmentio/analytics-go/timeout_16.go +++ /dev/null @@ -1,10 +0,0 @@ -// +build go1.6 - -package analytics - -import "net/http" - -// http clients on versions of go after 1.6 always support timeout. -func supportsTimeout(transport http.RoundTripper) bool { - return true -} diff --git a/vendor/github.com/segmentio/analytics-go/track.go b/vendor/github.com/segmentio/analytics-go/track.go deleted file mode 100644 index 9c92a809a5..0000000000 --- a/vendor/github.com/segmentio/analytics-go/track.go +++ /dev/null @@ -1,46 +0,0 @@ -package analytics - -import "time" - -var _ Message = (*Track)(nil) - -// This type represents object sent in a track call as described in -// https://segment.com/docs/libraries/http/#track -type Track struct { - // This field is exported for serialization purposes and shouldn't be set by - // the application, its value is always overwritten by the library. - Type string `json:"type,omitempty"` - - MessageId string `json:"messageId,omitempty"` - AnonymousId string `json:"anonymousId,omitempty"` - UserId string `json:"userId,omitempty"` - Event string `json:"event"` - Timestamp time.Time `json:"timestamp,omitempty"` - Context *Context `json:"context,omitempty"` - Properties Properties `json:"properties,omitempty"` - Integrations Integrations `json:"integrations,omitempty"` -} - -func (msg Track) internal() { - panic(unimplementedError) -} - -func (msg Track) Validate() error { - if len(msg.Event) == 0 { - return FieldError{ - Type: "analytics.Track", - Name: "Event", - Value: msg.Event, - } - } - - if len(msg.UserId) == 0 && len(msg.AnonymousId) == 0 { - return FieldError{ - Type: "analytics.Track", - Name: "UserId", - Value: msg.UserId, - } - } - - return nil -} diff --git a/vendor/github.com/segmentio/analytics-go/traits.go b/vendor/github.com/segmentio/analytics-go/traits.go deleted file mode 100644 index d4e82f07a7..0000000000 --- a/vendor/github.com/segmentio/analytics-go/traits.go +++ /dev/null @@ -1,89 +0,0 @@ -package analytics - -import "time" - -// This type is used to represent traits in messages that support it. -// It is a free-form object so the application can set any value it sees fit but -// a few helper method are defined to make it easier to instantiate traits with -// common fields. -// Here's a quick example of how this type is meant to be used: -// -// analytics.Identify{ -// UserId: "0123456789", -// Traits: analytics.NewTraits() -// .SetFirstName("Luke") -// .SetLastName("Skywalker") -// .Set("Role", "Jedi"), -// } -// -// The specifications can be found at https://segment.com/docs/spec/identify/#traits -type Traits map[string]interface{} - -func NewTraits() Traits { - return make(Traits, 10) -} - -func (t Traits) SetAddress(address string) Traits { - return t.Set("address", address) -} - -func (t Traits) SetAge(age int) Traits { - return t.Set("age", age) -} - -func (t Traits) SetAvatar(url string) Traits { - return t.Set("avatar", url) -} - -func (t Traits) SetBirthday(date time.Time) Traits { - return t.Set("birthday", date) -} - -func (t Traits) SetCreatedAt(date time.Time) Traits { - return t.Set("createdAt", date) -} - -func (t Traits) SetDescription(desc string) Traits { - return t.Set("description", desc) -} - -func (t Traits) SetEmail(email string) Traits { - return t.Set("email", email) -} - -func (t Traits) SetFirstName(firstName string) Traits { - return t.Set("firstName", firstName) -} - -func (t Traits) SetGender(gender string) Traits { - return t.Set("gender", gender) -} - -func (t Traits) SetLastName(lastName string) Traits { - return t.Set("lastName", lastName) -} - -func (t Traits) SetName(name string) Traits { - return t.Set("name", name) -} - -func (t Traits) SetPhone(phone string) Traits { - return t.Set("phone", phone) -} - -func (t Traits) SetTitle(title string) Traits { - return t.Set("title", title) -} - -func (t Traits) SetUsername(username string) Traits { - return t.Set("username", username) -} - -func (t Traits) SetWebsite(url string) Traits { - return t.Set("website", url) -} - -func (t Traits) Set(field string, value interface{}) Traits { - t[field] = value - return t -} diff --git a/vendor/modules.txt b/vendor/modules.txt index bcc985306f..a66a5b96cc 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -403,9 +403,6 @@ github.com/rwcarlsen/goexif/exif github.com/rwcarlsen/goexif/tiff # github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 github.com/sean-/seed -# github.com/segmentio/analytics-go v3.1.0+incompatible -## explicit -github.com/segmentio/analytics-go # github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3 ## explicit github.com/segmentio/backo-go diff --git a/web/handlers.go b/web/handlers.go index 18f66ec7a1..36de35f709 100644 --- a/web/handlers.go +++ b/web/handlers.go @@ -167,7 +167,7 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Frame-Options", "SAMEORIGIN") // Set content security policy. This is also specified in the root.html of the webapp in a meta tag. w.Header().Set("Content-Security-Policy", fmt.Sprintf( - "frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com cdn.segment.com/analytics.js/%s", + "frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com%s", h.cspShaDirective, )) } else { diff --git a/web/handlers_test.go b/web/handlers_test.go index c4fc13472e..e569d14389 100644 --- a/web/handlers_test.go +++ b/web/handlers_test.go @@ -298,7 +298,7 @@ func TestHandlerServeCSPHeader(t *testing.T) { response := httptest.NewRecorder() handler.ServeHTTP(response, request) assert.Equal(t, 200, response.Code) - assert.Equal(t, response.Header()["Content-Security-Policy"], []string{"frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com cdn.segment.com/analytics.js/"}) + assert.Equal(t, response.Header()["Content-Security-Policy"], []string{"frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com"}) }) t.Run("static, with subpath", func(t *testing.T) { @@ -337,12 +337,12 @@ func TestHandlerServeCSPHeader(t *testing.T) { response := httptest.NewRecorder() handler.ServeHTTP(response, request) assert.Equal(t, 200, response.Code) - assert.Equal(t, response.Header()["Content-Security-Policy"], []string{"frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com cdn.segment.com/analytics.js/"}) + assert.Equal(t, response.Header()["Content-Security-Policy"], []string{"frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com"}) // TODO: It's hard to unit test this now that the CSP directive is effectively // decided in Setup(). Circle back to this in master once the memory store is // merged, allowing us to mock the desired initial config to take effect in Setup(). - // assert.Contains(t, response.Header()["Content-Security-Policy"], "frame-ancestors 'self'; script-src 'self' cdn.segment.com/analytics.js/ 'sha256-tPOjw+tkVs9axL78ZwGtYl975dtyPHB6LYKAO2R3gR4='") + // assert.Contains(t, response.Header()["Content-Security-Policy"], "frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com 'sha256-tPOjw+tkVs9axL78ZwGtYl975dtyPHB6LYKAO2R3gR4='") th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = *cfg.ServiceSettings.SiteURL + "/subpath2" @@ -352,9 +352,9 @@ func TestHandlerServeCSPHeader(t *testing.T) { response = httptest.NewRecorder() handler.ServeHTTP(response, request) assert.Equal(t, 200, response.Code) - assert.Equal(t, response.Header()["Content-Security-Policy"], []string{"frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com cdn.segment.com/analytics.js/"}) + assert.Equal(t, response.Header()["Content-Security-Policy"], []string{"frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com"}) // TODO: See above. - // assert.Contains(t, response.Header()["Content-Security-Policy"], "frame-ancestors 'self'; script-src 'self' cdn.segment.com/analytics.js/ 'sha256-tPOjw+tkVs9axL78ZwGtYl975dtyPHB6LYKAO2R3gR4='", "csp header incorrectly changed after subpath changed") + // assert.Contains(t, response.Header()["Content-Security-Policy"], "frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com 'sha256-tPOjw+tkVs9axL78ZwGtYl975dtyPHB6LYKAO2R3gR4='", "csp header incorrectly changed after subpath changed") }) }