diff --git a/.clabot b/.clabot index 035db1143..36e117be3 100644 --- a/.clabot +++ b/.clabot @@ -18,6 +18,6 @@ "$$$ Bots $$$", "dependabot", "dependabot[bot]", - "renovate" + "renovate[bot]" ] } diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 1e314f25c..8ab1b45d7 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,7 +1,7 @@ name: Build, Test, Lint License env: - GO_VERSION: "1.20.3" + GO_VERSION: "1.20.5" on: push: diff --git a/cmd/collectors/ems/ems.go b/cmd/collectors/ems/ems.go index 310cc467e..bd139c443 100644 --- a/cmd/collectors/ems/ems.go +++ b/cmd/collectors/ems/ems.go @@ -25,6 +25,7 @@ const defaultSeverityFilter = "alert|emergency|error|informational|notice" const MaxBookendInstances = 1000 const DefaultBookendResolutionDuration = 28 * 24 * time.Hour // 28 days == 672 hours const Hyphen = "-" +const AutoResolved = "autoresolved" type Ems struct { *rest2.Rest // provides: AbstractCollector, Client, Object, Query, TemplateFn, TemplateType @@ -340,11 +341,11 @@ func (e *Ems) PollInstance() (map[string]*matrix.Matrix, error) { func (e *Ems) PollData() (map[string]*matrix.Matrix, error) { var ( - count uint64 - apiD, parseD time.Duration - startTime time.Time - err error - records []gjson.Result + count, instanceCount uint64 + apiD, parseD time.Duration + startTime time.Time + err error + records []gjson.Result ) e.Logger.Debug().Msg("starting data poll") @@ -395,29 +396,15 @@ func (e *Ems) PollData() (map[string]*matrix.Matrix, error) { apiD = time.Since(startTime) - if len(records) == 0 { - e.lastFilterTime = toTime - _ = e.Metadata.LazySetValueInt64("api_time", "data", apiD.Microseconds()) - _ = e.Metadata.LazySetValueInt64("parse_time", "data", parseD.Microseconds()) - _ = e.Metadata.LazySetValueUint64("metrics", "data", 0) - _ = e.Metadata.LazySetValueUint64("instances", "data", 0) - return nil, nil - } - startTime = time.Now() - _, count = e.HandleResults(records, e.emsProp) + _, count, instanceCount = e.HandleResults(records, e.emsProp) parseD = time.Since(startTime) - var instanceCount int - for _, v := range e.Matrix { - instanceCount += len(v.GetInstances()) - } - _ = e.Metadata.LazySetValueInt64("api_time", "data", apiD.Microseconds()) _ = e.Metadata.LazySetValueInt64("parse_time", "data", parseD.Microseconds()) _ = e.Metadata.LazySetValueUint64("metrics", "data", count) - _ = e.Metadata.LazySetValueUint64("instances", "data", uint64(instanceCount)) + _ = e.Metadata.LazySetValueUint64("instances", "data", instanceCount) e.AddCollectCount(count) @@ -464,11 +451,11 @@ func parseProperties(instanceData gjson.Result, property string) gjson.Result { } // HandleResults function is used for handling the rest response for parent as well as endpoints calls, -func (e *Ems) HandleResults(result []gjson.Result, prop map[string][]*emsProp) (map[string]*matrix.Matrix, uint64) { +func (e *Ems) HandleResults(result []gjson.Result, prop map[string][]*emsProp) (map[string]*matrix.Matrix, uint64, uint64) { var ( - err error - count uint64 - mx *matrix.Matrix + err error + count, instanceCount uint64 + mx *matrix.Matrix ) var m = e.Matrix @@ -568,6 +555,10 @@ func (e *Ems) HandleResults(result []gjson.Result, prop map[string][]*emsProp) ( instance.SetExportable(true) for label, display := range p.InstanceLabels { + if label == AutoResolved { + instance.SetLabel(display, "") + continue + } value := parseProperties(instanceData, label) if value.Exists() { if value.IsArray() { @@ -652,7 +643,16 @@ func (e *Ems) HandleResults(result []gjson.Result, prop map[string][]*emsProp) ( count += instanceLabelCount } } - return m, count + + for _, v := range e.Matrix { + for _, i := range v.GetInstances() { + if i.IsExportable() { + instanceCount++ + } + } + } + + return m, count, instanceCount } func (e *Ems) getInstanceKeys(p *emsProp, instanceData gjson.Result) string { @@ -671,12 +671,6 @@ func (e *Ems) getInstanceKeys(p *emsProp, instanceData gjson.Result) string { } func (e *Ems) updateMatrix() { - var ( - ok bool - val float64 - eventMetric, timestampMetric *matrix.Metric - ) - tempMap := make(map[string]*matrix.Matrix) // store the bookend ems metric in tempMap for _, issuingEmsList := range e.bookendEmsMap { @@ -693,7 +687,8 @@ func (e *Ems) updateMatrix() { e.Matrix[e.Object] = mat for issuingEms, mx := range tempMap { - if eventMetric, ok = mx.GetMetrics()["events"]; !ok { + eventMetric, ok := mx.GetMetrics()["events"] + if !ok { e.Logger.Error(). Str("issuingEms", issuingEms). Str("name", "events"). @@ -701,7 +696,8 @@ func (e *Ems) updateMatrix() { continue } - if timestampMetric, ok = mx.GetMetrics()["timestamp"]; !ok { + timestampMetric, ok := mx.GetMetrics()["timestamp"] + if !ok { e.Logger.Error(). Str("issuingEms", issuingEms). Str("name", "timestamp"). @@ -712,14 +708,22 @@ func (e *Ems) updateMatrix() { // set export to false instance.SetExportable(false) - if val, ok = eventMetric.GetValueFloat64(instance); ok && val == 0 { + if val, exist := eventMetric.GetValueFloat64(instance); exist && val == 0 { mx.RemoveInstance(instanceKey) continue } + // check instance timestamp and remove it after given resolve_after duration if metricTimestamp, ok := timestampMetric.GetValueFloat64(instance); ok { if collectors.IsTimestampOlderThanDuration(metricTimestamp, e.resolveAfter[issuingEms]) { - mx.RemoveInstance(instanceKey) + // Set events metric value as 0 and export instance to true with label autoresolved as true. + if err := eventMetric.SetValueFloat64(instance, 0); err != nil { + e.Logger.Error().Err(err).Str("key", "events"). + Msg("Unable to set float key on metric") + continue + } + instance.SetExportable(true) + instance.SetLabel(AutoResolved, "true") } } } diff --git a/cmd/collectors/ems/ems_test.go b/cmd/collectors/ems/ems_test.go index 836c2e156..f0f1a3db5 100644 --- a/cmd/collectors/ems/ems_test.go +++ b/cmd/collectors/ems/ems_test.go @@ -11,11 +11,15 @@ import ( "github.com/rs/zerolog/log" "os" "testing" + "time" ) // Bookend EMS testing: Simulated bookend issuing ems "wafl.vvol.offline" and ems "hm.alert.raised" with alert_id value as "RaidLeftBehindAggrAlert" var issuingEmsNames = []string{"wafl.vvol.offline", "hm.alert.raised"} +// Auto resolve EMS testing: Simulated bookend issuing ems "LUN.offline" and ems "monitor.fan.critical" +var autoresolveEmsNames = []string{"LUN.offline", "monitor.fan.critical"} + func Test_Ems(t *testing.T) { // Initialize the Ems collector e := NewEms() @@ -30,6 +34,9 @@ func BookendEmsTest(t *testing.T, e *Ems) { // Step 2: Generate Bookend resolving ems e.testBookendResolvingEms(t, "testdata/resolvingEms.json") + + // Step 3: Generate Bookend issuing ems and validate auto resolution functionality + e.testAutoResolvingEms(t, "testdata/autoresolveEms.json") } func NewEms() *Ems { @@ -49,6 +56,9 @@ func NewEms() *Ems { if err := e.Init(ac); err != nil { log.Fatal().Err(err) } + // Changed the resolve_after for 2 issuing ems for auto resolve testing + e.resolveAfter["LUN.offline"] = 1 * time.Second + e.resolveAfter["monitor.fan.critical"] = 2 * time.Second return e } @@ -70,7 +80,7 @@ func (e *Ems) testBookendIssuingEms(t *testing.T, path string) { results := collectors.JSONToGson(path, true) // Polling ems collector to handle results - if _, emsCount := e.HandleResults(results, e.emsProp); emsCount == 0 { + if _, emsCount, _ := e.HandleResults(results, e.emsProp); emsCount == 0 { t.Fatal("Failed to fetch data") } @@ -79,8 +89,7 @@ func (e *Ems) testBookendIssuingEms(t *testing.T, path string) { for generatedEmsName, mx := range e.Matrix { if util.Contains(issuingEmsNames, generatedEmsName) { metr, ok := mx.GetMetrics()["events"] - // e.Matrix map would have one entry of Ems(parent) in map, skipping that as it's not required for testing. - if !ok && generatedEmsName != "Ems" { + if !ok { t.Fatalf("Failed to get netric for Ems %s", generatedEmsName) } for _, instance := range mx.GetInstances() { @@ -110,7 +119,7 @@ func (e *Ems) testBookendResolvingEms(t *testing.T, path string) { // Simulated bookend resolving ems "wafl.vvol.online" and ems "hm.alert.cleared" with alert_id value as "RaidLeftBehindAggrAlert" results := collectors.JSONToGson(path, true) // Polling ems collector to handle results - if _, emsCount := e.HandleResults(results, e.emsProp); emsCount == 0 { + if _, emsCount, _ := e.HandleResults(results, e.emsProp); emsCount == 0 { t.Fatal("Failed to fetch data") } @@ -119,8 +128,7 @@ func (e *Ems) testBookendResolvingEms(t *testing.T, path string) { for generatedEmsName, mx := range e.Matrix { if util.Contains(issuingEmsNames, generatedEmsName) { metr, ok := mx.GetMetrics()["events"] - // e.Matrix map would have one entry of Ems(parent) in map, skipping that as it's not required for testing. - if !ok && generatedEmsName != "Ems" { + if !ok { t.Fatalf("Failed to get netric for Ems %s", generatedEmsName) } for _, instance := range mx.GetInstances() { @@ -145,3 +153,82 @@ func (e *Ems) testBookendResolvingEms(t *testing.T, path string) { t.Errorf("These Bookend Ems haven't been resolved: %s", notResolvedEmsNames) } } + +func (e *Ems) testAutoResolvingEms(t *testing.T, path string) { + var notGeneratedEmsNames, notAutoResolvedEmsNames []string + e.updateMatrix() + + results := collectors.JSONToGson(path, true) + // Polling ems collector to handle results + if _, emsCount, _ := e.HandleResults(results, e.emsProp); emsCount == 0 { + t.Fatal("Failed to fetch data") + } + + // Check and evaluate ems events + for generatedEmsName, mx := range e.Matrix { + if util.Contains(autoresolveEmsNames, generatedEmsName) { + if metr, ok := mx.GetMetrics()["events"]; ok { + for _, instance := range mx.GetInstances() { + // If value not exist for that instance or metric value 0 indicate ems hasn't been raised. + if val, ok := metr.GetValueFloat64(instance); !ok || val == 0 { + notGeneratedEmsNames = append(notGeneratedEmsNames, generatedEmsName) + } + } + } else { + t.Fatalf("Failed to get netric for Ems %s", generatedEmsName) + } + } + } + if len(notGeneratedEmsNames) > 0 { + t.Fatalf("These Bookend Ems haven't been raised: %s", notGeneratedEmsNames) + } + + // Evaluate the cache for existence of these auto resolve ems. + // Sleep for 1 second and check LUN.offline ems got auto resolved + time.Sleep(1 * time.Second) + e.updateMatrix() + // Check and evaluate bookend ems events got auto resolved successfully. + for generatedEmsName, mx := range e.Matrix { + if util.Contains(autoresolveEmsNames, generatedEmsName) { + if metr, ok := mx.GetMetrics()["events"]; ok { + for _, instance := range mx.GetInstances() { + // If value not exist for that instance or metric value 0 indicate ems hasn't been raised. + if val, ok := metr.GetValueFloat64(instance); !ok || val == 1 { + notAutoResolvedEmsNames = append(notAutoResolvedEmsNames, generatedEmsName) + } + } + } else { + t.Fatalf("Failed to get netric for Ems %s", generatedEmsName) + } + } + } + if util.Contains(notAutoResolvedEmsNames, "LUN.offline") { + t.Fatalf("These Bookend Ems haven't been auto resolved: %s", notAutoResolvedEmsNames) + } + + // Sleep for another 1 second and check "LUN.offline" ems got removed from cache and "monitor.fan.critical" got auto resolved + time.Sleep(1 * time.Second) + e.updateMatrix() + notAutoResolvedEmsNames = make([]string, 0) + // Check bookend ems event got removed from cache successfully. + if e.Matrix["LUN.offline"] != nil { + t.Fatalf("These Bookend Ems haven't been removed from cache: %s", "LUN.offline") + } + for generatedEmsName, mx := range e.Matrix { + if util.Contains(autoresolveEmsNames, generatedEmsName) { + if metr, ok := mx.GetMetrics()["events"]; ok { + for _, instance := range mx.GetInstances() { + // If value not exist for that instance or metric value 0 indicate ems hasn't been raised. + if val, ok := metr.GetValueFloat64(instance); !ok || val == 1 { + notAutoResolvedEmsNames = append(notAutoResolvedEmsNames, generatedEmsName) + } + } + } else { + t.Fatalf("Failed to get netric for Ems %s", generatedEmsName) + } + } + } + if util.Contains(notAutoResolvedEmsNames, "monitor.fan.critical") { + t.Fatalf("These Bookend Ems haven't been auto resolved: %s", notAutoResolvedEmsNames) + } +} diff --git a/cmd/collectors/ems/templating.go b/cmd/collectors/ems/templating.go index 36373b616..8100130d2 100644 --- a/cmd/collectors/ems/templating.go +++ b/cmd/collectors/ems/templating.go @@ -158,4 +158,7 @@ func (e *Ems) ParseResolveEms(resolveEvent *node.Node, issueEmsProp emsProp) { } e.bookendEmsMap[resolveEmsName].Add(issueEmsProp.Name) e.emsProp[resolveEmsName] = append(e.emsProp[resolveEmsName], &prop) + + // add autoresolved label in issuingEms labels + issueEmsProp.InstanceLabels[AutoResolved] = AutoResolved } diff --git a/cmd/collectors/ems/testdata/autoresolveEms.json b/cmd/collectors/ems/testdata/autoresolveEms.json new file mode 100644 index 000000000..b56fea1c2 --- /dev/null +++ b/cmd/collectors/ems/testdata/autoresolveEms.json @@ -0,0 +1,86 @@ +{ + "records": [ + { + "node": { + "name": "umeng-aff300-01", + "uuid": "28e14eab-0580-11e8-bd9d-00a098d39e12", + "_links": { + "self": { + "href": "/api/cluster/nodes/28e14eab-0580-11e8-bd9d-00a098d39e12" + } + } + }, + "index": 41087737, + "time": "2023-05-12T21:13:00+12:00", + "message": { + "severity": "notice", + "name": "LUN.offline" + }, + "source": "notifyd", + "parameters": [ + { + "name": "lun_path", + "value": "1" + }, + { + "name": "volume_name", + "value": "2" + }, + { + "name": "volume_dsid", + "value": "3" + }, + { + "name": "object_uuid", + "value": "4" + }, + { + "name": "object_type", + "value": "5" + } + ], + "log_message": "LUN.offline: LUN 1, vol 2 (DSID 3) was brought offline (UUID: 4).", + "_links": { + "self": { + "href": "/api/support/ems/events/umeng-aff300-01/41087737" + } + } + }, + { + "node": { + "name": "umeng-aff300-01", + "uuid": "28e14eab-0580-11e8-bd9d-00a098d39e12", + "_links": { + "self": { + "href": "/api/cluster/nodes/28e14eab-0580-11e8-bd9d-00a098d39e12" + } + } + }, + "index": 41087738, + "time": "2023-05-12T21:13:15+12:00", + "message": { + "severity": "emergency", + "name": "monitor.fan.critical" + }, + "source": "notifyd", + "parameters": [ + { + "name": "report", + "value": "1" + } + ], + "log_message": "monitor.fan.critical: 1", + "_links": { + "self": { + "href": "/api/support/ems/events/umeng-aff300-01/41087738" + } + } + } + ], + "num_records": 2, + "_links": { + "self": { + "href": "/api/support/ems/events?return_records=true&fields=*&message.severity=alert|emergency|error|informational|notice&message.name=LUN.offline,monitor.fan.critical,callhome.battery.low&order_by=index%20asc" + } + } +} \ No newline at end of file diff --git a/cmd/collectors/restperf/plugins/volume/volume.go b/cmd/collectors/restperf/plugins/volume/volume.go index c79957294..f1d3355e2 100644 --- a/cmd/collectors/restperf/plugins/volume/volume.go +++ b/cmd/collectors/restperf/plugins/volume/volume.go @@ -11,18 +11,35 @@ import ( type Volume struct { *plugin.AbstractPlugin + styleType string } func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Volume{AbstractPlugin: p} } -func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, error) { +func (v *Volume) Init() error { + var err error + + if err = v.InitAbc(); err != nil { + return err + } + + v.styleType = "style" + + if v.Params.HasChildS("historicalLabels") { + v.styleType = "type" + } + return nil +} + +func (v *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, error) { var ( err error ) - data := dataMap[me.Object] + data := dataMap[v.Object] + style := v.styleType opsKeyPrefix := "temp_" re := regexp.MustCompile(`^(.*)__(\d{4})$`) @@ -35,10 +52,10 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro metric, err := volumeAggrmetric.NewMetricFloat64(metricName) if err != nil { - me.Logger.Error().Err(err).Msg("add metric") + v.Logger.Error().Err(err).Msg("add metric") return nil, err } - me.Logger.Trace().Msgf("added metric: (%s) %v", metricName, metric) + v.Logger.Trace().Msgf("added metric: (%s) %v", metricName, metric) cache := data.Clone(false, true, false) cache.UUID += ".Volume" @@ -55,7 +72,7 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro // Flexgroup don't show any aggregate, node fg.SetLabel("aggr", "") fg.SetLabel("node", "") - fg.SetLabel("style", "flexgroup") + fg.SetLabel(style, "flexgroup") } if volumeAggrmetric.GetInstance(key) == nil { @@ -64,32 +81,32 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro flexgroupInstance.SetLabel("volume", match[1]) // Flexgroup don't show any node flexgroupInstance.SetLabel("node", "") - flexgroupInstance.SetLabel("style", "flexgroup") + flexgroupInstance.SetLabel(style, "flexgroup") flexgroupAggrsMap[key] = set.New() if err := metric.SetValueFloat64(flexgroupInstance, 1); err != nil { - me.Logger.Error().Err(err).Str("metric", metricName).Msg("Unable to set value on metric") + v.Logger.Error().Err(err).Str("metric", metricName).Msg("Unable to set value on metric") } } flexgroupAggrsMap[key].Add(i.GetLabel("aggr")) - i.SetLabel("style", "flexgroup_constituent") + i.SetLabel(style, "flexgroup_constituent") i.SetExportable(false) } else { - i.SetLabel("style", "flexvol") + i.SetLabel(style, "flexvol") key := i.GetLabel("svm") + "." + i.GetLabel("volume") flexvolInstance, err := volumeAggrmetric.NewInstance(key) if err != nil { - me.Logger.Error().Err(err).Str("key", key).Msg("Failed to create new instance") + v.Logger.Error().Err(err).Str("key", key).Msg("Failed to create new instance") continue } flexvolInstance.SetLabels(i.GetLabels().Copy()) - flexvolInstance.SetLabel("style", "flexvol") + flexvolInstance.SetLabel(style, "flexvol") if err := metric.SetValueFloat64(flexvolInstance, 1); err != nil { - me.Logger.Error().Err(err).Str("metric", metricName).Msg("Unable to set value on metric") + v.Logger.Error().Err(err).Str("metric", metricName).Msg("Unable to set value on metric") } } } - me.Logger.Debug().Int("flexgroup volume count", len(cache.GetInstances())).Msg("") + v.Logger.Debug().Int("flexgroup volume count", len(cache.GetInstances())).Msg("") //cache.Reset() @@ -110,7 +127,7 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro fg := cache.GetInstance(key) if fg == nil { - me.Logger.Error().Msgf("instance [%s] not in local cache", key) + v.Logger.Error().Msgf("instance [%s] not in local cache", key) continue } @@ -122,11 +139,11 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro fgm := cache.GetMetric(mkey) if fgm == nil { - me.Logger.Error().Msgf("metric [%s] not in local cache", mkey) + v.Logger.Error().Msgf("metric [%s] not in local cache", mkey) continue } - me.Logger.Trace().Msgf("(%s) handling metric (%s)", fg.GetLabel("volume"), mkey) + v.Logger.Trace().Msgf("(%s) handling metric (%s)", fg.GetLabel("volume"), mkey) if value, ok := m.GetValueFloat64(i); ok { @@ -137,12 +154,12 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro err := fgm.SetValueFloat64(fg, fgv+value) if err != nil { - me.Logger.Error().Err(err).Msg("error") + v.Logger.Error().Err(err).Msg("error") } // just for debugging fgv2, _ := fgm.GetValueFloat64(fg) - me.Logger.Trace().Msgf(" > simple increment %f + %f = %f", fgv, value, fgv2) + v.Logger.Trace().Msgf(" > simple increment %f + %f = %f", fgv, value, fgv2) continue } @@ -151,7 +168,7 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro if strings.Contains(mkey, "_latency") { opsKey = m.GetComment() } - me.Logger.Trace().Msgf(" > weighted increment <%s * %s>", mkey, opsKey) + v.Logger.Trace().Msgf(" > weighted increment <%s * %s>", mkey, opsKey) if ops := data.GetMetric(opsKey); ops != nil { if opsValue, ok := ops.GetValueFloat64(i); ok { @@ -175,20 +192,20 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro if value != 0 { err = tempOps.SetValueFloat64(fg, tempOpsV+opsValue) if err != nil { - me.Logger.Error().Err(err).Msg("error") + v.Logger.Error().Err(err).Msg("error") } } err = fgm.SetValueFloat64(fg, fgv+prod) if err != nil { - me.Logger.Error().Err(err).Msg("error") + v.Logger.Error().Err(err).Msg("error") } // debugging fgv2, _ := fgm.GetValueFloat64(fg) - me.Logger.Trace().Msgf(" %f + (%f * %f) (=%f) = %f", fgv, value, opsValue, prod, fgv2) + v.Logger.Trace().Msgf(" %f + (%f * %f) (=%f) = %f", fgv, value, opsValue, prod, fgv2) } else { - me.Logger.Trace().Msg(" no ops value SKIP") + v.Logger.Trace().Msg(" no ops value SKIP") } } @@ -215,7 +232,7 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro if opsValue, ok := ops.GetValueFloat64(i); ok && opsValue != 0 { err := m.SetValueFloat64(i, value/opsValue) if err != nil { - me.Logger.Error().Err(err).Msgf("error") + v.Logger.Error().Err(err).Msgf("error") } } else { m.SetValueNAN(i) diff --git a/cmd/collectors/restperf/restperf.go b/cmd/collectors/restperf/restperf.go index e223d5586..79cacc9ac 100644 --- a/cmd/collectors/restperf/restperf.go +++ b/cmd/collectors/restperf/restperf.go @@ -1248,10 +1248,11 @@ func (r *RestPerf) PollInstance() (map[string]*matrix.Matrix, error) { ) dataQuery := path.Join(r.Prop.Query, "rows") - fields := "*" + fields := "properties" var filter []string if isWorkloadObject(r.Prop.Query) || isWorkloadDetailObject(r.Prop.Query) { + fields = "*" dataQuery = qosWorkloadQuery if r.Prop.Query == qosVolumeQuery || r.Prop.Query == qosDetailVolumeQuery { filter = append(filter, "workload-class=autovolume") diff --git a/cmd/collectors/restperf/restperf_test.go b/cmd/collectors/restperf/restperf_test.go index e73252f2d..e6c48115c 100644 --- a/cmd/collectors/restperf/restperf_test.go +++ b/cmd/collectors/restperf/restperf_test.go @@ -67,9 +67,10 @@ func Test_parseMetricResponse(t *testing.T) { } var ( - ms []*matrix.Matrix - benchPerf *RestPerf - fullPollData []rest.PerfRecord + ms []*matrix.Matrix + benchPerf *RestPerf + fullPollData []rest.PerfRecord + propertiesData []rest.PerfRecord ) func TestMain(m *testing.M) { @@ -79,9 +80,10 @@ func TestMain(m *testing.M) { counters := jsonToPerfRecords("testdata/volume-counters.json") _, _ = benchPerf.pollCounter(counters[0].Records.Array()) now := time.Now().Truncate(time.Second) + propertiesData = jsonToPerfRecords("testdata/volume-poll-properties.json.gz") fullPollData = jsonToPerfRecords("testdata/volume-poll-full.json.gz") fullPollData[0].Timestamp = now.UnixNano() - _, _ = benchPerf.pollInstance(fullPollData[0].Records.Array()) + _, _ = benchPerf.pollInstance(propertiesData[0].Records.Array()) _, _ = benchPerf.pollData(now, fullPollData) os.Exit(m.Run()) @@ -95,7 +97,7 @@ func BenchmarkRestPerf_PollData(b *testing.B) { for i := 0; i < b.N; i++ { now = now.Add(time.Minute * 15) fullPollData[0].Timestamp = now.UnixNano() - mi, _ := benchPerf.pollInstance(fullPollData[0].Records.Array()) + mi, _ := benchPerf.pollInstance(propertiesData[0].Records.Array()) for _, mm := range mi { ms = append(ms, mm) } @@ -114,6 +116,7 @@ func TestRestPerf_pollData(t *testing.T) { tests := []struct { name string wantErr bool + pollInstance string pollDataPath1 string pollDataPath2 string numInstances int @@ -126,6 +129,7 @@ func TestRestPerf_pollData(t *testing.T) { name: "bytes_read", counter: "bytes_read", pollCounters: "testdata/volume-counters.json", + pollInstance: "testdata/volume-poll-instance.json", pollDataPath1: "testdata/volume-poll-1.json", pollDataPath2: "testdata/volume-poll-2.json", numInstances: 2, @@ -142,9 +146,9 @@ func TestRestPerf_pollData(t *testing.T) { if err != nil { t.Fatal(err) } - + pollInstance := jsonToPerfRecords(tt.pollInstance) pollData := jsonToPerfRecords(tt.pollDataPath1) - _, err = r.pollInstance(pollData[0].Records.Array()) + _, err = r.pollInstance(pollInstance[0].Records.Array()) if err != nil { t.Fatal(err) } diff --git a/cmd/collectors/restperf/testdata/volume-poll-full.json.gz b/cmd/collectors/restperf/testdata/volume-poll-full.json.gz index 674bf75e9..96cfbc8f1 100644 Binary files a/cmd/collectors/restperf/testdata/volume-poll-full.json.gz and b/cmd/collectors/restperf/testdata/volume-poll-full.json.gz differ diff --git a/cmd/collectors/restperf/testdata/volume-poll-instance.json b/cmd/collectors/restperf/testdata/volume-poll-instance.json new file mode 100644 index 000000000..8c64a22bd --- /dev/null +++ b/cmd/collectors/restperf/testdata/volume-poll-instance.json @@ -0,0 +1,92 @@ +{ + "records": [ + { + "counter_table": { + "name": "volume" + }, + "id": "umeng-aff300-01:arunima-test:harvest:cde3cfe9-de9a-11ed-a376-00a098d39e12", + "properties": [ + { + "name": "node.name", + "value": "umeng-aff300-01" + }, + { + "name": "node.uuid", + "value": "28e14eab-0580-11e8-bd9d-00a098d39e12" + }, + { + "name": "svm.name", + "value": "arunima-test" + }, + { + "name": "svm.uuid", + "value": "7693d638-f38c-11ec-9e8d-00a098d390f2" + }, + { + "name": "parent_aggregate", + "value": "umeng_aff300_aggr2" + }, + { + "name": "name", + "value": "harvest" + }, + { + "name": "uuid", + "value": "cde3cfe9-de9a-11ed-a376-00a098d39e12" + } + ], + "_links": { + "self": { + "href": "/api/cluster/counter/tables/volume/rows/umeng-aff300-01%3Aarunima-test%3Aharvest%3Acde3cfe9-de9a-11ed-a376-00a098d39e12" + } + } + }, + { + "counter_table": { + "name": "volume" + }, + "id": "umeng-aff300-01:astra_300:svm_root:a2944e62-2225-4dea-a4f2-93b3fdf11ed9", + "properties": [ + { + "name": "node.name", + "value": "umeng-aff300-01" + }, + { + "name": "node.uuid", + "value": "28e14eab-0580-11e8-bd9d-00a098d39e12" + }, + { + "name": "svm.name", + "value": "astra_300" + }, + { + "name": "svm.uuid", + "value": "835c0d25-ceb0-11eb-80e3-00a098d39e12" + }, + { + "name": "parent_aggregate", + "value": "umeng_aff300_aggr2" + }, + { + "name": "name", + "value": "svm_root" + }, + { + "name": "uuid", + "value": "a2944e62-2225-4dea-a4f2-93b3fdf11ed9" + } + ], + "_links": { + "self": { + "href": "/api/cluster/counter/tables/volume/rows/umeng-aff300-01%3Aastra_300%3Asvm_root%3Aa2944e62-2225-4dea-a4f2-93b3fdf11ed9" + } + } + } + ], + "num_records": 2, + "_links": { + "self": { + "href": "/api/cluster/counter/tables/volume/rows?return_records=true&fields=*" + } + } +} \ No newline at end of file diff --git a/cmd/collectors/restperf/testdata/volume-poll-properties.json.gz b/cmd/collectors/restperf/testdata/volume-poll-properties.json.gz new file mode 100644 index 000000000..d955b565d Binary files /dev/null and b/cmd/collectors/restperf/testdata/volume-poll-properties.json.gz differ diff --git a/cmd/collectors/storagegrid/plugins/joinrest/joinrest.go b/cmd/collectors/storagegrid/plugins/joinrest/joinrest.go index cebe8340c..d4f6fa12a 100644 --- a/cmd/collectors/storagegrid/plugins/joinrest/joinrest.go +++ b/cmd/collectors/storagegrid/plugins/joinrest/joinrest.go @@ -4,7 +4,6 @@ import ( "github.com/netapp/harvest/v2/cmd/collectors/storagegrid/rest" "github.com/netapp/harvest/v2/cmd/poller/plugin" "github.com/netapp/harvest/v2/pkg/matrix" - "github.com/rs/zerolog/log" "github.com/tidwall/gjson" "gopkg.in/yaml.v3" "strings" @@ -56,7 +55,7 @@ func (t *JoinRest) Init() error { var tm translatePlugin err = decoder.Decode(&tm) if err != nil { - log.Error().Err(err).Msg("Failed to decode joinTemplate") + t.Logger.Error().Err(err).Msg("Failed to decode joinTemplate") return err } for _, p := range tm.Plugins { @@ -84,7 +83,7 @@ func (t *JoinRest) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, err for _, model := range t.translateMap { bytes, err := t.client.GetGridRest(model.Rest) if err != nil { - log.Error().Err(err).Str("rest", model.Rest).Msg("Failed to collect records from REST") + t.Logger.Error().Err(err).Str("rest", model.Rest).Msg("Failed to collect records from REST") continue } t.updateCache(model, &bytes) @@ -98,7 +97,7 @@ func (t *JoinRest) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, err } cache, ok := t.resourcesMap[model.Rest] if !ok { - log.Warn(). + t.Logger.Warn(). Str("metricName", metricName). Str("rest", model.Rest). Msg("Cache does not have resources for REST") @@ -107,7 +106,7 @@ func (t *JoinRest) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, err for _, instance := range m.GetInstances() { label := instance.GetLabel(model.WithProm) if label == "" { - log.Debug(). + t.Logger.Debug(). Str("metricName", metricName). Str("withProm", model.WithProm). Str("rest", model.Rest). @@ -116,7 +115,7 @@ func (t *JoinRest) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, err } newLabel, ok := cache[label] if !ok { - log.Debug(). + t.Logger.Debug(). Str("metricName", metricName). Str("withProm", model.WithProm). Str("label", label). diff --git a/cmd/collectors/zapiperf/plugins/volume/volume.go b/cmd/collectors/zapiperf/plugins/volume/volume.go index e9dfde61f..d41fb9711 100644 --- a/cmd/collectors/zapiperf/plugins/volume/volume.go +++ b/cmd/collectors/zapiperf/plugins/volume/volume.go @@ -15,22 +15,40 @@ import ( type Volume struct { *plugin.AbstractPlugin + styleType string } func New(p *plugin.AbstractPlugin) plugin.Plugin { return &Volume{AbstractPlugin: p} } +func (v *Volume) Init() error { + var err error + + if err = v.InitAbc(); err != nil { + return err + } + + v.styleType = "style" + + if v.Params.HasChildS("historicalLabels") { + v.styleType = "type" + } + return nil +} + //@TODO cleanup logging //@TODO rewrite using vector arithmetic // will simplify the code a whole!!! -func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, error) { +func (v *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, error) { var ( err error ) - data := dataMap[me.Object] + + data := dataMap[v.Object] + style := v.styleType opsKeyPrefix := "temp_" re := regexp.MustCompile(`^(.*)__(\d{4})$`) @@ -42,10 +60,10 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro metric, err := volumeAggrmetric.NewMetricFloat64(metricName) if err != nil { - me.Logger.Error().Err(err).Msg("add metric") + v.Logger.Error().Err(err).Msg("add metric") return nil, err } - me.Logger.Trace().Msgf("added metric: (%s) %v", metricName, metric) + v.Logger.Trace().Msgf("added metric: (%s) %v", metricName, metric) cache := data.Clone(false, true, false) cache.UUID += ".Volume" @@ -62,7 +80,7 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro // Flexgroup don't show any aggregate, node fg.SetLabel("aggr", "") fg.SetLabel("node", "") - fg.SetLabel("style", "flexgroup") + fg.SetLabel(style, "flexgroup") } if volumeAggrmetric.GetInstance(key) == nil { @@ -71,33 +89,33 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro flexgroupInstance.SetLabel("volume", match[1]) // Flexgroup don't show any node flexgroupInstance.SetLabel("node", "") - flexgroupInstance.SetLabel("style", "flexgroup") + flexgroupInstance.SetLabel(style, "flexgroup") flexgroupAggrsMap[key] = set.New() if err := metric.SetValueFloat64(flexgroupInstance, 1); err != nil { - me.Logger.Error().Err(err).Str("metric", metricName).Msg("Unable to set value on metric") + v.Logger.Error().Err(err).Str("metric", metricName).Msg("Unable to set value on metric") } } flexgroupAggrsMap[key].Add(i.GetLabel("aggr")) - i.SetLabel("style", "flexgroup_constituent") + i.SetLabel(style, "flexgroup_constituent") i.SetExportable(false) } else { - i.SetLabel("style", "flexvol") + i.SetLabel(style, "flexvol") key := i.GetLabel("svm") + "." + i.GetLabel("volume") flexvolInstance, err := volumeAggrmetric.NewInstance(key) if err != nil { - me.Logger.Error().Err(err).Str("key", key).Msg("Failed to create new instance") + v.Logger.Error().Err(err).Str("key", key).Msg("Failed to create new instance") continue } flexvolInstance.SetLabels(i.GetLabels().Copy()) - flexvolInstance.SetLabel("style", "flexvol") + flexvolInstance.SetLabel(style, "flexvol") if err := metric.SetValueFloat64(flexvolInstance, 1); err != nil { - me.Logger.Error().Err(err).Str("metric", metricName).Msg("Unable to set value on metric") + v.Logger.Error().Err(err).Str("metric", metricName).Msg("Unable to set value on metric") } } } - me.Logger.Debug().Msgf("extracted %d flexgroup volumes", len(cache.GetInstances())) + v.Logger.Debug().Msgf("extracted %d flexgroup volumes", len(cache.GetInstances())) //cache.Reset() @@ -118,7 +136,7 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro fg := cache.GetInstance(key) if fg == nil { - me.Logger.Error().Err(nil).Msgf("instance [%s] not in local cache", key) + v.Logger.Error().Err(nil).Msgf("instance [%s] not in local cache", key) continue } @@ -130,11 +148,11 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro fgm := cache.GetMetric(mkey) if fgm == nil { - me.Logger.Error().Err(nil).Msgf("metric [%s] not in local cache", mkey) + v.Logger.Error().Err(nil).Msgf("metric [%s] not in local cache", mkey) continue } - me.Logger.Trace().Msgf("(%s) handling metric (%s)", fg.GetLabel("volume"), mkey) + v.Logger.Trace().Msgf("(%s) handling metric (%s)", fg.GetLabel("volume"), mkey) if value, ok := m.GetValueFloat64(i); ok { @@ -145,12 +163,12 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro err := fgm.SetValueFloat64(fg, fgv+value) if err != nil { - me.Logger.Error().Err(err).Msg("error") + v.Logger.Error().Err(err).Msg("error") } // just for debugging fgv2, _ := fgm.GetValueFloat64(fg) - me.Logger.Trace().Msgf(" > simple increment %f + %f = %f", fgv, value, fgv2) + v.Logger.Trace().Msgf(" > simple increment %f + %f = %f", fgv, value, fgv2) continue } @@ -159,7 +177,7 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro if strings.Contains(mkey, "_latency") { opsKey = m.GetComment() } - me.Logger.Trace().Msgf(" > weighted increment <%s * %s>", mkey, opsKey) + v.Logger.Trace().Msgf(" > weighted increment <%s * %s>", mkey, opsKey) if ops := data.GetMetric(opsKey); ops != nil { if opsValue, ok := ops.GetValueFloat64(i); ok { @@ -183,20 +201,20 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro if value != 0 { err = tempOps.SetValueFloat64(fg, tempOpsV+opsValue) if err != nil { - me.Logger.Error().Err(err).Msg("error") + v.Logger.Error().Err(err).Msg("error") } } err = fgm.SetValueFloat64(fg, fgv+prod) if err != nil { - me.Logger.Error().Err(err).Msg("error") + v.Logger.Error().Err(err).Msg("error") } // debugging fgv2, _ := fgm.GetValueFloat64(fg) - me.Logger.Trace().Msgf(" %f + (%f * %f) (=%f) = %f", fgv, value, opsValue, prod, fgv2) + v.Logger.Trace().Msgf(" %f + (%f * %f) (=%f) = %f", fgv, value, opsValue, prod, fgv2) } else { - me.Logger.Trace().Msg(" no ops value SKIP") + v.Logger.Trace().Msg(" no ops value SKIP") } } } @@ -222,7 +240,7 @@ func (me *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, erro if opsValue, ok := ops.GetValueFloat64(i); ok && opsValue != 0 { err := m.SetValueFloat64(i, value/opsValue) if err != nil { - me.Logger.Error().Err(err).Msgf("error") + v.Logger.Error().Err(err).Msgf("error") } } else { m.SetValueNAN(i) diff --git a/cmd/poller/plugin/labelagent/label_agent.go b/cmd/poller/plugin/labelagent/label_agent.go index bd43e29a8..3efef6e2e 100644 --- a/cmd/poller/plugin/labelagent/label_agent.go +++ b/cmd/poller/plugin/labelagent/label_agent.go @@ -20,6 +20,7 @@ type LabelAgent struct { splitRegexRules []splitRegexRule splitPairsRules []splitPairsRule joinSimpleRules []joinSimpleRule + renameRules []renameRule replaceSimpleRules []replaceSimpleRule replaceRegexRules []replaceRegexRule excludeEqualsRules []excludeEqualsRule @@ -137,6 +138,24 @@ func (a *LabelAgent) joinSimple(matrix *matrix.Matrix) error { return nil } +// rename source label, if present, to target label +// if target label already exists overwrite it +func (a *LabelAgent) rename(matrix *matrix.Matrix) error { + for _, instance := range matrix.GetInstances() { + for _, r := range a.renameRules { + if old := instance.GetLabel(r.source); old != "" { + instance.SetLabel(r.target, old) + instance.DeleteLabel(r.source) + a.Logger.Trace(). + Str("source", r.source). + Str("target", r.target). + Msg("rename") + } + } + } + return nil +} + // replace in source label, if present, and add as new label func (a *LabelAgent) replaceSimple(matrix *matrix.Matrix) error { for _, instance := range matrix.GetInstances() { diff --git a/cmd/poller/plugin/labelagent/label_agent_test.go b/cmd/poller/plugin/labelagent/label_agent_test.go index 14f10ec1d..c3b83b374 100644 --- a/cmd/poller/plugin/labelagent/label_agent_test.go +++ b/cmd/poller/plugin/labelagent/label_agent_test.go @@ -54,7 +54,7 @@ func newLabelAgent() *LabelAgent { // create metric "result", if label "state" matches regex then map to 1 else use default value "4" params.NewChildS("value_to_num_regex", "").NewChildS("", "result value ^test\\d+ ^error `4`") - // These both are mutually exclusive, and should honour the above one's filtered result. + // These both are mutually exclusive, and should honor the above one's filtered result. // exclude instance if label "volstate" has value "offline" params.NewChildS("exclude_equals", "").NewChildS("", "volstate `offline`") // include instance if label "voltype" has value "rw" @@ -64,6 +64,9 @@ func newLabelAgent() *LabelAgent { // exclude instance if label "volstatus" has value which starts with "stopped_" params.NewChildS("exclude_contains", "").NewChildS("", "volstatus `stop`") + // rename label named style to type + params.NewChildS("rename", "").NewChildS("", "style type") + abc := plugin.New("Test", nil, params, nil, "", nil) p := &LabelAgent{AbstractPlugin: abc} @@ -145,6 +148,23 @@ func TestJoinSimpleRule(t *testing.T) { } } +func TestRenameRule(t *testing.T) { + m := matrix.New("TestLabelAgent", "test", "test") + p := newLabelAgent() + + instance, _ := m.NewInstance("0") + instance.SetLabel("style", "aaa_X") + + _ = p.rename(m) + + if instance.GetLabel("type") != "aaa_X" { + t.Errorf("rename failed, label type got=[%s] want=[%s]", instance.GetLabel("type"), "aaa_X") + } + if instance.GetLabel("style") != "" { + t.Errorf("rename failed, style lable should not exist got=[%s] ", instance.GetLabel("style")) + } +} + func TestReplaceSimpleRule(t *testing.T) { m := matrix.New("TestLabelAgent", "test", "test") p := newLabelAgent() diff --git a/cmd/poller/plugin/labelagent/parse_rules.go b/cmd/poller/plugin/labelagent/parse_rules.go index d085db17d..fc9ab298e 100644 --- a/cmd/poller/plugin/labelagent/parse_rules.go +++ b/cmd/poller/plugin/labelagent/parse_rules.go @@ -46,6 +46,8 @@ func (a *LabelAgent) parseRules() int { a.parseSplitPairsRule(rule) case "join": a.parseJoinSimpleRule(rule) + case "rename": + a.parseRenameRule(rule) case "replace": a.parseReplaceSimpleRule(rule) case "replace_regex": @@ -100,6 +102,11 @@ func (a *LabelAgent) parseRules() int { a.actions = append(a.actions, a.joinSimple) count += len(a.joinSimpleRules) } + case "rename": + if len(a.renameRules) != 0 { + a.actions = append(a.actions, a.rename) + count += len(a.renameRules) + } case "replace": if len(a.replaceSimpleRules) != 0 { a.actions = append(a.actions, a.replaceSimple) @@ -278,6 +285,28 @@ func (a *LabelAgent) parseJoinSimpleRule(rule string) { a.Logger.Warn().Msgf("(join) rule has invalid format [%s]", rule) } +type renameRule struct { + source string + target string +} + +// example rule: +// style type +// if the label named `style` exists, rename that label to `type` +// metric_one{style="flex",vol="vol1"} becomes metric_one{type="flex",vol="vol1"} + +func (a *LabelAgent) parseRenameRule(rule string) { + if fields := strings.SplitN(rule, " ", 2); len(fields) == 2 { + r := renameRule{source: strings.TrimSpace(fields[0]), target: strings.TrimSpace(fields[1])} + a.Logger.Debug().Msgf("fields := %v", fields) + a.renameRules = append(a.renameRules, r) + a.addNewLabels([]string{r.target}) + a.Logger.Debug().Msgf("(rename) parsed rule [%v]", r) + return + } + a.Logger.Warn().Str("rule", rule).Msg("rename rule has invalid format") +} + type replaceSimpleRule struct { source string target string diff --git a/cmd/tools/template/template_test.go b/cmd/tools/template/template_test.go index 678f6c154..2181fb698 100644 --- a/cmd/tools/template/template_test.go +++ b/cmd/tools/template/template_test.go @@ -582,7 +582,7 @@ func newZapiMetric(n *y3.Node, parents []string) metric { return m } -var setRe = regexp.MustCompile(`[sS]etLabel\("(\w+)",`) +var setRe = regexp.MustCompile(`[sS]etLabel\("?(\w+)"?,`) func findCustomPlugins(path string, template *node.Node, model *TemplateModel) error { plug := template.SearchChildren([]string{"plugins"}) diff --git a/docs/configure-ems.md b/docs/configure-ems.md index 756abbf46..04d524edb 100644 --- a/docs/configure-ems.md +++ b/docs/configure-ems.md @@ -111,7 +111,8 @@ The EMS event template parameters are explained below along with an example for named `LUN.online` is received. - `resolve_after` (optional, Go duration, default = 28 days) resolve the issuing EMS after the specified duration has elapsed (`672h` = `28d`). - If the bookend pair is not received within the `resolve_after` duration, the issuing EMS event expires. + If the bookend pair is not received within the `resolve_after` duration, the Issuing EMS event expires. When that + happens, Harvest will mark the event as auto resolved by adding the `autoresolve=true` label to the Issuing EMS event. - `resolve_key` (optional) bookend key used to match bookend EMS events. Defaults to prefixed (`^^`) labels in `exports` section. `resolve_key` allows you to override what is defined in the `exports` section. diff --git a/docs/configure-harvest-basic.md b/docs/configure-harvest-basic.md index bf2bc54ea..e8159b21c 100644 --- a/docs/configure-harvest-basic.md +++ b/docs/configure-harvest-basic.md @@ -204,10 +204,11 @@ Pollers: You can fetch authentication information via an external script by using the `credentials_script` section in the `Pollers` section of your `harvest.yml` as shown in the [example below](#example). -At runtime, Harvest will invoke the script referenced in the `credentials_script` `path` section. -Harvest will call the script with two arguments via `standard in`, in this order: -1. address of the cluster taken from your `harvest.yaml` file, section `Pollers` `addr` -2. username of the cluster taken from your `harvest.yaml` file, section `Pollers` `username` +At runtime, Harvest will invoke the script referenced in the `credentials_script` `path` section. +Harvest will call the script with two arguments like so: `./script $addr $username`. + +- The first argument is the address of the cluster taken from your `harvest.yaml` file, section `Pollers addr` +- The second argument is the username of the cluster taken from your `harvest.yaml` file, section `Pollers username` The script should use the two arguments to look up and return the password via the script's `standard out`. If the script doesn't finish within the specified `timeout`, Harvest will kill the script and any spawned processes. diff --git a/docs/plugins.md b/docs/plugins.md index e4de680b3..1b37cc785 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -278,6 +278,30 @@ join: # by joining their values with "_" ``` +## rename + +If the label named `SOURCE` exists, rename that label to `TARGET`. +If the `TARGET` label already exists, overwrite it. + +NOTE: Don't forget to update your `export_options` to include the `TARGET` label. + +Rule syntax: + +```yaml +rename: + - SOURCE TARGET +``` + +Example: + +```yaml +rename: + - style type +# this rule will rename the `style` label to `type` +# for example, metric_one{style="flex",vol="vol1"} 3 +# becomes metric_one{type="flex",vol="vol1"} 3 +``` + ## replace Substitute substring `OLD` with `NEW` in label `SOURCE` and store in `TARGET`. Note that target and source labels can be @@ -296,7 +320,7 @@ Example: ```yaml replace: - node node_short `node_` `` -# this rule will just remove "node_" from all values of label +# this rule will remove "node_" from all values of label # "node". E.g. if label is "node_jamaica1", it will rewrite it # as "jamaica1" ``` diff --git a/docs/prepare-fsx-clusters.md b/docs/prepare-fsx-clusters.md index 9ec5604f0..cfbe1b525 100644 --- a/docs/prepare-fsx-clusters.md +++ b/docs/prepare-fsx-clusters.md @@ -16,5 +16,4 @@ The dashboards that work with FSx are tagged with `fsx` and listed below: * ONTAP: SVM * ONTAP: Security * ONTAP: Data Protection Snapshots -* ONTAP: Compliance -* ONTAP: Headroom (Only works for Rest Collector) \ No newline at end of file +* ONTAP: Compliance \ No newline at end of file diff --git a/go.mod b/go.mod index 8b052825f..f7709ddb6 100644 --- a/go.mod +++ b/go.mod @@ -6,10 +6,10 @@ require ( github.com/bbrks/wrap/v2 v2.5.0 github.com/go-openapi/spec v0.20.9 github.com/hashicorp/go-version v1.6.0 - github.com/imdario/mergo v0.3.15 + github.com/imdario/mergo v0.3.16 github.com/olekukonko/tablewriter v0.0.5 github.com/rs/zerolog v1.29.1 - github.com/shirou/gopsutil/v3 v3.23.4 + github.com/shirou/gopsutil/v3 v3.23.5 github.com/spf13/cobra v1.7.0 github.com/tidwall/gjson v1.14.4 github.com/tidwall/sjson v1.2.5 @@ -35,11 +35,11 @@ require ( github.com/mattn/go-runewidth v0.0.14 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/shoenig/go-m1cpu v0.1.5 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect ) diff --git a/go.sum b/go.sum index 9bfc2ede2..db44d7236 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -76,10 +76,15 @@ github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o= github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8= +github.com/shirou/gopsutil/v3 v3.23.5 h1:5SgDCeQ0KW0S4N0znjeM/eFHXXOKyv2dVNgRq/c9P6Y= +github.com/shirou/gopsutil/v3 v3.23.5/go.mod h1:Ng3Maa27Q2KARVJ0SPZF5NdrQSC3XHKP8IIWrHgMeLY= github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ= github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -96,6 +101,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -112,6 +118,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zekroTJA/timedmap v1.5.1 h1:s9SI1T8gl1OAfDw9LKZYMfbhNqqCIOhZTfhsHgpKHMw= github.com/zekroTJA/timedmap v1.5.1/go.mod h1:Go4uPxMN1Wjl5IgO6HYD1tM9IQhkYEVqcrrdsI4ljXo= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/integration/Jenkinsfile b/integration/Jenkinsfile index 6e23dde8f..053f5a54b 100644 --- a/integration/Jenkinsfile +++ b/integration/Jenkinsfile @@ -18,7 +18,7 @@ pipeline { environment { BUILD_ID="dontKillMe" JENKINS_NODE_COOKIE="dontKillMe" - GO_VERSION = "1.20.3" + GO_VERSION = "1.20.5" } stages { diff --git a/jenkins/artifacts/jenkinsfile b/jenkins/artifacts/jenkinsfile index 6fce252e1..40be4c2cc 100644 --- a/jenkins/artifacts/jenkinsfile +++ b/jenkins/artifacts/jenkinsfile @@ -37,7 +37,7 @@ pipeline { jfrogImagePrefix = "netappdownloads.jfrog.io/oss-docker-harvest-production/harvest" jfrogRepo = "netappdownloads.jfrog.io" COMMIT_ID = sh(returnStdout: true, script: 'git rev-parse HEAD') - GO_VERSION = "1.20.3" + GO_VERSION = "1.20.5" } stages { diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index f33b628b2..fd26e6db2 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -151,6 +151,10 @@ func (c *Credentials) GetPollerAuth() (PollerAuth, error) { copyDefault := *conf.Config.Defaults copyDefault.Name = c.poller.Name + copyDefault.Addr = c.poller.Addr + if c.poller.Username != "" { + copyDefault.Username = c.poller.Username + } defaultAuth, err := getPollerAuth(c, ©Default) if err != nil { return PollerAuth{}, err diff --git a/pkg/auth/auth_test.go b/pkg/auth/auth_test.go index b96d65004..954407827 100644 --- a/pkg/auth/auth_test.go +++ b/pkg/auth/auth_test.go @@ -92,7 +92,7 @@ Pollers: { name: "default credentials_script", pollerName: "test", - want: PollerAuth{Username: "username", Password: "pass-from-script", IsCert: false}, + want: PollerAuth{Username: "username", Password: "addr=a.b.c user=username", IsCert: false}, defaultDefined: true, yaml: ` Defaults: @@ -105,10 +105,25 @@ Pollers: username: username`, }, + { + name: "credentials_script with default username", + pollerName: "test", + want: PollerAuth{Username: "me", Password: "addr=a.b.c user=me", IsCert: false}, + defaultDefined: true, + yaml: ` +Defaults: + username: me + credentials_script: + path: testdata/get_pass +Pollers: + test: + addr: a.b.c`, + }, + { name: "no default", pollerName: "test", - want: PollerAuth{Username: "username", Password: "pass-from-script", IsCert: false}, + want: PollerAuth{Username: "username", Password: "addr=a.b.c user=username", IsCert: false}, yaml: ` Pollers: test: diff --git a/pkg/auth/testdata/get_pass b/pkg/auth/testdata/get_pass index f01f0745a..23344fd4a 100755 --- a/pkg/auth/testdata/get_pass +++ b/pkg/auth/testdata/get_pass @@ -1,3 +1,3 @@ #!/bin/bash # Used by pkg/auth/auth_test.go -echo pass-from-script \ No newline at end of file +echo "addr=$1 user=$2" \ No newline at end of file diff --git a/pkg/matrix/instance.go b/pkg/matrix/instance.go index a2cff1e4e..9292f9615 100644 --- a/pkg/matrix/instance.go +++ b/pkg/matrix/instance.go @@ -35,6 +35,10 @@ func (i *Instance) ClearLabels() { i.labels = dict.New() } +func (i *Instance) DeleteLabel(key string) { + i.labels.Delete(key) +} + func (i *Instance) SetLabel(key, value string) { i.labels.Set(key, value) } diff --git a/renovate.json b/renovate.json index 77d8ce622..88b95fab8 100644 --- a/renovate.json +++ b/renovate.json @@ -1,7 +1,9 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base" + "config:base", + ":semanticCommitTypeAll(chore)", + ":semanticCommitScopeDisabled" ], "ignorePaths": ["**/integration/**"], "schedule": ["after 10pm and before 5am every weekday", "every weekend"] diff --git a/vendor/github.com/imdario/mergo/README.md b/vendor/github.com/imdario/mergo/README.md index 4f0287498..ffbbb62c7 100644 --- a/vendor/github.com/imdario/mergo/README.md +++ b/vendor/github.com/imdario/mergo/README.md @@ -1,17 +1,20 @@ # Mergo -[![GoDoc][3]][4] [![GitHub release][5]][6] [![GoCard][7]][8] -[![Build Status][1]][2] -[![Coverage Status][9]][10] +[![Test status][1]][2] +[![OpenSSF Scorecard][21]][22] +[![OpenSSF Best Practices][19]][20] +[![Coverage status][9]][10] [![Sourcegraph][11]][12] -[![FOSSA Status][13]][14] +[![FOSSA status][13]][14] + +[![GoDoc][3]][4] [![Become my sponsor][15]][16] [![Tidelift][17]][18] -[1]: https://travis-ci.org/imdario/mergo.png -[2]: https://travis-ci.org/imdario/mergo +[1]: https://github.com/imdario/mergo/workflows/tests/badge.svg?branch=master +[2]: https://github.com/imdario/mergo/actions/workflows/tests.yml [3]: https://godoc.org/github.com/imdario/mergo?status.svg [4]: https://godoc.org/github.com/imdario/mergo [5]: https://img.shields.io/github/release/imdario/mergo.svg @@ -28,6 +31,10 @@ [16]: https://github.com/sponsors/imdario [17]: https://tidelift.com/badges/package/go/github.com%2Fimdario%2Fmergo [18]: https://tidelift.com/subscription/pkg/go-github.com-imdario-mergo +[19]: https://bestpractices.coreinfrastructure.org/projects/7177/badge +[20]: https://bestpractices.coreinfrastructure.org/projects/7177 +[21]: https://api.securityscorecards.dev/projects/github.com/imdario/mergo/badge +[22]: https://api.securityscorecards.dev/projects/github.com/imdario/mergo A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements. @@ -232,5 +239,4 @@ Written by [Dario Castañé](http://dario.im). [BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE). - [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_large) diff --git a/vendor/github.com/shirou/gopsutil/v3/internal/common/sleep.go b/vendor/github.com/shirou/gopsutil/v3/internal/common/sleep.go index 8c35b1722..9bed2419e 100644 --- a/vendor/github.com/shirou/gopsutil/v3/internal/common/sleep.go +++ b/vendor/github.com/shirou/gopsutil/v3/internal/common/sleep.go @@ -11,6 +11,9 @@ func Sleep(ctx context.Context, interval time.Duration) error { timer := time.NewTimer(interval) select { case <-ctx.Done(): + if !timer.Stop() { + <-timer.C + } return ctx.Err() case <-timer.C: return nil diff --git a/vendor/github.com/shirou/gopsutil/v3/mem/mem_linux.go b/vendor/github.com/shirou/gopsutil/v3/mem/mem_linux.go index 56fb1cc6c..059518dc5 100644 --- a/vendor/github.com/shirou/gopsutil/v3/mem/mem_linux.go +++ b/vendor/github.com/shirou/gopsutil/v3/mem/mem_linux.go @@ -154,13 +154,13 @@ func fillFromMeminfoWithContext() (*VirtualMemoryStat, *VirtualMemoryExStat, err return ret, retEx, err } retEx.Unevictable = t * 1024 - case "WriteBack": + case "Writeback": t, err := strconv.ParseUint(value, 10, 64) if err != nil { return ret, retEx, err } ret.WriteBack = t * 1024 - case "WriteBackTmp": + case "WritebackTmp": t, err := strconv.ParseUint(value, 10, 64) if err != nil { return ret, retEx, err diff --git a/vendor/github.com/shirou/gopsutil/v3/net/net_darwin.go b/vendor/github.com/shirou/gopsutil/v3/net/net_darwin.go index 1c8d4f4e3..4d2cfbcd8 100644 --- a/vendor/github.com/shirou/gopsutil/v3/net/net_darwin.go +++ b/vendor/github.com/shirou/gopsutil/v3/net/net_darwin.go @@ -278,7 +278,7 @@ func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackSta return nil, common.ErrNotImplementedError } -// NetProtoCounters returns network statistics for the entire system +// ProtoCounters returns network statistics for the entire system // If protocols is empty then all protocols are returned, otherwise // just the protocols in the list are returned. // Not Implemented for Darwin diff --git a/vendor/github.com/shirou/gopsutil/v3/net/net_freebsd.go b/vendor/github.com/shirou/gopsutil/v3/net/net_freebsd.go index 7f31851ea..bf8baf094 100644 --- a/vendor/github.com/shirou/gopsutil/v3/net/net_freebsd.go +++ b/vendor/github.com/shirou/gopsutil/v3/net/net_freebsd.go @@ -115,7 +115,7 @@ func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackSta return nil, common.ErrNotImplementedError } -// NetProtoCounters returns network statistics for the entire system +// ProtoCounters returns network statistics for the entire system // If protocols is empty then all protocols are returned, otherwise // just the protocols in the list are returned. // Not Implemented for FreeBSD diff --git a/vendor/github.com/shirou/gopsutil/v3/net/net_linux.go b/vendor/github.com/shirou/gopsutil/v3/net/net_linux.go index c7cd0db18..dd62d4791 100644 --- a/vendor/github.com/shirou/gopsutil/v3/net/net_linux.go +++ b/vendor/github.com/shirou/gopsutil/v3/net/net_linux.go @@ -157,7 +157,7 @@ var netProtocols = []string{ "udplite", } -// NetProtoCounters returns network statistics for the entire system +// ProtoCounters returns network statistics for the entire system // If protocols is empty then all protocols are returned, otherwise // just the protocols in the list are returned. // Available protocols: diff --git a/vendor/github.com/shirou/gopsutil/v3/net/net_openbsd.go b/vendor/github.com/shirou/gopsutil/v3/net/net_openbsd.go index 5f066a09f..cf48f53e7 100644 --- a/vendor/github.com/shirou/gopsutil/v3/net/net_openbsd.go +++ b/vendor/github.com/shirou/gopsutil/v3/net/net_openbsd.go @@ -164,7 +164,7 @@ func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackSta return nil, common.ErrNotImplementedError } -// NetProtoCounters returns network statistics for the entire system +// ProtoCounters returns network statistics for the entire system // If protocols is empty then all protocols are returned, otherwise // just the protocols in the list are returned. // Not Implemented for OpenBSD diff --git a/vendor/github.com/shirou/gopsutil/v3/net/net_windows.go b/vendor/github.com/shirou/gopsutil/v3/net/net_windows.go index 68b26bdcd..5d384342f 100644 --- a/vendor/github.com/shirou/gopsutil/v3/net/net_windows.go +++ b/vendor/github.com/shirou/gopsutil/v3/net/net_windows.go @@ -338,7 +338,7 @@ func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackSta return nil, common.ErrNotImplementedError } -// NetProtoCounters returns network statistics for the entire system +// ProtoCounters returns network statistics for the entire system // If protocols is empty then all protocols are returned, otherwise // just the protocols in the list are returned. // Not Implemented for Windows diff --git a/vendor/github.com/shirou/gopsutil/v3/process/process.go b/vendor/github.com/shirou/gopsutil/v3/process/process.go index 0ca26c210..1a7fe1b80 100644 --- a/vendor/github.com/shirou/gopsutil/v3/process/process.go +++ b/vendor/github.com/shirou/gopsutil/v3/process/process.go @@ -335,7 +335,7 @@ func (p *Process) MemoryPercentWithContext(ctx context.Context) (float32, error) return (100 * float32(used) / float32(total)), nil } -// CPU_Percent returns how many percent of the CPU time this process uses +// CPUPercent returns how many percent of the CPU time this process uses func (p *Process) CPUPercent() (float64, error) { return p.CPUPercentWithContext(context.Background()) } @@ -507,7 +507,7 @@ func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { return p.MemoryInfoExWithContext(context.Background()) } -// PageFaultsInfo returns the process's page fault counters. +// PageFaults returns the process's page fault counters. func (p *Process) PageFaults() (*PageFaultsStat, error) { return p.PageFaultsWithContext(context.Background()) } @@ -530,7 +530,7 @@ func (p *Process) Connections() ([]net.ConnectionStat, error) { return p.ConnectionsWithContext(context.Background()) } -// Connections returns a slice of net.ConnectionStat used by the process at most `max`. +// ConnectionsMax returns a slice of net.ConnectionStat used by the process at most `max`. func (p *Process) ConnectionsMax(max int) ([]net.ConnectionStat, error) { return p.ConnectionsMaxWithContext(context.Background(), max) } diff --git a/vendor/github.com/shoenig/go-m1cpu/cpu.go b/vendor/github.com/shoenig/go-m1cpu/cpu.go index 9e55eb458..502a8cce9 100644 --- a/vendor/github.com/shoenig/go-m1cpu/cpu.go +++ b/vendor/github.com/shoenig/go-m1cpu/cpu.go @@ -8,7 +8,7 @@ package m1cpu // #include // #include // -// #ifndef MAC_OS_VERSION_12_0 +// #if !defined(MAC_OS_VERSION_12_0) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0 // #define kIOMainPortDefault kIOMasterPortDefault // #endif // diff --git a/vendor/github.com/yusufpapurcu/wmi/README.md b/vendor/github.com/yusufpapurcu/wmi/README.md index c4a432d6d..426d1a46b 100644 --- a/vendor/github.com/yusufpapurcu/wmi/README.md +++ b/vendor/github.com/yusufpapurcu/wmi/README.md @@ -4,10 +4,3 @@ wmi Package wmi provides a WQL interface to Windows WMI. Note: It interfaces with WMI on the local machine, therefore it only runs on Windows. - ---- - -NOTE: This project is no longer being actively maintained. If you would like -to become its new owner, please contact tlimoncelli at stack over flow dot com. - ---- diff --git a/vendor/github.com/yusufpapurcu/wmi/swbemservices.go b/vendor/github.com/yusufpapurcu/wmi/swbemservices.go index 3ff875630..a250c846d 100644 --- a/vendor/github.com/yusufpapurcu/wmi/swbemservices.go +++ b/vendor/github.com/yusufpapurcu/wmi/swbemservices.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package wmi diff --git a/vendor/github.com/yusufpapurcu/wmi/wmi.go b/vendor/github.com/yusufpapurcu/wmi/wmi.go index b4bb4f090..26c3581c9 100644 --- a/vendor/github.com/yusufpapurcu/wmi/wmi.go +++ b/vendor/github.com/yusufpapurcu/wmi/wmi.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows /* @@ -20,7 +21,6 @@ Example code to print names of running processes: println(i, v.Name) } } - */ package wmi @@ -338,11 +338,6 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat f := v.Field(i) of := f isPtr := f.Kind() == reflect.Ptr - if isPtr { - ptr := reflect.New(f.Type().Elem()) - f.Set(ptr) - f = f.Elem() - } n := v.Type().Field(i).Name if n[0] < 'A' || n[0] > 'Z' { continue @@ -367,6 +362,12 @@ func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismat } defer prop.Clear() + if isPtr && !(c.PtrNil && prop.VT == 0x1) { + ptr := reflect.New(f.Type().Elem()) + f.Set(ptr) + f = f.Elem() + } + if prop.VT == 0x1 { //VT_NULL continue } diff --git a/vendor/modules.txt b/vendor/modules.txt index 2069a69b9..2d7659dec 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -21,7 +21,7 @@ github.com/go-openapi/swag # github.com/hashicorp/go-version v1.6.0 ## explicit github.com/hashicorp/go-version -# github.com/imdario/mergo v0.3.15 +# github.com/imdario/mergo v0.3.16 ## explicit; go 1.13 github.com/imdario/mergo # github.com/inconshreveable/mousetrap v1.1.0 @@ -62,7 +62,7 @@ github.com/rs/zerolog github.com/rs/zerolog/internal/cbor github.com/rs/zerolog/internal/json github.com/rs/zerolog/log -# github.com/shirou/gopsutil/v3 v3.23.4 +# github.com/shirou/gopsutil/v3 v3.23.5 ## explicit; go 1.15 github.com/shirou/gopsutil/v3/cpu github.com/shirou/gopsutil/v3/host @@ -70,7 +70,7 @@ github.com/shirou/gopsutil/v3/internal/common github.com/shirou/gopsutil/v3/mem github.com/shirou/gopsutil/v3/net github.com/shirou/gopsutil/v3/process -# github.com/shoenig/go-m1cpu v0.1.5 +# github.com/shoenig/go-m1cpu v0.1.6 ## explicit; go 1.20 github.com/shoenig/go-m1cpu # github.com/spf13/cobra v1.7.0 @@ -97,7 +97,7 @@ github.com/tklauser/go-sysconf # github.com/tklauser/numcpus v0.6.0 ## explicit; go 1.13 github.com/tklauser/numcpus -# github.com/yusufpapurcu/wmi v1.2.2 +# github.com/yusufpapurcu/wmi v1.2.3 ## explicit; go 1.16 github.com/yusufpapurcu/wmi # github.com/zekroTJA/timedmap v1.5.1