From 2508e2130924e5f76efe32095aa1dc55f12fff85 Mon Sep 17 00:00:00 2001 From: Juan Manuel Perez Date: Thu, 19 Sep 2024 11:55:45 +0200 Subject: [PATCH] make timeout configurable --- args/args.go | 27 +++++++++---------- data/metric/metrics.go | 4 +-- go.mod | 22 ++++++++++++++++ go.sum | 52 +++++++++++++++++++++++++++++++++++++ integration/integration.go | 4 +-- integration/options_test.go | 11 +++++--- persist/store_path.go | 7 ++--- persist/storer.go | 2 -- persist/storer_test.go | 10 ++++--- 9 files changed, 111 insertions(+), 28 deletions(-) create mode 100644 go.mod create mode 100644 go.sum diff --git a/args/args.go b/args/args.go index 08aca0f..305deae 100644 --- a/args/args.go +++ b/args/args.go @@ -14,16 +14,17 @@ import ( // DefaultArgumentList includes the minimal set of necessary arguments for an integration. // If all data flags (Inventory, Metrics and Events) are false, all of them are published. type DefaultArgumentList struct { - Verbose bool `default:"false" help:"Print more information to logs."` - Pretty bool `default:"false" help:"Print pretty formatted JSON."` - Metrics bool `default:"false" help:"Publish metrics data."` - Inventory bool `default:"false" help:"Publish inventory data."` - Events bool `default:"false" help:"Publish events data."` - Metadata bool `default:"false" help:"Add customer defined key-value attributes to the samples."` - NriAddHostname bool `default:"false" help:"Add hostname attribute to the samples."` - NriCluster string `default:"" help:"Optional. Cluster name"` - NriService string `default:"" help:"Optional. Service name"` - TempDir string `default:"" help:"Optional. Integrations path to store temporal data (defaults to os.tempDir if left empty)."` + Verbose bool `default:"false" help:"Print more information to logs."` + Pretty bool `default:"false" help:"Print pretty formatted JSON."` + Metrics bool `default:"false" help:"Publish metrics data."` + Inventory bool `default:"false" help:"Publish inventory data."` + Events bool `default:"false" help:"Publish events data."` + Metadata bool `default:"false" help:"Add customer defined key-value attributes to the samples."` + NriAddHostname bool `default:"false" help:"Add hostname attribute to the samples."` + NriCluster string `default:"" help:"Optional. Cluster name"` + NriService string `default:"" help:"Optional. Service name"` + TempDir string `default:"" help:"Optional. Integrations path to store temporal data (defaults to os.tempDir if left empty)."` + CacheTTL time.Duration `default:"6*time.Minute" help:"Optional. The time the integration considers a temporal stored value as valid (defaults to 6 minutes left empty)."` } // All returns if all data should be published @@ -49,9 +50,9 @@ func (d *DefaultArgumentList) HasInventory() bool { // HTTPClientArgumentList are meant to be used as flags from a custom integrations. With this you could // send this arguments from the command line. type HTTPClientArgumentList struct { - HTTPCaBundleFile string `default: "" help: "Name of the certificate file"` - HTTPCaBundleDir string `default: "" help: "Path where the certificate exists"` - HTTPTimeout time.Duration `default:30 help: "Client http timeout in seconds"` + HTTPCaBundleFile string `default:"" help:"Name of the certificate file"` + HTTPCaBundleDir string `default:"" help:"Path where the certificate exists"` + HTTPTimeout time.Duration `default:"30" help:"Client http timeout in seconds"` } func getArgsFromEnv() func(f *flag.Flag) { diff --git a/data/metric/metrics.go b/data/metric/metrics.go index db21ba5..9679fd0 100644 --- a/data/metric/metrics.go +++ b/data/metric/metrics.go @@ -2,6 +2,7 @@ package metric import ( "encoding/json" + "errors" "fmt" "math" "sort" @@ -9,7 +10,6 @@ import ( "github.com/newrelic/infra-integrations-sdk/data/attribute" "github.com/newrelic/infra-integrations-sdk/persist" - "github.com/pkg/errors" ) const ( @@ -81,7 +81,7 @@ func (ms *Set) SetMetric(name string, value interface{}, sourceType SourceType) } newValue, errElapsed = ms.elapsedDifference(name, value, sourceType) if errElapsed != nil { - return errors.Wrapf(errElapsed, "cannot calculate elapsed difference for metric: %s value %v", name, value) + return fmt.Errorf("cannot calculate elapsed difference for metric: %s value %v: %w", name, value, errElapsed) } case GAUGE: newValue, err = castToFloat(value) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a651b5a --- /dev/null +++ b/go.mod @@ -0,0 +1,22 @@ +module github.com/newrelic/infra-integrations-sdk + +go 1.23 + +require github.com/stretchr/testify v1.9.0 + +require ( + github.com/AlekSi/gocov-xml v1.1.0 // indirect + github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect + github.com/axw/gocov v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/nicksnyder/go-i18n v1.10.3 // indirect + github.com/pelletier/go-toml v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 // indirect + gopkg.in/alecthomas/gometalinter.v2 v2.0.12 // indirect + gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20191105091915-95d230a53780 // indirect + gopkg.in/yaml.v2 v2.2.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a723c7f --- /dev/null +++ b/go.sum @@ -0,0 +1,52 @@ +github.com/AlekSi/gocov-xml v1.1.0 h1:iElWGi7s/MuL8/d8WDtI2fOAsN3ap9x8nK5RrAhaDng= +github.com/AlekSi/gocov-xml v1.1.0/go.mod h1:g1dRVOCHjKkMtlPfW6BokJ/qxoeZ1uPNAK7A/ii3CUo= +github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 h1:t3eaIm0rUkzbrIewtiFmMK5RXHej2XnoXNhxVsAYUfg= +github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +github.com/axw/gocov v1.1.0 h1:y5U1krExoJDlb/kNtzxyZQmNRprFOFCutWbNjcQvmVM= +github.com/axw/gocov v1.1.0/go.mod h1:H9G4tivgdN3pYSSVrTFBr6kGDCmAkgbJhtxFzAvgcdw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/nicksnyder/go-i18n v1.10.3 h1:0U60fnLBNrLBVt8vb8Q67yKNs+gykbQuLsIkiesJL+w= +github.com/nicksnyder/go-i18n v1.10.3/go.mod h1:hvLG5HTlZ4UfSuVLSRuX7JRUomIaoKQM19hm6f+no7o= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/alecthomas/gometalinter.v2 v2.0.12 h1:/xBWwtjmOmVxn8FXfIk9noV8m2E2Id9jFfUY/Mh9QAI= +gopkg.in/alecthomas/gometalinter.v2 v2.0.12/go.mod h1:NDRytsqEZyolNuAgTzJkZMkSQM7FIKyzVzGhjB/qfYo= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20191105091915-95d230a53780 h1:CEBpW6C191eozfEuWdUmIAHn7lwlLxJ7HVdr2e2Tsrw= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20191105091915-95d230a53780/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/integration/integration.go b/integration/integration.go index b4698f0..7b6f2c7 100644 --- a/integration/integration.go +++ b/integration/integration.go @@ -100,14 +100,14 @@ func New(name, version string, opts ...Option) (i *Integration, err error) { } if i.storer == nil { - storePath, err := persist.NewStorePath(i.Name, i.CreateUniqueID(), defaultArgs.TempDir, i.logger, persist.DefaultTTL) + storePath, err := persist.NewStorePath(i.Name, i.CreateUniqueID(), defaultArgs.TempDir, i.logger, defaultArgs.CacheTTL) if err != nil { return nil, fmt.Errorf("can't create temporary directory for store: %s", err) } storePath.CleanOldFiles() - i.storer, err = persist.NewFileStore(storePath.GetFilePath(), i.logger, persist.DefaultTTL) + i.storer, err = persist.NewFileStore(storePath.GetFilePath(), i.logger, defaultArgs.CacheTTL) if err != nil { return nil, fmt.Errorf("can't create store: %s", err) } diff --git a/integration/options_test.go b/integration/options_test.go index fb8bb94..f32b1e7 100644 --- a/integration/options_test.go +++ b/integration/options_test.go @@ -9,6 +9,7 @@ import ( "os" "strconv" "testing" + "time" "github.com/stretchr/testify/assert" @@ -17,6 +18,10 @@ import ( "github.com/newrelic/infra-integrations-sdk/persist" ) +const ( + TTL = 1 * time.Minute +) + func TestWriter(t *testing.T) { var w bytes.Buffer @@ -72,10 +77,10 @@ func TestItStoresOnDiskByDefault(t *testing.T) { assert.NoError(t, i.Publish()) // assert data has been flushed to disk - storePath, err := persist.NewStorePath(i.Name, i.CreateUniqueID(), "", i.logger, persist.DefaultTTL) + storePath, err := persist.NewStorePath(i.Name, i.CreateUniqueID(), "", i.logger, TTL) assert.NoError(t, err) - c, err := persist.NewFileStore(storePath.GetFilePath(), log.NewStdErr(true), persist.DefaultTTL) + c, err := persist.NewFileStore(storePath.GetFilePath(), log.NewStdErr(true), TTL) assert.NoError(t, err) var v float64 @@ -101,7 +106,7 @@ func TestInMemoryStoreDoesNotPersistOnDisk(t *testing.T) { path := persist.DefaultPath(randomName) assert.NoError(t, os.MkdirAll(path, 0755)) - s, err := persist.NewFileStore(path, log.Discard, persist.DefaultTTL) + s, err := persist.NewFileStore(path, log.Discard, TTL) assert.NoError(t, err) var v float64 diff --git a/persist/store_path.go b/persist/store_path.go index 99e3892..f6642e1 100644 --- a/persist/store_path.go +++ b/persist/store_path.go @@ -2,10 +2,11 @@ package persist import ( "fmt" - "github.com/newrelic/infra-integrations-sdk/log" "os" "path/filepath" "time" + + "github.com/newrelic/infra-integrations-sdk/log" ) const ( @@ -37,8 +38,8 @@ func NewStorePath(integrationName, integrationID, customTempDir string, ilog log return nil, fmt.Errorf("integration id not specified") } - if ttl == 0 { - ttl = DefaultTTL + if ttl <= 0 { + return nil, fmt.Errorf("invalid TTL: %d", ttl) } return &storePath{ diff --git a/persist/storer.go b/persist/storer.go index f708d98..6dda343 100644 --- a/persist/storer.go +++ b/persist/storer.go @@ -16,8 +16,6 @@ import ( ) const ( - // DefaultTTL specifies the "Time To Live" of the disk storage. - DefaultTTL = 1 * time.Minute filePerm = 0644 dirFilePerm = 0755 integrationsDir = "nr-integrations" diff --git a/persist/storer_test.go b/persist/storer_test.go index ef3a120..31758b2 100644 --- a/persist/storer_test.go +++ b/persist/storer_test.go @@ -13,6 +13,10 @@ import ( "github.com/stretchr/testify/assert" ) +const ( + TTL = 1 * time.Minute +) + // setNow forces a different "current time" for the storage. func setNow(newNow func() time.Time) { now = newNow @@ -43,7 +47,7 @@ func (j *diskStorerProvider) new() (Storer, error) { j.filePath = path.Join(j.t.TempDir(), "storage.json") } - return NewFileStore(j.filePath, log.NewStdErr(true), DefaultTTL) + return NewFileStore(j.filePath, log.NewStdErr(true), TTL) } func (j *diskStorerProvider) prepareToRead(s Storer) (Storer, error) { @@ -353,7 +357,7 @@ func TestFileStorer_Save(t *testing.T) { dir, err := ioutil.TempDir("", "filestorer_save") assert.NoError(t, err) filePath := path.Join(dir, "test.json") - storer, err := NewFileStore(filePath, log.NewStdErr(true), DefaultTTL) + storer, err := NewFileStore(filePath, log.NewStdErr(true), TTL) assert.NoError(t, err) type testStruct struct { @@ -374,7 +378,7 @@ func TestFileStorer_Save(t *testing.T) { storer.Save() // And a new storer opens the file - storer, err = NewFileStore(filePath, log.NewStdErr(true), DefaultTTL) + storer, err = NewFileStore(filePath, log.NewStdErr(true), TTL) assert.NoError(t, err) // The data is persisted as expected