diff --git a/README.md b/README.md index dc1af16..d0fef87 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,3 @@ Shows ES cluster health details An example of event structure is here [testdata/exampleEnrichedContentModel.json](testdata/exampleEnrichedContentModel.json) The reference mappings for Elasticsearch are found here [runtime/referenceSchema.json](runtime/referenceSchema.json) - -### Logging - -* The application uses [logrus](https://github.com/Sirupsen/logrus); the log file is initialised in [main.go](main.go). -* NOTE: `/__build-info` and `/__gtg` endpoints are not logged as they are called every second from varnish/vulcand and this information is not needed in logs/splunk. diff --git a/content_indexer.go b/content_indexer.go index bcb141a..5610b75 100644 --- a/content_indexer.go +++ b/content_indexer.go @@ -3,15 +3,15 @@ package main import ( "encoding/json" health "github.com/Financial-Times/go-fthealth/v1_1" + "github.com/Financial-Times/go-logger" "github.com/Financial-Times/message-queue-gonsumer/consumer" status "github.com/Financial-Times/service-status-go/httphandlers" - log "github.com/Sirupsen/logrus" + "github.com/dchest/uniuri" "net" "net/http" "strings" "sync" "time" - "github.com/dchest/uniuri" ) const ( @@ -49,11 +49,11 @@ func (indexer *contentIndexer) start(appSystemCode string, appName string, index for { ec, err := newAmazonClient(accessConfig) if err == nil { - log.Infof("connected to Elasticsearch") + logger.Info("Connected to Elasticsearch") channel <- ec return } - log.Errorf("could not connect to Elasticsearch: %s", err.Error()) + logger.Error("Could not connect to Elasticsearch") time.Sleep(time.Minute) } }() @@ -80,7 +80,7 @@ func (indexer *contentIndexer) stop() { indexer.mu.Unlock() }() if err := indexer.server.Close(); err != nil { - log.Errorf("Unable to stop http server: %v", err) + logger.WithError(err).Error("Unable to stop http server") } indexer.wg.Wait() } @@ -101,7 +101,7 @@ func (indexer *contentIndexer) serveAdminEndpoints(appSystemCode string, appName indexer.wg.Add(1) go func() { if err := indexer.server.ListenAndServe(); err != nil { - log.Infof("HTTP server closing with message: %v", err) + logger.WithError(err).Error("HTTP server is closing") } indexer.wg.Done() }() @@ -135,33 +135,33 @@ func (indexer *contentIndexer) handleMessage(msg consumer.Message) { tid := msg.Headers[transactionIDHeader] if tid == "" { tid = "tid_" + uniuri.NewLen(10) + "_content-rw-elasticsearch" - log.Infof("Generated tid: %d", tid) + logger.WithTransactionID(tid).Info("Generated tid") } if strings.Contains(tid, syntheticRequestPrefix) { - log.Infof("[%s] Ignoring synthetic message", tid) + logger.WithTransactionID(tid).Info("Ignoring synthetic message") return } var combinedPostPublicationEvent enrichedContentModel err := json.Unmarshal([]byte(msg.Body), &combinedPostPublicationEvent) if err != nil { - log.Errorf("[%s] Cannot unmarshal message body:[%v]", tid, err.Error()) + logger.WithTransactionID(tid).WithError(err).Error("Cannot unmarshal message body") return } if !contains(allowedTypes, combinedPostPublicationEvent.Content.Type) { - log.Infof("[%s] Ignoring message of type %s", tid, combinedPostPublicationEvent.Content.Type) + logger.WithTransactionID(tid).Infof("Ignoring message of type %s", combinedPostPublicationEvent.Content.Type) return } if combinedPostPublicationEvent.Content.UUID == "" { - log.Infof("[%s] Ignoring message with no content for UUID: %s", tid, combinedPostPublicationEvent.UUID) + logger.WithTransactionID(tid).WithUUID(combinedPostPublicationEvent.UUID).Info("Ignoring message with no content for UUID") return } uuid := combinedPostPublicationEvent.UUID - log.Infof("[%s] Processing combined post publication event for uuid [%s]", tid, uuid) + logger.WithTransactionID(tid).WithUUID(uuid).Info("Processing combined post publication event") var contentType string for _, identifier := range combinedPostPublicationEvent.Content.Identifiers { @@ -183,7 +183,7 @@ func (indexer *contentIndexer) handleMessage(msg consumer.Message) { } else if strings.Contains(origin, videoOrigin) { contentType = videoType } else { - log.Errorf("[%s] Failed to index content with UUID %s. Could not infer type of content.", tid, uuid) + logger.WithTransactionID(tid).WithUUID(uuid).WithError(err).Error("Failed to index content. Could not infer type of content") return } } @@ -191,17 +191,19 @@ func (indexer *contentIndexer) handleMessage(msg consumer.Message) { if combinedPostPublicationEvent.Content.MarkedDeleted { _, err = indexer.esServiceInstance.deleteData(contentTypeMap[contentType].collection, uuid) if err != nil { - log.Errorf("[%s] Failed to index content with UUID %s. Error: [%s]", tid, uuid, err.Error()) + logger.WithTransactionID(tid).WithUUID(uuid).WithError(err).Error("Failed to index content") return } + logger.WithMonitoringEvent("ContentDeleteElasticsearch", tid, "").WithUUID(uuid).Info("Successfully deleted") } else { payload := convertToESContentModel(combinedPostPublicationEvent, contentType, tid) _, err = indexer.esServiceInstance.writeData(contentTypeMap[contentType].collection, uuid, payload) if err != nil { - log.Errorf("[%s] Failed to index content with UUID %s. Error: [%s]", tid, uuid, err.Error()) + logger.WithTransactionID(tid).WithUUID(uuid).WithError(err).Error("Failed to index content") return } + logger.WithMonitoringEvent("ContentWriteElasticsearch", tid, "").WithUUID(uuid).Info("Successfully saved") } } diff --git a/content_indexer_test.go b/content_indexer_test.go index 72dc298..cb20d3b 100644 --- a/content_indexer_test.go +++ b/content_indexer_test.go @@ -1,17 +1,17 @@ package main import ( + logTest "github.com/Financial-Times/go-logger/test" "github.com/Financial-Times/message-queue-gonsumer/consumer" - "github.com/Sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "gopkg.in/olivere/elastic.v2" "io/ioutil" "net/url" "strings" - "sync" "testing" "time" + "github.com/stretchr/testify/require" ) type esServiceMock struct { @@ -75,36 +75,6 @@ func (client elasticClientMock) PerformRequest(method, path string, params url.V return args.Get(0).(*elastic.Response), args.Error(1) } -type logHook struct { - sync.Mutex - Entries []*logrus.Entry -} - -func (hook *logHook) Fire(e *logrus.Entry) error { - hook.Lock() - defer hook.Unlock() - hook.Entries = append(hook.Entries, e) - return nil -} - -func (hook *logHook) Levels() []logrus.Level { - return logrus.AllLevels -} - -func (hook *logHook) LastEntry() (l *logrus.Entry) { - hook.Lock() - defer hook.Unlock() - if i := len(hook.Entries) - 1; i >= 0 { - return hook.Entries[i] - } - return nil -} - -// Reset removes all Entries from this test hook. -func (hook *logHook) Reset() { - hook.Entries = make([]*logrus.Entry, 0) -} - func TestStartClient(t *testing.T) { assert := assert.New(t) @@ -143,8 +113,7 @@ func TestStartClient(t *testing.T) { func TestStartClientError(t *testing.T) { assert := assert.New(t) - hook := &logHook{} - logrus.AddHook(hook) + hook := logTest.NewTestHook("content-rw-elasticsearch") accessConfig := esAccessConfig{ accessKey: "key", @@ -171,6 +140,7 @@ func TestStartClientError(t *testing.T) { time.Sleep(100 * time.Millisecond) + require.NotNil(t, hook.LastEntry()) assert.Equal("error", hook.LastEntry().Level.String(), "Wrong log") assert.NotNil(indexer.esServiceInstance, "Elastic Service should be initialized") assert.Equal("index", (indexer.esServiceInstance).(*esService).indexName, "Wrong index") @@ -264,8 +234,7 @@ func TestHandleWriteMessageUnknownType(t *testing.T) { func TestHandleWriteMessageNoUUIDForMetadataPublish(t *testing.T) { assert := assert.New(t) - hook := &logHook{} - logrus.AddHook(hook) + hook := logTest.NewTestHook("content-rw-elasticsearch") inputJSON, err := ioutil.ReadFile("testdata/testInput4.json") assert.NoError(err, "Unexpected error") @@ -278,14 +247,15 @@ func TestHandleWriteMessageNoUUIDForMetadataPublish(t *testing.T) { serviceMock.AssertNotCalled(t, "writeData", mock.Anything, "b17756fe-0f62-4cf1-9deb-ca7a2ff80172", mock.Anything) serviceMock.AssertNotCalled(t, "deleteData", mock.Anything, "b17756fe-0f62-4cf1-9deb-ca7a2ff80172") serviceMock.AssertExpectations(t) + + require.NotNil(t, hook.LastEntry()) assert.Equal("info", hook.LastEntry().Level.String(), "Wrong log") } func TestHandleWriteMessageNoType(t *testing.T) { assert := assert.New(t) - hook := &logHook{} - logrus.AddHook(hook) + hook := logTest.NewTestHook("content-rw-elasticsearch") inputJSON, err := ioutil.ReadFile("testdata/exampleEnrichedContentModel.json") assert.NoError(err, "Unexpected error") @@ -298,14 +268,14 @@ func TestHandleWriteMessageNoType(t *testing.T) { serviceMock.AssertNotCalled(t, "writeData", mock.Anything, mock.Anything, mock.Anything) serviceMock.AssertNotCalled(t, "deleteData", mock.Anything, mock.Anything) + require.NotNil(t, hook.LastEntry()) assert.Equal("error", hook.LastEntry().Level.String(), "Wrong log") } func TestHandleWriteMessageError(t *testing.T) { assert := assert.New(t) - hook := &logHook{} - logrus.AddHook(hook) + hook := logTest.NewTestHook("content-rw-elasticsearch") inputJSON, err := ioutil.ReadFile("testdata/exampleEnrichedContentModel.json") assert.NoError(err, "Unexpected error") @@ -318,6 +288,7 @@ func TestHandleWriteMessageError(t *testing.T) { indexer.handleMessage(consumer.Message{Body: string(inputJSON)}) serviceMock.AssertExpectations(t) + require.NotNil(t, hook.LastEntry()) assert.Equal("error", hook.LastEntry().Level.String(), "Wrong log") } @@ -341,8 +312,7 @@ func TestHandleDeleteMessage(t *testing.T) { func TestHandleDeleteMessageError(t *testing.T) { assert := assert.New(t) - hook := &logHook{} - logrus.AddHook(hook) + hook := logTest.NewTestHook("content-rw-elasticsearch") inputJSON, err := ioutil.ReadFile("testdata/exampleEnrichedContentModel.json") assert.NoError(err, "Unexpected error") @@ -356,20 +326,21 @@ func TestHandleDeleteMessageError(t *testing.T) { indexer.handleMessage(consumer.Message{Body: input}) serviceMock.AssertExpectations(t) + require.NotNil(t, hook.LastEntry()) assert.Equal("error", hook.LastEntry().Level.String(), "Wrong log") } func TestHandleMessageJsonError(t *testing.T) { assert := assert.New(t) - hook := &logHook{} - logrus.AddHook(hook) + hook := logTest.NewTestHook("content-rw-elasticsearch") serviceMock := &esServiceMock{} indexer := &contentIndexer{esServiceInstance: serviceMock} indexer.handleMessage(consumer.Message{Body: "malformed json"}) + require.NotNil(t, hook.LastEntry()) assert.Equal("error", hook.LastEntry().Level.String(), "Wrong log") serviceMock.AssertNotCalled(t, "writeData", mock.Anything, mock.Anything, mock.Anything) serviceMock.AssertNotCalled(t, "deleteData", mock.Anything, mock.Anything) @@ -378,13 +349,13 @@ func TestHandleMessageJsonError(t *testing.T) { func TestHandleSyntheticMessage(t *testing.T) { assert := assert.New(t) - hook := &logHook{} - logrus.AddHook(hook) + hook := logTest.NewTestHook("content-rw-elasticsearch") serviceMock := &esServiceMock{} indexer := &contentIndexer{esServiceInstance: serviceMock} indexer.handleMessage(consumer.Message{Headers: map[string]string{"X-Request-Id": "SYNTHETIC-REQ-MON_WuLjbRpCgh"}}) + require.NotNil(t, hook.LastEntry()) assert.Equal("info", hook.LastEntry().Level.String(), "Wrong log") serviceMock.AssertNotCalled(t, "writeData", mock.Anything, mock.Anything, mock.Anything) serviceMock.AssertNotCalled(t, "deleteData", mock.Anything, mock.Anything) diff --git a/es_client.go b/es_client.go index 9e7ef75..bf63f82 100644 --- a/es_client.go +++ b/es_client.go @@ -1,10 +1,10 @@ package main import ( - log "github.com/Sirupsen/logrus" awsauth "github.com/smartystreets/go-aws-auth" "gopkg.in/olivere/elastic.v2" "net/http" + "github.com/Financial-Times/go-logger" ) type esClientI interface { @@ -47,6 +47,6 @@ var newAmazonClient = func(config esAccessConfig) (esClientI, error) { elastic.SetScheme("https"), elastic.SetHttpClient(signingClient), elastic.SetSniff(false), //needs to be disabled due to EAS behavior. Healthcheck still operates as normal. - elastic.SetErrorLog(log.New()), + elastic.SetErrorLog(logger.Logger()), ) } diff --git a/healthcheck.go b/healthcheck.go index 27e46b5..d40483e 100644 --- a/healthcheck.go +++ b/healthcheck.go @@ -10,7 +10,7 @@ import ( health "github.com/Financial-Times/go-fthealth/v1_1" "github.com/Financial-Times/message-queue-gonsumer/consumer" "github.com/Financial-Times/service-status-go/gtg" - log "github.com/Sirupsen/logrus" + "github.com/Financial-Times/go-logger" ) type healthService struct { @@ -150,6 +150,6 @@ func (service *healthService) HealthDetails(writer http.ResponseWriter, req *htt _, err = writer.Write(response) if err != nil { - log.Errorf(err.Error()) + logger.WithError(err).Error(err.Error()) } } diff --git a/main.go b/main.go index 5ff157a..ec0e7b1 100644 --- a/main.go +++ b/main.go @@ -1,14 +1,21 @@ package main import ( + "github.com/Financial-Times/go-logger" "github.com/Financial-Times/message-queue-gonsumer/consumer" - log "github.com/Sirupsen/logrus" "github.com/jawher/mow.cli" "os" "os/signal" "syscall" + "time" ) +const appNameDefaultValue = "content-rw-elasticsearch" + +func init() { + logger.InitDefaultLogger(appNameDefaultValue) +} + func main() { app := cli.App("content-rw-elasticsearch", "Service for loading contents into elasticsearch") @@ -21,7 +28,7 @@ func main() { appName := app.String(cli.StringOpt{ Name: "app-name", - Value: "Content RW Elasticsearch", + Value: appNameDefaultValue, Desc: "Application name", EnvVar: "APP_NAME", }) @@ -100,22 +107,21 @@ func main() { ConcurrentProcessing: *kafkaConcurrentProcessing, } - log.SetLevel(log.InfoLevel) - log.Infof("[Startup] Content RW Elasticsearch is starting ") + logger.Info("[Startup] Application is starting") app.Action = func() { indexer := contentIndexer{} indexer.start(*appSystemCode, *appName, *indexName, *port, accessConfig, queueConfig) waitForSignal() - log.Infof("[Shutdown] Content RW Elasticsearch is shutting down") + logger.Info("[Shutdown] Application is shutting down") indexer.stop() } err := app.Run(os.Args) if err != nil { - log.Errorf("App could not start, error=[%s]\n", err) + logger.WithError(err).WithTime(time.Now()).Fatal("App could not start") return } - log.Infof("[Shutdown] Content RW Elasticsearch shutdown complete") + logger.Info("[Shutdown] Shutdown complete") } func waitForSignal() { diff --git a/model.go b/model.go index 55b2169..9fa97c6 100644 --- a/model.go +++ b/model.go @@ -2,10 +2,10 @@ package main import ( "encoding/base64" - log "github.com/Sirupsen/logrus" + "github.com/Financial-Times/uuid-utils-go" "strings" "time" - "github.com/Financial-Times/uuid-utils-go" + "github.com/Financial-Times/go-logger" ) const ( @@ -259,7 +259,7 @@ func convertToESContentModel(enrichedContent enrichedContentModel, contentType s } if err != nil { - log.Warnf("Couldn't generate image uuid for the image set with uuid %s: image field won't be populated. Received error: %s", enrichedContent.Content.MainImage, err.Error()) + logger.WithError(err).Warnf("Couldn't generate image uuid for the image set with uuid %s: image field won't be populated.", enrichedContent.Content.MainImage) } *esModel.ThumbnailURL = strings.Replace(imageServiceURL, imagePlaceholder, imageID.String(), -1) @@ -278,8 +278,7 @@ func convertToESContentModel(enrichedContent enrichedContentModel, contentType s if len(annotation.Thing.TmeIDs) != 0 { tmeIDs = append(tmeIDs, annotation.Thing.TmeIDs...) } else { - log.Warnf("Indexing content with uuid %s - TME id missing for concept with id %s, using thing id instead", - enrichedContent.Content.UUID, fallbackID) + logger.Warnf("Indexing content with uuid %s - TME id missing for concept with id %s, using thing id instead", enrichedContent.Content.UUID, fallbackID) } for _, taxonomy := range annotation.Thing.Types { switch taxonomy { diff --git a/vendor/vendor.json b/vendor/vendor.json index 1ab3227..79b74e1 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -3,25 +3,29 @@ "ignore": "test", "package": [ { - "checksumSHA1": "huWiT3IqaHYWQcBWcYmEPkjFFyE=", - "path": "github.com/Financial-Times/content-rw-elasticsearch", - "revision": "28ec46fb13c51b69d977242e46bcfe5c6340ca77", - "revisionTime": "2017-06-14T14:04:47Z" - }, - { - "checksumSHA1": "2dtgENfeO6SICvxjruwb9f1CzLY=", + "checksumSHA1": "TVyK4buHhPUkpD0Pt9M7Zo2UAlI=", "path": "github.com/Financial-Times/go-fthealth/v1_1", "revision": "bc27ed19189994eef0364e4a07879d5a3f3be76f", "revisionTime": "2017-03-24T12:21:32Z" }, { - "checksumSHA1": "zUpINnstJChGK0LAtkt7jBc3RY0=", - "path": "github.com/Financial-Times/http-handlers-go/httphandlers", - "revision": "bb69c454da9050fe1c4b92fe1345a01583ee70be", - "revisionTime": "2016-08-03T10:40:03Z" + "checksumSHA1": "yco8EvtwVNKDpHLLemPvVh2PAqw=", + "path": "github.com/Financial-Times/go-logger", + "revision": "febee6537e90971bab6f6fe60b71b4a0562dcab3", + "revisionTime": "2018-03-23T12:41:13Z", + "version": "0.0.4", + "versionExact": "0.0.4" + }, + { + "checksumSHA1": "IZSWcIapbmDO8RlrPVyrgjn91QI=", + "path": "github.com/Financial-Times/go-logger/test", + "revision": "febee6537e90971bab6f6fe60b71b4a0562dcab3", + "revisionTime": "2018-03-23T12:41:13Z", + "version": "0.0.4", + "versionExact": "0.0.4" }, { - "checksumSHA1": "mirNgwWRdRte0ku/g4u4fNbzQP0=", + "checksumSHA1": "v+iZMRghLJr+LHe8ihEViOFE+9g=", "path": "github.com/Financial-Times/message-queue-gonsumer/consumer", "revision": "6f96a5cb1e34c4baa8bc64f56524a7f2e0092ed3", "revisionTime": "2017-06-22T11:17:49Z", @@ -29,31 +33,25 @@ "versionExact": "0.4.0" }, { - "checksumSHA1": "fqpohN7Qp2qj7TLMbUxh/cK4oH0=", + "checksumSHA1": "lQfsRf7gWYQDNoI3IOZuwNGUwRo=", "path": "github.com/Financial-Times/service-status-go/buildinfo", "revision": "3f5199736a3d7ae52394c63aac36834786825e21", "revisionTime": "2016-03-23T11:15:42Z" }, { - "checksumSHA1": "2rGNLXdRC3qr5n5ll7BpYt8HCK8=", + "checksumSHA1": "7QAsTdXi/6nTkDhqKy54YIc69d4=", "path": "github.com/Financial-Times/service-status-go/gtg", "revision": "3f5199736a3d7ae52394c63aac36834786825e21", "revisionTime": "2016-03-23T11:15:42Z" }, { - "checksumSHA1": "973POGyMCoyaKQuIYX2f7EKFwlQ=", + "checksumSHA1": "YxgjuCI4TJyfQujUeQk3V+gypzo=", "path": "github.com/Financial-Times/service-status-go/httphandlers", "revision": "3f5199736a3d7ae52394c63aac36834786825e21", "revisionTime": "2016-03-23T11:15:42Z" }, { - "checksumSHA1": "+sjiZBzrsk91W1A3Md1azCkZadg=", - "path": "github.com/Financial-Times/transactionid-utils-go", - "revision": "df2f00c734957c9dd651ce23ab0e0902504c7636", - "revisionTime": "2017-03-28T16:39:54Z" - }, - { - "checksumSHA1": "OctXH9nxfVzFlVWD7h4K5e+x5/M=", + "checksumSHA1": "SFO+8Q3GAkd8e/LaTdsJRu4OZLA=", "path": "github.com/Financial-Times/uuid-utils-go", "revision": "e22658edd0f130936e99079bf844bde7087c914c", "revisionTime": "2017-05-16T11:04:27Z", @@ -61,118 +59,128 @@ "versionExact": "1.0.1" }, { - "checksumSHA1": "ZKxETlJdB2XubMrZnXB0FQimVA8=", - "path": "github.com/Sirupsen/logrus", - "revision": "10f801ebc38b33738c9d17d50860f484a0988ff5", - "revisionTime": "2017-03-17T14:32:14Z" - }, - { - "checksumSHA1": "OFu4xJEIjiI8Suu+j/gabfp+y6Q=", + "checksumSHA1": "DuEyF75v9xaKXfJsCPRdHNOpGZk=", "origin": "github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew", "path": "github.com/davecgh/go-spew/spew", "revision": "4d4bfba8f1d1027c4fdbe371823030df51419987", "revisionTime": "2017-01-30T11:31:45Z" }, { - "checksumSHA1": "pXA0VXOMBMY18/4WFJjqnsT51jo=", + "checksumSHA1": "Cv1SPq5uwD7mx76IWwra244PF+g=", "path": "github.com/dchest/uniuri", "revision": "8902c56451e9b58ff940bbe5fec35d5f9c04584a", "revisionTime": "2016-02-12T16:43:26Z" }, { - "checksumSHA1": "zmCk+lgIeiOf0Ng9aFP9aFy8ksE=", - "path": "github.com/gorilla/mux", - "revision": "599cba5e7b6137d46ddf58fb1765f5d928e69604", - "revisionTime": "2017-02-28T22:43:54Z" - }, - { - "checksumSHA1": "tUGxc7rfX0cmhOOUDhMuAZ9rWsA=", + "checksumSHA1": "KJqRW8jfPoHquMAd6FI7x92JxFs=", "path": "github.com/hashicorp/go-version", "revision": "03c5bf6be031b6dd45afec16b1cf94fc8938bc77", "revisionTime": "2017-02-02T08:07:59Z" }, { - "checksumSHA1": "pYoO37aSFZl2uJAXpePBDnGItZc=", + "checksumSHA1": "rW0QSLVB0eUCzMdIL7yigeLBQ54=", "path": "github.com/jawher/mow.cli", "revision": "d3ffbc2f98b83e09dc8efd55ecec75eb5fd656ec", "revisionTime": "2017-02-20T22:51:54Z" }, { - "checksumSHA1": "eOXF2PEvYLMeD8DSzLZJWbjYzco=", - "path": "github.com/kr/pretty", - "revision": "cfb55aafdaf3ec08f0db22699ab822c50091b1c4", - "revisionTime": "2016-08-23T17:07:15Z" - }, - { - "checksumSHA1": "uulQHQ7IsRKqDudBC8Go9J0gtAc=", - "path": "github.com/kr/text", - "revision": "7cafcd837844e784b526369c9bce262804aebc60", - "revisionTime": "2016-05-04T02:26:26Z" - }, - { - "checksumSHA1": "zKKp5SZ3d3ycKe4EKMNT0BqAWBw=", + "checksumSHA1": "+oyIJwPyeof36XCkY8awrNfxaNM=", "origin": "github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib", "path": "github.com/pmezard/go-difflib/difflib", "revision": "4d4bfba8f1d1027c4fdbe371823030df51419987", "revisionTime": "2017-01-30T11:31:45Z" }, { - "checksumSHA1": "KAzbLjI9MzW2tjfcAsK75lVRp6I=", - "path": "github.com/rcrowley/go-metrics", - "revision": "1f30fe9094a513ce4c700b9a54458bbb0c96996c", - "revisionTime": "2016-11-28T21:05:44Z" + "checksumSHA1": "hXa0Yg8QcjnzQrd7823NalQitS8=", + "path": "github.com/sirupsen/logrus", + "revision": "c155da19408a8799da419ed3eeb0cb5db0ad5dbc", + "revisionTime": "2018-03-11T22:51:37Z", + "version": "v1.0.5", + "versionExact": "v1.0.5" + }, + { + "checksumSHA1": "bEYPw3QRqpj0ID7Q2FAr0xnF1Xw=", + "path": "github.com/sirupsen/logrus/hooks/test", + "revision": "c155da19408a8799da419ed3eeb0cb5db0ad5dbc", + "revisionTime": "2018-03-11T22:51:37Z", + "version": "v1.0.5", + "versionExact": "v1.0.5" }, { - "checksumSHA1": "iy7TNc01LWFOGwRwD6v0iDRqtLU=", + "checksumSHA1": "oNcjSQf1zGY27b9xipsqb2L4/RY=", "path": "github.com/smartystreets/go-aws-auth", "revision": "2043e6d0bb7e4c18464a7bba562acbe482e3cabd", "revisionTime": "2016-07-22T04:48:03Z" }, { - "checksumSHA1": "EO+jcRet/AJ6IY3lBO8l8BLsZWg=", + "checksumSHA1": "iDI3Ec9Co5dn9MAf6VRg5cGNRPI=", "origin": "github.com/stretchr/testify/vendor/github.com/stretchr/objx", "path": "github.com/stretchr/objx", "revision": "4d4bfba8f1d1027c4fdbe371823030df51419987", "revisionTime": "2017-01-30T11:31:45Z" }, { - "checksumSHA1": "JXUVA1jky8ZX8w09p2t5KLs97Nc=", + "checksumSHA1": "jOpeEFMbb70Y0RGoAnj0aYtLZWg=", "path": "github.com/stretchr/testify/assert", - "revision": "4d4bfba8f1d1027c4fdbe371823030df51419987", - "revisionTime": "2017-01-30T11:31:45Z" + "revision": "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c", + "revisionTime": "2017-12-30T17:54:59Z", + "version": "v1.2.0", + "versionExact": "v1.2.0" }, { - "checksumSHA1": "WGwMB6WljaeGKzuNCX5M4E8LADE=", + "checksumSHA1": "BTZ7ijqCXbpBeeDvex+TlnhkoDQ=", "path": "github.com/stretchr/testify/mock", - "revision": "4d4bfba8f1d1027c4fdbe371823030df51419987", - "revisionTime": "2017-01-30T11:31:45Z" + "revision": "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c", + "revisionTime": "2017-12-30T17:54:59Z", + "version": "v1.2.0", + "versionExact": "v1.2.0" }, { - "checksumSHA1": "6KZEap6v/5gD+tjiNbpD81kD61o=", + "checksumSHA1": "ya1eEQdc0qWt9OZGJaph/6oZStI=", + "path": "github.com/stretchr/testify/require", + "revision": "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c", + "revisionTime": "2017-12-30T17:54:59Z", + "version": "v1.2.0", + "versionExact": "v1.2.0" + }, + { + "checksumSHA1": "hRpSBofTFAM50mVLe4sID2rP2v8=", "path": "github.com/willf/bitset", "revision": "988f4f24992fc745de53c42df0da6581e42a6686", "revisionTime": "2017-05-05T19:16:46Z" }, { - "checksumSHA1": "Y+HGqEkYM15ir+J93MEaHdyFy0c=", - "path": "golang.org/x/net/context", - "revision": "05d3205156cb1bdc096578d6457fa161cd950aa2", - "revisionTime": "2017-03-29T00:59:59Z" + "checksumSHA1": "BGm8lKZmvJbf/YOJLeL1rw2WVjA=", + "path": "golang.org/x/crypto/ssh/terminal", + "revision": "80db560fac1fb3e6ac81dbc7f8ae4c061f5257bd", + "revisionTime": "2018-03-14T11:37:28Z" + }, + { + "checksumSHA1": "UBM+o5nmA/h/47jfqfoH2n8KlZo=", + "path": "golang.org/x/sys/unix", + "revision": "bb729a57828d76e3050e664d86aa052741ab620f", + "revisionTime": "2018-03-21T07:56:37Z" + }, + { + "checksumSHA1": "Dfz4tGItokMvHZENCsBmPPB8FGQ=", + "path": "golang.org/x/sys/windows", + "revision": "bb729a57828d76e3050e664d86aa052741ab620f", + "revisionTime": "2018-03-21T07:56:37Z" }, { - "checksumSHA1": "YaYXHmoUOYfWXu5TMM4k8ChZ8vY=", + "checksumSHA1": "lS6lXLd2ujduMzmQ8Z20Dt9QZyo=", "path": "gopkg.in/olivere/elastic.v2", "revision": "54283cb278d855e562a3d20f6c5afdbe1decf25b", "revisionTime": "2017-03-29T06:52:08Z" }, { - "checksumSHA1": "TYefriikhzyFZ9ynNHgYUjeoHgw=", + "checksumSHA1": "51/q8kpt63umcMuWOlTpKSUbnwM=", "path": "gopkg.in/olivere/elastic.v2/backoff", "revision": "54283cb278d855e562a3d20f6c5afdbe1decf25b", "revisionTime": "2017-03-29T06:52:08Z" }, { - "checksumSHA1": "O5dZe+m70S7vbkgePsMLrUc86DA=", + "checksumSHA1": "jWlBRALwERf/Gv46hCYr3AdiIS0=", "path": "gopkg.in/olivere/elastic.v2/uritemplates", "revision": "54283cb278d855e562a3d20f6c5afdbe1decf25b", "revisionTime": "2017-03-29T06:52:08Z"