diff --git a/.clabot b/.clabot
index 66583d944..d92f29ab3 100644
--- a/.clabot
+++ b/.clabot
@@ -16,6 +16,7 @@
"cordelster",
"george-strother",
"7840vz",
+ "embusalacchi",
"$$$ Bots $$$",
"dependabot",
"dependabot[bot]",
diff --git a/.github/ISSUE_TEMPLATE/release-template.md b/.github/ISSUE_TEMPLATE/release-template.md
index 3d75d13bb..fb802b6f4 100644
--- a/.github/ISSUE_TEMPLATE/release-template.md
+++ b/.github/ISSUE_TEMPLATE/release-template.md
@@ -27,6 +27,7 @@ git push origin release/$RELEASE
| DOCKER_PUBLISH | false |
| RUN_TEST | true |
| OVERWRITE_DOCKER_LATEST_TAG | false |
+| RUN_TRIVY_SCAN | true |
- [ ] Create a release branch for the harvest-metrics repo like so:
```bash
@@ -76,6 +77,7 @@ bin/harvest generate metrics --poller POLLERNAME
| DOCKER_PUBLISH | true |
| RUN_TEST | true |
| OVERWRITE_DOCKER_LATEST_TAG | true |
+| RUN_TRIVY_SCAN | true |
- [ ] [Draft a new release](https://github.com/NetApp/harvest/releases). Use `v$RELEASE` for the tag and pick the release/$RELEASE branch.
- [ ] Type `$RELEASE` in the `Release title` text input
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 8820c946d..d757ceb91 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -40,6 +40,8 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- name: read environment file
run: cat .harvest.env >> "$GITHUB_ENV"
diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml
index 2c29e3759..46cfaba41 100644
--- a/.github/workflows/commitlint.yml
+++ b/.github/workflows/commitlint.yml
@@ -6,4 +6,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- uses: wagoid/commitlint-github-action@v6
\ No newline at end of file
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 9424e3221..9059294e0 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -15,6 +15,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- name: read environment file
run: cat .harvest.env >> "$GITHUB_ENV"
diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml
index 24d90ace3..ce2d0bb09 100644
--- a/.github/workflows/lint-pr.yml
+++ b/.github/workflows/lint-pr.yml
@@ -1,13 +1,18 @@
name: "Lint PR"
on:
- pull_request_target:
+ pull_request:
types:
- opened
- edited
- synchronize
+ - reopened
+
+permissions:
+ pull-requests: read
jobs:
main:
+ name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v5
diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml
new file mode 100644
index 000000000..839c6d76c
--- /dev/null
+++ b/.github/workflows/zizmor.yml
@@ -0,0 +1,35 @@
+# https://github.com/woodruffw/zizmor
+name: GitHub Actions Security Analysis with Zizmor
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["*"]
+
+jobs:
+ zizmor:
+ name: Zizmor latest via Cargo
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ security-events: write
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ - name: Setup Rust
+ uses: actions-rust-lang/setup-rust-toolchain@v1
+ - name: Get zizmor
+ run: cargo install zizmor
+ - name: Run zizmor
+ run: zizmor --format sarif . > results.sarif
+ - name: Upload SARIF file
+ uses: github/codeql-action/upload-sarif@v3
+ with:
+ # Path to SARIF file relative to the root of the repository
+ sarif_file: results.sarif
+ # Optional category for the results
+ # Used to differentiate multiple results for one commit
+ category: zizmor
\ No newline at end of file
diff --git a/SUPPORT.md b/SUPPORT.md
index 3639fad1d..0dbed9905 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -1,12 +1,12 @@
# Harvest Support and Getting Help
-Harvest is an open-source project developed and published by NetApp to collect performance, capacity and hardware metrics from ONTAP clusters. These metrics can then be delivered to a range of databases and displayed in Grafana dashboards. Harvest is not an officially supported NetApp product. NetApp maintains and updates Harvest with bug fixes, security updates, and feature development. For assistance refer [Getting Help](#getting-help)
+Harvest is an open-source project developed and published by NetApp to collect performance, capacity and hardware metrics from ONTAP clusters. These metrics can then be delivered to a range of databases and displayed in Grafana dashboards. Harvest is not an officially supported NetApp product. NetApp maintains and updates Harvest with bug fixes, security updates, and feature development. For assistance, refer to [Getting Help](#getting-help)
This document describes Harvest's release and support lifecycle as well as places you can get help.
## Harvest's Release and Support Lifecycle
-Harvest's current release schedule is quarterly in January, April, July, and October, but it may change at our discretion.
+Harvest's current release schedule is quarterly in February, May, August, and November, but it may change at our discretion.
Each release of Harvest supports the most recently released version of ONTAP. We try our best to also support earlier versions of ONTAP. When that's not possible, breaking changes will be outlined in the changelog.
@@ -16,7 +16,7 @@ Harvest is constantly being improved with new features and bug fixes. Customers
For example, when `YY.MM` (ex: 21.04) is released, we intend to support it until `YY+1.MM` (ex: 22.04) is released. At the same time, `YY-1.MM` (ex: 20.04) and associated minor releases (ex: 20.04.1) move to limited or no support.
-If you are running a version of Harvest that’s more than 12 months old, you must upgrade to a newer version to receive any support then available from NetApp. We always recommend running the latest version.
+If you are running a version of Harvest that’s more than 12 months old, you must upgrade to a newer version to receive support from NetApp. We always recommend running the latest version.
We use GitHub for tracking bugs and feature requests.
diff --git a/cmd/collectors/commonutils.go b/cmd/collectors/commonutils.go
index 672c1ee89..52b311cb5 100644
--- a/cmd/collectors/commonutils.go
+++ b/cmd/collectors/commonutils.go
@@ -1,6 +1,7 @@
package collectors
import (
+ "fmt"
"github.com/netapp/harvest/v2/cmd/tools/rest"
"github.com/netapp/harvest/v2/pkg/errs"
"github.com/netapp/harvest/v2/pkg/matrix"
@@ -60,7 +61,7 @@ func IsEmbedShelf(model string, moduleType string) bool {
return combinations[embedShelf{model, moduleType}]
}
-func InvokeRestCallWithTestFile(client *rest.Client, href string, logger *slog.Logger, testFilePath string) ([]gjson.Result, error) {
+func InvokeRestCallWithTestFile(client *rest.Client, href string, testFilePath string) ([]gjson.Result, error) {
if testFilePath != "" {
b, err := os.ReadFile(testFilePath)
if err != nil {
@@ -69,19 +70,13 @@ func InvokeRestCallWithTestFile(client *rest.Client, href string, logger *slog.L
testData := gjson.Result{Type: gjson.JSON, Raw: string(b)}
return testData.Get("records").Array(), nil
}
- return InvokeRestCall(client, href, logger)
+ return InvokeRestCall(client, href)
}
-func InvokeRestCall(client *rest.Client, href string, logger *slog.Logger) ([]gjson.Result, error) {
+func InvokeRestCall(client *rest.Client, href string) ([]gjson.Result, error) {
result, err := rest.FetchAll(client, href)
if err != nil {
- logger.Error(
- "Failed to fetch data",
- slogx.Err(err),
- slog.String("href", href),
- slog.Int("hrefLength", len(href)),
- )
- return []gjson.Result{}, err
+ return []gjson.Result{}, fmt.Errorf("failed to fetchAll href=%s, hrefLength=%d err=%w", TruncateURL(href), len(href), err)
}
if len(result) == 0 {
@@ -91,6 +86,14 @@ func InvokeRestCall(client *rest.Client, href string, logger *slog.Logger) ([]gj
return result, nil
}
+func TruncateURL(href string) string {
+ indexOfQuestionMark := strings.Index(href, "?")
+ if indexOfQuestionMark == -1 {
+ return href
+ }
+ return href[:indexOfQuestionMark] + "..."
+}
+
func GetClusterTime(client *rest.Client, returnTimeOut *int, logger *slog.Logger) (time.Time, error) {
var (
err error
diff --git a/cmd/collectors/ems/ems.go b/cmd/collectors/ems/ems.go
index b394a4a78..019d55249 100644
--- a/cmd/collectors/ems/ems.go
+++ b/cmd/collectors/ems/ems.go
@@ -124,8 +124,8 @@ func (e *Ems) InitMatrix() error {
// overwrite from abstract collector
mat.Object = e.Object
// Add system (cluster) name
- mat.SetGlobalLabel("cluster", e.Client.Cluster().Name)
- mat.SetGlobalLabel("cluster_uuid", e.Client.Cluster().UUID)
+ mat.SetGlobalLabel("cluster", e.Client.Remote().Name)
+ mat.SetGlobalLabel("cluster_uuid", e.Client.Remote().UUID)
if e.Params.HasChildS("labels") {
for _, l := range e.Params.GetChildS("labels").GetChildren() {
diff --git a/cmd/collectors/keyperf/keyperf.go b/cmd/collectors/keyperf/keyperf.go
index ebfb6298a..111a8fb98 100644
--- a/cmd/collectors/keyperf/keyperf.go
+++ b/cmd/collectors/keyperf/keyperf.go
@@ -65,6 +65,8 @@ func (kp *KeyPerf) Init(a *collector.AbstractCollector) error {
return err
}
+ kp.Remote = kp.Client.Remote()
+
if kp.Prop.TemplatePath, err = kp.LoadTemplate(); err != nil {
return err
}
@@ -105,7 +107,7 @@ func (kp *KeyPerf) InitMatrix() error {
// overwrite from abstract collector
mat.Object = kp.Prop.Object
// Add system (cluster) name
- mat.SetGlobalLabel("cluster", kp.Client.Cluster().Name)
+ mat.SetGlobalLabel("cluster", kp.Remote.Name)
if kp.Params.HasChildS("labels") {
for _, l := range kp.Params.GetChildS("labels").GetChildren() {
mat.SetGlobalLabel(l.GetNameS(), l.GetContentS())
@@ -140,7 +142,7 @@ func (kp *KeyPerf) loadParamInt(name string, defaultValue int) int {
}
func (kp *KeyPerf) buildCounters() {
- staticCounterDef, err := loadStaticCounterDefinitions(kp.Prop.Object, "cmd/collectors/keyperf/static_counter_definitions.yaml", kp.Logger)
+ staticCounterDef, err := loadStaticCounterDefinitions(kp.Prop.Object, "conf/keyperf/static_counter_definitions.yaml", kp.Logger)
if err != nil {
// It's acceptable to continue even if there are errors, as the remaining counters will still be processed.
// Any counters that require counter metadata will be skipped.
diff --git a/cmd/collectors/power.go b/cmd/collectors/power.go
index 82628bd22..bdd39e687 100644
--- a/cmd/collectors/power.go
+++ b/cmd/collectors/power.go
@@ -50,7 +50,7 @@ func collectChassisFRU(client *rest.Client, logger *slog.Logger) (map[string]int
if !cn.Exists() {
logger.Warn(
"fru has no connected nodes",
- slog.String("cluster", client.Cluster().Name),
+ slog.String("cluster", client.Remote().Name),
slog.String("fru", r.Get("fru_name").String()),
)
continue
diff --git a/cmd/collectors/rest/plugins/aggregate/aggregate.go b/cmd/collectors/rest/plugins/aggregate/aggregate.go
index 3912045b3..c747c2ac7 100644
--- a/cmd/collectors/rest/plugins/aggregate/aggregate.go
+++ b/cmd/collectors/rest/plugins/aggregate/aggregate.go
@@ -177,5 +177,5 @@ func (a *Aggregate) getObjectStoreData() ([]gjson.Result, error) {
Filter([]string{`tier_name=!" "|""`}).
Build()
- return collectors.InvokeRestCall(a.client, href, a.SLogger)
+ return collectors.InvokeRestCall(a.client, href)
}
diff --git a/cmd/collectors/rest/plugins/certificate/certificate.go b/cmd/collectors/rest/plugins/certificate/certificate.go
index 0681f08f1..d6bf7e001 100644
--- a/cmd/collectors/rest/plugins/certificate/certificate.go
+++ b/cmd/collectors/rest/plugins/certificate/certificate.go
@@ -200,7 +200,7 @@ func (c *Certificate) GetAdminVserver() (string, error) {
Filter([]string{"type=admin"}).
Build()
- if result, err = collectors.InvokeRestCall(c.client, href, c.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(c.client, href); err != nil {
return "", err
}
@@ -227,7 +227,7 @@ func (c *Certificate) GetSecuritySsl(adminSvm string) (string, error) {
Filter([]string{"vserver=" + adminSvm}).
Build()
- if result, err = collectors.InvokeRestCall(c.client, href, c.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(c.client, href); err != nil {
return "", err
}
diff --git a/cmd/collectors/rest/plugins/health/health.go b/cmd/collectors/rest/plugins/health/health.go
index c612a96bd..3318c8d7d 100644
--- a/cmd/collectors/rest/plugins/health/health.go
+++ b/cmd/collectors/rest/plugins/health/health.go
@@ -1,6 +1,7 @@
package health
import (
+ "errors"
"fmt"
"github.com/netapp/harvest/v2/cmd/collectors"
"github.com/netapp/harvest/v2/cmd/poller/plugin"
@@ -14,6 +15,7 @@ import (
"github.com/tidwall/gjson"
"log/slog"
"strconv"
+ "strings"
"time"
)
@@ -33,6 +35,7 @@ const (
volumeRansomwareHealthMatrix = "health_volume_ransomware"
volumeMoveHealthMatrix = "health_volume_move"
licenseHealthMatrix = "health_license"
+ emsHealthMatrix = "health_ems"
severityLabel = "severity"
defaultDataPollDuration = 3 * time.Minute
)
@@ -44,6 +47,7 @@ type Health struct {
lastFilterTime int64
previousData map[string]*matrix.Matrix
resolutionData map[string]*matrix.Matrix
+ emsSeverity []string
}
func New(p *plugin.AbstractPlugin) plugin.Plugin {
@@ -66,6 +70,20 @@ func (h *Health) Init() error {
return err
}
+ ems := h.Params.GetChildS("ems")
+
+ // Set default severity to "emergency"
+ h.emsSeverity = []string{"emergency"}
+ if ems != nil {
+ severity := ems.GetChildS("severity")
+ if severity != nil {
+ severities := severity.GetAllChildContentS()
+ if len(severities) > 0 {
+ h.emsSeverity = severities
+ }
+ }
+ }
+
timeout, _ := time.ParseDuration(rest.DefaultTimeout)
if h.client, err = rest.New(conf.ZapiPoller(h.ParentParams), timeout, h.Auth); err != nil {
return err
@@ -109,7 +127,7 @@ func (h *Health) initMatrix(name string, prefix string, inputMat map[string]*mat
func (h *Health) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) {
data := dataMap[h.Object]
h.client.Metadata.Reset()
- clusterVersion := h.client.Cluster().GetVersion()
+ clusterVersion := h.client.Remote().Version
ontapVersion, err := goversion.NewVersion(clusterVersion)
if err != nil {
h.SLogger.Error(
@@ -147,6 +165,14 @@ func (h *Health) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util
h.resolutionData[k].SetGlobalLabels(data.GetGlobalLabels())
}
+ // Initialize emsMatrix separately as it doesn't need to be stored or processed for resolution
+ emsMat := matrix.New(h.Parent+emsHealthMatrix, emsHealthMatrix, emsHealthMatrix)
+ emsMat.SetGlobalLabels(data.GetGlobalLabels())
+ if err := h.initMatrix(emsHealthMatrix, "", map[string]*matrix.Matrix{emsHealthMatrix: emsMat}); err != nil {
+ h.SLogger.Warn("error while initializing emsHealthMatrix", slogx.Err(err))
+ return nil, nil, err
+ }
+
diskAlertCount := h.collectDiskAlerts()
shelfAlertCount := h.collectShelfAlerts()
supportAlertCount := h.collectSupportAlerts()
@@ -158,6 +184,7 @@ func (h *Health) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util
volumeRansomwareAlertCount := h.collectVolumeRansomwareAlerts()
volumeMoveAlertCount := h.collectVolumeMoveAlerts()
licenseAlertCount := h.collectLicenseAlerts()
+ emsAlertCount := h.collectEmsAlerts(emsMat)
resolutionInstancesCount := h.generateResolutionMetrics()
@@ -170,6 +197,8 @@ func (h *Health) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util
for _, value := range h.resolutionData {
result = append(result, value)
}
+
+ result = append(result, emsMat)
h.SLogger.Info(
"Collected",
slog.Int("numLicenseAlerts", licenseAlertCount),
@@ -183,12 +212,13 @@ func (h *Health) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util
slog.Int("numSupportAlerts", supportAlertCount),
slog.Int("numShelfAlerts", shelfAlertCount),
slog.Int("numDiskAlerts", diskAlertCount),
+ slog.Int("numEmsAlerts", emsAlertCount),
slog.Int("numResolutionInstanceCount", resolutionInstancesCount),
)
//nolint:gosec
h.client.Metadata.PluginInstances = uint64(diskAlertCount + shelfAlertCount + supportAlertCount + nodeAlertCount + HAAlertCount + networkEthernetPortAlertCount + networkFcpPortAlertCount +
- networkInterfaceAlertCount + volumeRansomwareAlertCount + volumeMoveAlertCount + licenseAlertCount + resolutionInstancesCount)
+ networkInterfaceAlertCount + volumeRansomwareAlertCount + volumeMoveAlertCount + licenseAlertCount + emsAlertCount + resolutionInstancesCount)
return result, h.client.Metadata, nil
}
@@ -270,7 +300,7 @@ func (h *Health) collectVolumeRansomwareAlerts() int {
instance *matrix.Instance
)
volumeRansomwareAlertCount := 0
- clusterVersion := h.client.Cluster().GetVersion()
+ clusterVersion := h.client.Remote().Version
ontapVersion, err := goversion.NewVersion(clusterVersion)
if err != nil {
h.SLogger.Error("Failed to parse version", slogx.Err(err), slog.String("version", clusterVersion))
@@ -635,6 +665,51 @@ func (h *Health) collectDiskAlerts() int {
return diskAlertCount
}
+func (h *Health) collectEmsAlerts(emsMat *matrix.Matrix) int {
+ var (
+ instance *matrix.Instance
+ )
+ emsAlertCount := 0
+ records, err := h.getEmsAlerts()
+ if err != nil {
+ if errs.IsRestErr(err, errs.APINotFound) {
+ h.SLogger.Debug("API not found", slogx.Err(err))
+ } else {
+ h.SLogger.Error("Failed to collect ems data", slogx.Err(err))
+ }
+ return 0
+ }
+ for _, record := range records {
+ node := record.Get("node.name").String()
+ severity := record.Get("message.severity").String()
+ message := record.Get("message.name").String()
+ source := record.Get("source").String()
+ if instance = emsMat.GetInstance(message); instance == nil {
+ instance, err = emsMat.NewInstance(message)
+ if err != nil {
+ h.SLogger.Warn("error while creating instance", slog.String("key", message))
+ continue
+ }
+ instance.SetLabel("node", node)
+ instance.SetLabel("message", message)
+ instance.SetLabel("source", source)
+ instance.SetLabel(severityLabel, severity)
+ h.setAlertMetric(emsMat, instance, 1)
+ emsAlertCount++
+ } else {
+ // Increment the alert metric count by 1
+ currentCount, err := h.getAlertMetric(emsMat, instance)
+ if err != nil {
+ h.SLogger.Error("Failed to get alert metric", slogx.Err(err))
+ continue
+ }
+ h.setAlertMetric(emsMat, instance, currentCount+1)
+ }
+ }
+
+ return emsAlertCount
+}
+
func (h *Health) getDisks() ([]gjson.Result, error) {
fields := []string{"name", "container_type"}
query := "api/storage/disks"
@@ -645,7 +720,7 @@ func (h *Health) getDisks() ([]gjson.Result, error) {
Filter([]string{"container_type=broken|unassigned"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getShelves() ([]gjson.Result, error) {
@@ -657,7 +732,7 @@ func (h *Health) getShelves() ([]gjson.Result, error) {
MaxRecords(collectors.DefaultBatchSize).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getNodes() ([]gjson.Result, error) {
@@ -670,7 +745,7 @@ func (h *Health) getNodes() ([]gjson.Result, error) {
Filter([]string{"health=false"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getHADown() ([]gjson.Result, error) {
@@ -683,7 +758,7 @@ func (h *Health) getHADown() ([]gjson.Result, error) {
Filter([]string{"possible=!true"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getRansomwareVolumes() ([]gjson.Result, error) {
@@ -694,7 +769,7 @@ func (h *Health) getRansomwareVolumes() ([]gjson.Result, error) {
Filter([]string{"anti_ransomware.state=enabled", "anti_ransomware.attack_probability=low|moderate|high"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getNonCompliantLicense() ([]gjson.Result, error) {
@@ -707,7 +782,7 @@ func (h *Health) getNonCompliantLicense() ([]gjson.Result, error) {
Filter([]string{"state=noncompliant"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getMoveFailedVolumes() ([]gjson.Result, error) {
@@ -720,7 +795,7 @@ func (h *Health) getMoveFailedVolumes() ([]gjson.Result, error) {
Filter([]string{"movement.state=cutover_wait|failed|cutover_pending"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getNonHomeLIFs() ([]gjson.Result, error) {
@@ -732,7 +807,7 @@ func (h *Health) getNonHomeLIFs() ([]gjson.Result, error) {
Filter([]string{"location.is_home=false"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getFCPorts() ([]gjson.Result, error) {
@@ -745,7 +820,7 @@ func (h *Health) getFCPorts() ([]gjson.Result, error) {
Filter([]string{"enabled=true", "state=offlined_by_system"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getEthernetPorts() ([]gjson.Result, error) {
@@ -758,7 +833,27 @@ func (h *Health) getEthernetPorts() ([]gjson.Result, error) {
Filter([]string{"enabled=true", "state=down"}).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
+}
+
+func (h *Health) getEmsAlerts() ([]gjson.Result, error) {
+ clusterTime, err := collectors.GetClusterTime(h.client, nil, h.SLogger)
+ if err != nil {
+ return nil, err
+ }
+ fromTime := clusterTime.Add(-24 * time.Hour).Unix()
+ timeFilter := fmt.Sprintf("time=>=%d", fromTime)
+ severityFilter := "message.severity=" + strings.Join(h.emsSeverity, "|")
+ fields := []string{"node,message,source"}
+ query := "api/support/ems/events"
+ href := rest.NewHrefBuilder().
+ APIPath(query).
+ Fields(fields).
+ MaxRecords(collectors.DefaultBatchSize).
+ Filter([]string{timeFilter, severityFilter}).
+ Build()
+
+ return collectors.InvokeRestCall(h.client, href)
}
func (h *Health) getSupportAlerts(filter []string) ([]gjson.Result, error) {
@@ -769,7 +864,7 @@ func (h *Health) getSupportAlerts(filter []string) ([]gjson.Result, error) {
Filter(filter).
Build()
- return collectors.InvokeRestCall(h.client, href, h.SLogger)
+ return collectors.InvokeRestCall(h.client, href)
}
// returns time filter (clustertime - polldata duration)
@@ -813,6 +908,15 @@ func (h *Health) setAlertMetric(mat *matrix.Matrix, instance *matrix.Instance, v
}
}
+func (h *Health) getAlertMetric(mat *matrix.Matrix, instance *matrix.Instance) (float64, error) {
+ m := mat.GetMetric("alerts")
+ if m != nil {
+ v, _ := m.GetValueFloat64(instance)
+ return v, nil
+ }
+ return 0, errors.New("alert metric doesn't exist")
+}
+
func (h *Health) generateResolutionMetrics() int {
resolutionInstancesCount := 0
for prevKey, prevMat := range h.previousData {
diff --git a/cmd/collectors/rest/plugins/ontaps3service/ontaps3service.go b/cmd/collectors/rest/plugins/ontaps3service/ontaps3service.go
index 18884de95..cc1555472 100644
--- a/cmd/collectors/rest/plugins/ontaps3service/ontaps3service.go
+++ b/cmd/collectors/rest/plugins/ontaps3service/ontaps3service.go
@@ -77,7 +77,7 @@ func (o *OntapS3Service) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matri
MaxRecords(collectors.DefaultBatchSize).
Build()
- if result, err = collectors.InvokeRestCall(o.client, href, o.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(o.client, href); err != nil {
return nil, nil, err
}
diff --git a/cmd/collectors/rest/plugins/securityaccount/securityaccount.go b/cmd/collectors/rest/plugins/securityaccount/securityaccount.go
index e8cd71767..b0dd58fc8 100644
--- a/cmd/collectors/rest/plugins/securityaccount/securityaccount.go
+++ b/cmd/collectors/rest/plugins/securityaccount/securityaccount.go
@@ -70,7 +70,7 @@ func (s *SecurityAccount) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matr
Build()
s.client.Metadata.Reset()
- if result, err = collectors.InvokeRestCall(s.client, href, s.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(s.client, href); err != nil {
return nil, nil, err
}
diff --git a/cmd/collectors/rest/plugins/snapmirror/snapmirror.go b/cmd/collectors/rest/plugins/snapmirror/snapmirror.go
index 6ef8117d9..2ca13a577 100644
--- a/cmd/collectors/rest/plugins/snapmirror/snapmirror.go
+++ b/cmd/collectors/rest/plugins/snapmirror/snapmirror.go
@@ -15,6 +15,7 @@ import (
"github.com/netapp/harvest/v2/pkg/util"
"log/slog"
"path/filepath"
+ "slices"
"strings"
"time"
)
@@ -231,6 +232,7 @@ func (m *SnapMirror) updateSMLabels(data *matrix.Matrix) {
func (m *SnapMirror) handleCGRelationships(data *matrix.Matrix, keys []string) {
for _, key := range keys {
+ var cgSourceVolumes, cgDestinationVolumes []string
cgInstance := data.GetInstance(key)
// find cgName from the destination_location, source_location
cgInstance.SetLabel("destination_cg_name", filepath.Base(cgInstance.GetLabel("destination_location")))
@@ -267,8 +269,15 @@ func (m *SnapMirror) handleCGRelationships(data *matrix.Matrix, keys []string) {
cgVolumeInstance.SetLabel("relationship_id", "")
cgVolumeInstance.SetLabel("source_volume", sourceVol)
cgVolumeInstance.SetLabel("destination_volume", destinationVol)
+ cgSourceVolumes = append(cgSourceVolumes, sourceVol)
+ cgDestinationVolumes = append(cgDestinationVolumes, destinationVol)
}
}
+ // Update parent CG source and destination volumes
+ slices.Sort(cgSourceVolumes)
+ slices.Sort(cgDestinationVolumes)
+ cgInstance.SetLabel("source_volume", strings.Join(cgSourceVolumes, ","))
+ cgInstance.SetLabel("destination_volume", strings.Join(cgDestinationVolumes, ","))
}
}
diff --git a/cmd/collectors/rest/plugins/svm/svm.go b/cmd/collectors/rest/plugins/svm/svm.go
index ec79a02d6..d05887b93 100644
--- a/cmd/collectors/rest/plugins/svm/svm.go
+++ b/cmd/collectors/rest/plugins/svm/svm.go
@@ -219,7 +219,7 @@ func (s *SVM) GetKerberosConfig() (map[string]string, error) {
MaxRecords(collectors.DefaultBatchSize).
Build()
- if result, err = collectors.InvokeRestCall(s.client, href, s.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(s.client, href); err != nil {
return nil, err
}
@@ -253,7 +253,7 @@ func (s *SVM) GetFpolicy() (map[string]Fpolicy, error) {
MaxRecords(collectors.DefaultBatchSize).
Build()
- if result, err = collectors.InvokeRestCall(s.client, href, s.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(s.client, href); err != nil {
return nil, err
}
@@ -288,7 +288,7 @@ func (s *SVM) GetIscsiServices() (map[string]string, error) {
MaxRecords(collectors.DefaultBatchSize).
Build()
- if result, err = collectors.InvokeRestCall(s.client, href, s.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(s.client, href); err != nil {
return nil, err
}
@@ -322,7 +322,7 @@ func (s *SVM) GetIscsiCredentials() (map[string]string, error) {
MaxRecords(collectors.DefaultBatchSize).
Build()
- if result, err = collectors.InvokeRestCall(s.client, href, s.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(s.client, href); err != nil {
return nil, err
}
diff --git a/cmd/collectors/rest/plugins/volume/volume.go b/cmd/collectors/rest/plugins/volume/volume.go
index 2b481d648..cbc7d24c2 100644
--- a/cmd/collectors/rest/plugins/volume/volume.go
+++ b/cmd/collectors/rest/plugins/volume/volume.go
@@ -17,6 +17,7 @@ import (
"github.com/netapp/harvest/v2/pkg/util"
"github.com/tidwall/gjson"
"log/slog"
+ "os"
"strconv"
"time"
)
@@ -24,6 +25,8 @@ import (
const HoursInMonth = 24 * 30
const ARWSupportedVersion = "9.10.0"
+var enableVolumeLogging bool
+
type Volume struct {
*plugin.AbstractPlugin
currentVal int
@@ -90,10 +93,11 @@ func (v *Volume) Init() error {
// Read template to decide inclusion of flexgroup constituents
v.includeConstituents = collectors.ReadPluginKey(v.Params, "include_constituents")
// ARW feature is supported from 9.10 onwards, If we ask this field in Rest call in plugin, then it will be failed.
- v.isArwSupportedVersion, err = util.VersionAtLeast(v.client.Cluster().GetVersion(), ARWSupportedVersion)
+ v.isArwSupportedVersion, err = util.VersionAtLeast(v.client.Remote().Version, ARWSupportedVersion)
if err != nil {
return fmt.Errorf("unable to get version %w", err)
}
+ enableVolumeLogging = os.Getenv("ENABLE_VOLUME_LOGGING") != ""
return nil
}
@@ -120,11 +124,11 @@ func (v *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util
volumeMap, err := v.getVolumeInfo()
if err != nil {
v.SLogger.Error("Failed to collect volume info data", slogx.Err(err))
+ } else {
+ // update volume instance labels
+ v.updateVolumeLabels(data, volumeMap)
}
- // update volume instance labels
- v.updateVolumeLabels(data, volumeMap)
-
// parse anti_ransomware_start_time, antiRansomwareState for all volumes and export at cluster level
v.handleARWProtection(data)
@@ -134,6 +138,11 @@ func (v *Volume) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util
func (v *Volume) updateVolumeLabels(data *matrix.Matrix, volumeMap map[string]volumeInfo) {
var err error
+
+ if enableVolumeLogging {
+ v.SLogger.Info("Size of volumeMap", slog.Int("size", len(volumeMap)), slog.Any("volumeMap", volumeMap))
+ }
+
cloneSplitEstimateMetric := data.GetMetric("clone_split_estimate")
if cloneSplitEstimateMetric == nil {
if cloneSplitEstimateMetric, err = data.NewMetricFloat64("clone_split_estimate"); err != nil {
@@ -147,6 +156,9 @@ func (v *Volume) updateVolumeLabels(data *matrix.Matrix, volumeMap map[string]vo
}
if volume.GetLabel("style") == "flexgroup_constituent" {
+ if enableVolumeLogging {
+ v.SLogger.Warn("Setting exportable for flexgroup constituent", slog.String("volume", volume.GetLabel("volume")), slog.Bool("exportable", v.includeConstituents))
+ }
volume.SetExportable(v.includeConstituents)
}
@@ -154,6 +166,9 @@ func (v *Volume) updateVolumeLabels(data *matrix.Matrix, volumeMap map[string]vo
if vInfo, ok := volumeMap[volume.GetLabel("volume")+volume.GetLabel("svm")]; ok {
if vInfo.isObjectStoreVolume {
+ if enableVolumeLogging {
+ v.SLogger.Warn("Setting exportable for object store volume", slog.String("volume", volume.GetLabel("volume")), slog.Bool("exportable", false))
+ }
volume.SetExportable(false)
continue
}
@@ -175,6 +190,9 @@ func (v *Volume) updateVolumeLabels(data *matrix.Matrix, volumeMap map[string]vo
}
} else {
// The public API does not include node root and temp volumes, while the private CLI does include them. Harvest will exclude them the same as the public API by not exporting them.
+ if enableVolumeLogging {
+ v.SLogger.Warn("Setting exportable for excluded volume", slog.String("volume", volume.GetLabel("volume")), slog.Bool("exportable", false))
+ }
volume.SetExportable(false)
}
}
@@ -271,7 +289,7 @@ func (v *Volume) getEncryptedDisks() ([]gjson.Result, error) {
Filter([]string{"protection_mode=!data|full"}).
Build()
- if result, err = collectors.InvokeRestCall(v.client, href, v.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(v.client, href); err != nil {
return nil, err
}
return result, nil
@@ -308,7 +326,7 @@ func (v *Volume) getVolume(field string, fields []string, volumeMap map[string]v
Filter([]string{field}).
Build()
- if result, err = collectors.InvokeRestCall(v.client, href, v.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(v.client, href); err != nil {
return nil, err
}
diff --git a/cmd/collectors/rest/plugins/volumeanalytics/volumeanalytics.go b/cmd/collectors/rest/plugins/volumeanalytics/volumeanalytics.go
index 835b95631..197e50464 100644
--- a/cmd/collectors/rest/plugins/volumeanalytics/volumeanalytics.go
+++ b/cmd/collectors/rest/plugins/volumeanalytics/volumeanalytics.go
@@ -99,7 +99,7 @@ func (v *VolumeAnalytics) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matr
v.client.Metadata.Reset()
cluster := data.GetGlobalLabels()["cluster"]
- clusterVersion := v.client.Cluster().GetVersion()
+ clusterVersion := v.client.Remote().Version
ontapVersion, err := goversion.NewVersion(clusterVersion)
if err != nil {
v.SLogger.Error("Failed to parse version",
diff --git a/cmd/collectors/rest/rest.go b/cmd/collectors/rest/rest.go
index 95ee382a4..fdc4d5528 100644
--- a/cmd/collectors/rest/rest.go
+++ b/cmd/collectors/rest/rest.go
@@ -37,8 +37,8 @@ import (
"log/slog"
"os"
"regexp"
+ "slices"
"sort"
- "strconv"
"strings"
"time"
)
@@ -201,6 +201,8 @@ func (r *Rest) InitClient() error {
}
r.Client.TraceLogSet(r.Name, r.Params)
+ r.Remote = r.Client.Remote()
+
return nil
}
@@ -209,7 +211,7 @@ func (r *Rest) InitMatrix() error {
// overwrite from abstract collector
mat.Object = r.Prop.Object
// Add system (cluster) name
- mat.SetGlobalLabel("cluster", r.Client.Cluster().Name)
+ mat.SetGlobalLabel("cluster", r.Remote.Name)
if r.Params.HasChildS("labels") {
for _, l := range r.Params.GetChildS("labels").GetChildren() {
@@ -333,7 +335,7 @@ func (r *Rest) PollCounter() (map[string]*matrix.Matrix, error) {
apiD := time.Since(startTime)
startTime = time.Now()
- v, err := util.VersionAtLeast(r.Client.Cluster().GetVersion(), "9.11.1")
+ v, err := util.VersionAtLeast(r.Remote.Version, "9.11.1")
if err != nil {
return nil, err
}
@@ -709,6 +711,7 @@ func (r *Rest) CollectAutoSupport(p *collector.Payload) {
for k := range r.Prop.Counters {
counters = append(counters, k)
}
+ slices.Sort(counters)
var schedules = make([]collector.Schedule, 0)
tasks := r.Params.GetChildS("schedule")
@@ -745,14 +748,18 @@ func (r *Rest) CollectAutoSupport(p *collector.Payload) {
InstanceInfo: &info,
})
- if (r.Name == "Rest" && (r.Object == "Volume" || r.Object == "Node")) || r.Name == "Ems" {
- version := r.Client.Cluster().Version
- p.Target.Version = strconv.Itoa(version[0]) + "." + strconv.Itoa(version[1]) + "." + strconv.Itoa(version[2])
+ isRest := r.Name == "Rest"
+ isKeyPerf := r.Name == "KeyPerf"
+ isEMS := r.Name == "Ems"
+ isOneOfVolumeNode := r.Object == "Volume" || r.Object == "Node"
+
+ if ((isRest || isKeyPerf) && isOneOfVolumeNode) || isEMS {
+ p.Target.Version = r.Remote.Version
p.Target.Model = "cdot"
if p.Target.Serial == "" {
- p.Target.Serial = r.Client.Cluster().UUID
+ p.Target.Serial = r.Remote.UUID
}
- p.Target.ClusterUUID = r.Client.Cluster().UUID
+ p.Target.ClusterUUID = r.Remote.UUID
if r.Object == "Node" || r.Name == "ems" {
var (
diff --git a/cmd/collectors/rest/rest_test.go b/cmd/collectors/rest/rest_test.go
index b4b4373dc..bb23d1db7 100644
--- a/cmd/collectors/rest/rest_test.go
+++ b/cmd/collectors/rest/rest_test.go
@@ -353,7 +353,7 @@ func TestFields(t *testing.T) {
func TestQuotas(t *testing.T) {
r := newRest("Quota", "quota.yaml", "../../../conf")
var instanceKeys []string
- result, err := collectors.InvokeRestCallWithTestFile(r.Client, "", r.Logger, "testdata/quota.json")
+ result, err := collectors.InvokeRestCallWithTestFile(r.Client, "", "testdata/quota.json")
if err != nil {
t.Errorf("Error while invoking quota rest api call")
}
diff --git a/cmd/collectors/rest/templating.go b/cmd/collectors/rest/templating.go
index fc68a5dd4..0e29bc9c8 100644
--- a/cmd/collectors/rest/templating.go
+++ b/cmd/collectors/rest/templating.go
@@ -18,7 +18,7 @@ import (
func (r *Rest) LoadTemplate() (string, error) {
jitter := r.Params.GetChildContentS("jitter")
- template, path, err := r.ImportSubTemplate("", TemplateFn(r.Params, r.Object), jitter, r.Client.Cluster().Version)
+ template, path, err := r.ImportSubTemplate("", TemplateFn(r.Params, r.Object), jitter, r.Remote.Version)
if err != nil {
return "", err
}
@@ -39,6 +39,10 @@ func (r *Rest) InitCache() error {
r.Prop.Object = strings.ToLower(r.Object)
}
+ if shouldIgnore := r.Params.GetChildContentS("ignore"); shouldIgnore == "true" {
+ return nil
+ }
+
if e := r.Params.GetChildS("export_options"); e != nil {
r.Matrix[r.Object].SetExportOptions(e)
}
diff --git a/cmd/collectors/restperf/plugins/nic/nic.go b/cmd/collectors/restperf/plugins/nic/nic.go
index 107268c63..33d2a687c 100644
--- a/cmd/collectors/restperf/plugins/nic/nic.go
+++ b/cmd/collectors/restperf/plugins/nic/nic.go
@@ -241,7 +241,7 @@ func (n *Nic) getIfgroupInfo() map[string]string {
MaxRecords(collectors.DefaultBatchSize).
Build()
- if ifgroupsData, err = collectors.InvokeRestCallWithTestFile(n.client, href, n.SLogger, n.testFilePath); err != nil {
+ if ifgroupsData, err = collectors.InvokeRestCallWithTestFile(n.client, href, n.testFilePath); err != nil {
return portIfgroupMap
}
diff --git a/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients.go b/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients.go
index 1e9f176d3..082de6e12 100644
--- a/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients.go
+++ b/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients.go
@@ -367,7 +367,7 @@ func (t *TopClients) fetchVolumesWithActivityTrackingEnabled() (*set.Set, error)
Filter([]string{"activity_tracking.state=on"}).
Build()
- if result, err = collectors.InvokeRestCall(t.client, href, t.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(t.client, href); err != nil {
return va, err
}
@@ -395,7 +395,7 @@ func (t *TopClients) fetchTopClients(volumes *set.Set, svms *set.Set, metric str
Filter([]string{"top_metric=" + metric, "volume=" + strings.Join(volumes.Values(), "|"), "svm=" + strings.Join(svms.Values(), "|")}).
Build()
- if result, err = collectors.InvokeRestCall(t.client, href, t.SLogger); err != nil {
+ if result, err = collectors.InvokeRestCall(t.client, href); err != nil {
return result, err
}
diff --git a/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients_test.go b/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients_test.go
index 1c1565a86..a8ff51af3 100644
--- a/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients_test.go
+++ b/cmd/collectors/restperf/plugins/volumetopclients/volumetopclients_test.go
@@ -18,7 +18,7 @@ type MockVolume struct {
}
func (mv *MockVolume) fetchTopClients(_ *set.Set, _ *set.Set, _ string) ([]gjson.Result, error) {
- return collectors.InvokeRestCallWithTestFile(nil, "", nil, mv.testFilePath)
+ return collectors.InvokeRestCallWithTestFile(nil, "", mv.testFilePath)
}
func (mv *MockVolume) fetchVolumesWithActivityTrackingEnabled() (*set.Set, error) {
diff --git a/cmd/collectors/restperf/restperf.go b/cmd/collectors/restperf/restperf.go
index 84e482ff9..99677926f 100644
--- a/cmd/collectors/restperf/restperf.go
+++ b/cmd/collectors/restperf/restperf.go
@@ -3,6 +3,7 @@ package restperf
import (
"context"
"fmt"
+ "github.com/netapp/harvest/v2/cmd/collectors"
rest2 "github.com/netapp/harvest/v2/cmd/collectors/rest"
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/disk"
"github.com/netapp/harvest/v2/cmd/collectors/restperf/plugins/fabricpool"
@@ -197,7 +198,7 @@ func (r *RestPerf) InitMatrix() error {
// overwrite from abstract collector
mat.Object = r.Prop.Object
// Add system (cluster) name
- mat.SetGlobalLabel("cluster", r.Client.Cluster().Name)
+ mat.SetGlobalLabel("cluster", r.Remote.Name)
if r.Params.HasChildS("labels") {
for _, l := range r.Params.GetChildS("labels").GetChildren() {
mat.SetGlobalLabel(l.GetNameS(), l.GetContentS())
@@ -1624,9 +1625,13 @@ func (r *RestPerf) updateQosLabels(qos gjson.Result, instance *matrix.Instance,
func (r *RestPerf) handleError(err error, href string) (map[string]*matrix.Matrix, error) {
if errs.IsRestErr(err, errs.TableNotFound) || errs.IsRestErr(err, errs.APINotFound) {
// the table or API does not exist. return ErrAPIRequestRejected so the task goes to stand-by
- return nil, fmt.Errorf("polling href=[%s] err: %w", href, errs.New(errs.ErrAPIRequestRejected, err.Error()))
+ return nil, fmt.Errorf(
+ "polling href=[%s] err: %w",
+ collectors.TruncateURL(href),
+ errs.New(errs.ErrAPIRequestRejected, err.Error()),
+ )
}
- return nil, fmt.Errorf("failed to fetch data. href=[%s] err: %w", href, err)
+ return nil, fmt.Errorf("failed to fetch data. href=[%s] err: %w", collectors.TruncateURL(href), err)
}
func (r *RestPerf) InitSchedule() {
diff --git a/cmd/collectors/storagegrid/rest/client.go b/cmd/collectors/storagegrid/rest/client.go
index f13b1f2d9..7f9144a7b 100644
--- a/cmd/collectors/storagegrid/rest/client.go
+++ b/cmd/collectors/storagegrid/rest/client.go
@@ -18,6 +18,7 @@ import (
"math"
"net/http"
"net/url"
+ "strconv"
"strings"
"time"
)
@@ -35,7 +36,7 @@ type Client struct {
buffer *bytes.Buffer
Logger *slog.Logger
baseURL string
- Cluster Cluster
+ Remote conf.Remote
token string
Timeout time.Duration
logRest bool // used to log Rest request/response
@@ -44,13 +45,6 @@ type Client struct {
Metadata *util.Metadata
}
-type Cluster struct {
- Name string
- Info string
- UUID string
- Version [3]int
-}
-
func NewClient(pollerName string, clientTimeout string, c *auth.Credentials) (*Client, error) {
var (
poller *conf.Poller
@@ -303,13 +297,13 @@ func (c *Client) Init(retries int) error {
}
results = gjson.ParseBytes(content)
- c.Cluster.Name = results.Get("data.name").String()
+ c.Remote.Name = results.Get("data.name").String()
if content, err = c.GetGridRest("grid/license"); err != nil {
continue
}
results = gjson.ParseBytes(content)
- c.Cluster.UUID = results.Get("data.systemId").String()
+ c.Remote.UUID = results.Get("data.systemId").String()
return nil
}
@@ -324,9 +318,10 @@ func (c *Client) SetVersion(v string) error {
// e.g 11.6.0.3-20220802.2201.f58633a
segments := newVersion.Segments()
if len(segments) >= 3 {
- c.Cluster.Version[0] = check(segments[0])
- c.Cluster.Version[1] = check(segments[1])
- c.Cluster.Version[2] = check(segments[2])
+ v0 := check(segments[0])
+ v1 := check(segments[1])
+ v2 := check(segments[2])
+ c.Remote.Version = strconv.Itoa(v0) + "." + strconv.Itoa(v1) + "." + strconv.Itoa(v2)
} else {
return fmt.Errorf("failed to parse version %s", v)
}
diff --git a/cmd/collectors/storagegrid/rest/dummyclient.go b/cmd/collectors/storagegrid/rest/dummyclient.go
index 5977eff49..f0875a644 100644
--- a/cmd/collectors/storagegrid/rest/dummyclient.go
+++ b/cmd/collectors/storagegrid/rest/dummyclient.go
@@ -2,6 +2,7 @@ package rest
import (
"bytes"
+ "github.com/netapp/harvest/v2/pkg/conf"
"github.com/netapp/harvest/v2/pkg/util"
"log/slog"
@@ -20,11 +21,10 @@ func NewDummyClient() *Client {
buffer := new(bytes.Buffer)
- cluster := Cluster{
+ remote := conf.Remote{
Name: "TestCluster",
- Info: "TestInfo",
UUID: "TestUUID",
- Version: [3]int{1, 2, 3},
+ Version: "1.2.3",
}
client := &Client{
@@ -33,7 +33,7 @@ func NewDummyClient() *Client {
buffer: buffer,
Logger: slog.Default(),
baseURL: "http://example.com",
- Cluster: cluster,
+ Remote: remote,
token: "TestToken",
Timeout: time.Second * 10,
logRest: true,
diff --git a/cmd/collectors/storagegrid/storagegrid.go b/cmd/collectors/storagegrid/storagegrid.go
index cdff8d2cb..0eb215388 100644
--- a/cmd/collectors/storagegrid/storagegrid.go
+++ b/cmd/collectors/storagegrid/storagegrid.go
@@ -15,6 +15,7 @@ import (
"github.com/netapp/harvest/v2/pkg/util"
"github.com/tidwall/gjson"
"log/slog"
+ "slices"
"sort"
"strconv"
"strings"
@@ -91,7 +92,7 @@ func (s *StorageGrid) InitMatrix() error {
// overwrite from abstract collector
mat.Object = s.Props.Object
// Add system (cluster) name
- mat.SetGlobalLabel("cluster", s.client.Cluster.Name)
+ mat.SetGlobalLabel("cluster", s.client.Remote.Name)
if s.Params.HasChildS("labels") {
for _, l := range s.Params.GetChildS("labels").GetChildren() {
@@ -441,6 +442,8 @@ func (s *StorageGrid) initClient() error {
}
s.client.TraceLogSet(s.Name, s.Params)
+ s.Remote = s.client.Remote
+
return nil
}
@@ -492,7 +495,7 @@ func (s *StorageGrid) LoadTemplate() (string, error) {
jitter := s.Params.GetChildContentS("jitter")
- template, path, err = s.ImportSubTemplate("", rest.TemplateFn(s.Params, s.Object), jitter, s.client.Cluster.Version)
+ template, path, err = s.ImportSubTemplate("", rest.TemplateFn(s.Params, s.Object), jitter, s.Remote.Version)
if err != nil {
return "", err
}
@@ -540,6 +543,7 @@ func (s *StorageGrid) CollectAutoSupport(p *collector.Payload) {
for k := range s.Props.Counters {
counters = append(counters, k)
}
+ slices.Sort(counters)
var schedules = make([]collector.Schedule, 0)
tasks := s.Params.GetChildS("schedule")
@@ -576,10 +580,10 @@ func (s *StorageGrid) CollectAutoSupport(p *collector.Payload) {
InstanceInfo: &info,
})
- version := s.client.Cluster.Version
- p.Target.Version = strconv.Itoa(version[0]) + "." + strconv.Itoa(version[1]) + "." + strconv.Itoa(version[2])
+ version := s.Remote.Version
+ p.Target.Version = version
p.Target.Model = "storagegrid"
- p.Target.ClusterUUID = s.client.Cluster.UUID
+ p.Target.ClusterUUID = s.Remote.UUID
if p.Nodes == nil {
nodeIDs, err := s.getNodeUuids()
diff --git a/cmd/collectors/zapi/collector/zapi.go b/cmd/collectors/zapi/collector/zapi.go
index 7556f2b27..33fbbd6be 100644
--- a/cmd/collectors/zapi/collector/zapi.go
+++ b/cmd/collectors/zapi/collector/zapi.go
@@ -25,6 +25,7 @@ import (
"github.com/netapp/harvest/v2/pkg/slogx"
"github.com/netapp/harvest/v2/pkg/util"
"log/slog"
+ "slices"
"sort"
"strconv"
"strings"
@@ -93,7 +94,7 @@ func (z *Zapi) InitVars() error {
if z.Options.IsTest {
z.Client = client.NewTestClient()
templateName := z.Params.GetChildS("objects").GetChildContentS(z.Object)
- template, path, err := z.ImportSubTemplate("cdot", templateName, jitter, [3]int{9, 8, 0})
+ template, path, err := z.ImportSubTemplate("cdot", templateName, jitter, "9.8.0")
if err != nil {
return err
}
@@ -119,13 +120,16 @@ func (z *Zapi) InitVars() error {
}
// save for ASUP messaging
- z.HostUUID = z.Client.Serial()
- version := z.Client.Version()
- z.HostVersion = strconv.Itoa(version[0]) + "." + strconv.Itoa(version[1]) + "." + strconv.Itoa(version[2])
- z.HostModel = model
- templateName := z.Params.GetChildS("objects").GetChildContentS(z.Object)
+ versionT := z.Client.Version()
+ z.Remote = conf.Remote{
+ Name: z.Client.Name(),
+ UUID: z.Client.Serial(),
+ Model: model,
+ Version: strconv.Itoa(versionT[0]) + "." + strconv.Itoa(versionT[1]) + "." + strconv.Itoa(versionT[2]),
+ }
- template, path, err := z.ImportSubTemplate(model, templateName, jitter, z.Client.Version())
+ templateName := z.Params.GetChildS("objects").GetChildContentS(z.Object)
+ template, path, err := z.ImportSubTemplate(model, templateName, jitter, z.Remote.Version)
if err != nil {
return err
}
@@ -436,6 +440,7 @@ func (z *Zapi) CollectAutoSupport(p *collector.Payload) {
c := z.Params.GetChildS("counters")
c.FlatList(&counters, "")
}
+ slices.Sort(counters)
var schedules = make([]collector.Schedule, 0)
tasks := z.Params.GetChildS("schedule")
@@ -480,10 +485,10 @@ func (z *Zapi) CollectAutoSupport(p *collector.Payload) {
})
if z.Name == "Zapi" && (z.Object == "Volume" || z.Object == "Node" || z.Object == "Qtree") {
- p.Target.Version = z.GetHostVersion()
- p.Target.Model = z.GetHostModel()
+ p.Target.Version = z.Remote.Version
+ p.Target.Model = z.Remote.Model
if p.Target.Serial == "" {
- p.Target.Serial = z.GetHostUUID()
+ p.Target.Serial = z.Remote.UUID
}
p.Target.ClusterUUID = z.Client.ClusterUUID()
diff --git a/cmd/poller/collector/asup.go b/cmd/poller/collector/asup.go
index 0cfd3c5bd..4b312fd1f 100644
--- a/cmd/poller/collector/asup.go
+++ b/cmd/poller/collector/asup.go
@@ -226,6 +226,14 @@ func BuildAndWriteAutoSupport(collectors []Collector, status *matrix.Matrix, pol
attachMemory(msg)
// give each collector the opportunity to attach autosupport information
+ slices.SortStableFunc(collectors, func(a, b Collector) int {
+ nameCmp := cmp.Compare(a.GetName(), b.GetName())
+ if nameCmp == 0 {
+ return cmp.Compare(a.GetObject(), b.GetObject())
+ }
+ return nameCmp
+ })
+
for _, c := range collectors {
c.CollectAutoSupport(msg)
}
diff --git a/cmd/poller/collector/collector.go b/cmd/poller/collector/collector.go
index 548215715..4984740fe 100644
--- a/cmd/poller/collector/collector.go
+++ b/cmd/poller/collector/collector.go
@@ -70,6 +70,7 @@ type Collector interface {
LoadPlugins(*node.Node, Collector, string) error
LoadPlugin(string, *plugin.AbstractPlugin) plugin.Plugin
CollectAutoSupport(p *Payload)
+ GetRemote() conf.Remote
}
const (
@@ -106,11 +107,9 @@ type AbstractCollector struct {
collectCount uint64 // count of collected data points
// this is different from what the collector will have in its metadata, since this variable
// holds count independent of the poll interval of the collector, used to give stats to Poller
- countMux *sync.Mutex // used for atomic access to collectCount
- Auth *auth.Credentials // used for authing the collector
- HostVersion string
- HostModel string
- HostUUID string
+ countMux *sync.Mutex // used for atomic access to collectCount
+ Auth *auth.Credentials // used for authing the collector
+ Remote conf.Remote
}
func New(name, object string, o *options.Options, params *node.Node, credentials *auth.Credentials) *AbstractCollector {
@@ -291,16 +290,8 @@ func (c *AbstractCollector) GetMetadata() *matrix.Matrix {
return c.Metadata
}
-func (c *AbstractCollector) GetHostModel() string {
- return c.HostModel
-}
-
-func (c *AbstractCollector) GetHostVersion() string {
- return c.HostVersion
-}
-
-func (c *AbstractCollector) GetHostUUID() string {
- return c.HostUUID
+func (c *AbstractCollector) GetRemote() conf.Remote {
+ return c.Remote
}
// Start will run the collector in an infinite loop
diff --git a/cmd/poller/collector/helpers.go b/cmd/poller/collector/helpers.go
index 669866ef9..ce421fc35 100644
--- a/cmd/poller/collector/helpers.go
+++ b/cmd/poller/collector/helpers.go
@@ -54,7 +54,7 @@ var versionRegex = regexp.MustCompile(`\d+\.\d+\.\d+`)
// are sorted, and we try to return the subtemplate that most closely matches the ONTAP version.
// Model is cdot or 7mode, filename is the name of the subtemplate, and ver is the
// ONTAP version triple (generation, major, minor)
-func (c *AbstractCollector) ImportSubTemplate(model, filename, jitter string, ver [3]int) (*node.Node, string, error) {
+func (c *AbstractCollector) ImportSubTemplate(model, filename, jitter string, verWithDots string) (*node.Node, string, error) {
var (
selectedVersion, templatePath string
@@ -72,7 +72,9 @@ func (c *AbstractCollector) ImportSubTemplate(model, filename, jitter string, ve
// string like "volume.yaml,custom_volume.yaml"
filenames := strings.Split(filename, ",")
- verWithDots := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(ver)), "."), "[]")
+ if verWithDots == "" {
+ verWithDots = "0.0.0"
+ }
ontapVersion, err := version.NewVersion(verWithDots)
if err != nil {
return nil, "", fmt.Errorf("no best-fit template found due to err=%w", err)
diff --git a/cmd/poller/poller.go b/cmd/poller/poller.go
index 05cd6151f..c0dfa40eb 100644
--- a/cmd/poller/poller.go
+++ b/cmd/poller/poller.go
@@ -135,6 +135,7 @@ type Poller struct {
auth *auth.Credentials
hasPromExporter bool
maxRssBytes uint64
+ startTime time.Time
}
// Init starts Poller, reads parameters, opens zeroLog handler, initializes metadata,
@@ -148,6 +149,7 @@ func (p *Poller) Init() error {
configPath string
)
+ p.startTime = time.Now()
p.options = opts.SetDefaults()
p.name = opts.Poller
@@ -384,7 +386,7 @@ func (p *Poller) Init() error {
if tools != nil && tools.AsupDisabled {
logger.Info("Autosupport is disabled")
} else {
- if p.targetIsOntap() {
+ if p.collectorIsBuiltin() {
// Write the payload after asupFirstWrite.
// This is to examine the autosupport contents
// Nothing is sent, sending happens based on the asupSchedule
@@ -569,6 +571,7 @@ func (p *Poller) Run() {
upe := 0 // up exporters
// update status of collectors
+ var remote conf.Remote
for _, c := range p.collectors {
code, _, msg := c.GetStatus()
@@ -587,8 +590,14 @@ func (p *Poller) Run() {
instance.SetLabel("reason", strings.ReplaceAll(msg, "\"", ""))
}
}
+
+ remote = c.GetRemote()
}
+ // add remote version and name to metadata
+ p.status.GetInstance("remote").SetLabel("version", remote.Version)
+ p.status.GetInstance("remote").SetLabel("name", remote.Name)
+
// update status of exporters
for _, ee := range p.exporters {
code, status, msg := ee.GetStatus()
@@ -822,6 +831,10 @@ func (p *Poller) loadCollectorObject(ocs []objectCollector) error {
)
}
} else {
+ if shouldIgnore := col.GetParams().GetChildContentS("ignore"); shouldIgnore == "true" {
+ logger.Debug("ignoring collector", slog.String("collector", oc.class), slog.String("object", oc.object))
+ continue
+ }
collectors = append(collectors, col)
logger.Debug(
"initialized collector-object",
@@ -1079,6 +1092,9 @@ func (p *Poller) loadMetadata() {
instance, _ := p.metadataTarget.NewInstance("host")
pInstance, _ := p.status.NewInstance("host")
+ pRemote, _ := p.status.NewInstance("remote")
+ pRemote.SetExportable(false)
+
instance.SetLabel("addr", p.target)
pInstance.SetLabel("addr", p.target)
@@ -1125,13 +1141,21 @@ var pollerCmd = &cobra.Command{
Run: startPoller,
}
-// Returns true if at least one collector is known
-// to collect from an Ontap system (needs to be updated
-// when we add other Ontap collectors, e.g. REST)
+// Returns true if at least one collector is one of the builtin collectors.
+func (p *Poller) collectorIsBuiltin() bool {
+ for _, c := range p.collectors {
+ _, ok := util.IsCollector[c.GetName()]
+ if ok {
+ return true
+ }
+ }
+ return false
+}
+// Returns true if at least one collector is known to collect from an Ontap system.
func (p *Poller) targetIsOntap() bool {
for _, c := range p.collectors {
- _, ok := util.IsCollector[c.GetName()]
+ _, ok := util.IsONTAPCollector[c.GetName()]
if ok {
return true
}
@@ -1428,11 +1452,19 @@ func (p *Poller) logPollerMetadata() (map[string]*matrix.Matrix, error) {
}
rss, _ := p.status.LazyGetValueFloat64("memory.rss", "host")
+ remoteName := p.status.GetInstance("remote").GetLabel("name")
+ remoteVersion := p.status.GetInstance("remote").GetLabel("version")
+
slog.Info(
"Metadata",
- slog.Float64("rssKB", rss),
- slog.Uint64("maxRssKB", p.maxRssBytes/1024),
+ slog.Float64("rssMB", rss/1024),
+ slog.Uint64("maxRssMB", p.maxRssBytes/1024/1024),
slog.String("version", strings.TrimSpace(version.String())),
+ slog.Group("remote",
+ slog.String("name", remoteName),
+ slog.String("version", remoteVersion),
+ ),
+ slog.Uint64("uptimeSeconds", uint64(time.Since(p.startTime).Seconds())),
)
return nil, nil
@@ -1445,6 +1477,9 @@ func (p *Poller) sendHarvestVersion() error {
err error
)
+ if !p.targetIsOntap() {
+ return nil
+ }
// connect to the cluster and retrieve the system version
if poller, err = conf.PollerNamed(opts.Poller); err != nil {
return err
@@ -1462,7 +1497,7 @@ func (p *Poller) sendHarvestVersion() error {
// If it is, send a harvestTag to the cluster to indicate that Harvest is running
// Otherwise, do nothing
- ontapVersion, err := goversion.NewVersion(connection.Cluster().GetVersion())
+ ontapVersion, err := goversion.NewVersion(connection.Remote().Version)
if err != nil {
return err
}
diff --git a/cmd/tools/generate/counter.go b/cmd/tools/generate/counter.go
index ffc86354b..89f08a8a8 100644
--- a/cmd/tools/generate/counter.go
+++ b/cmd/tools/generate/counter.go
@@ -41,6 +41,9 @@ var (
"security_ssh": "cluster_ssh_server",
"namespace": "nvme_namespace",
"fcp": "fc_port",
+ "svm_cifs": "cifs_service",
+ "svm_nfs": "nfs_service",
+ "lif": "ip_interface",
}
swaggerBytes []byte
excludePerfTemplates = map[string]struct{}{
@@ -145,7 +148,7 @@ var (
"aggr_hybrid_disk_count",
"nfs_clients_idle_duration",
"ems_events",
- "olume_top_clients",
+ "volume_top_clients",
}
excludeDocumentedZapiMetrics = []string{
@@ -278,12 +281,30 @@ func processRestCounters(dir string, client *rest.Client) map[string]Counter {
})
restCounters := visitRestTemplates(filepath.Join(dir, "conf", "rest"), client, func(path string, client *rest.Client) map[string]Counter { // revive:disable-line:unused-parameter
- return processRestConfigCounters(path)
+ return processRestConfigCounters(path, "REST")
+ })
+
+ keyPerfCounters := visitRestTemplates(filepath.Join(dir, "conf", "keyperf"), client, func(path string, client *rest.Client) map[string]Counter { // revive:disable-line:unused-parameter
+ return processRestConfigCounters(path, "KeyPerf")
})
for k, v := range restPerfCounters {
restCounters[k] = v
}
+
+ keyPerfKeys := slices.Sorted(maps.Keys(keyPerfCounters))
+ for _, k := range keyPerfKeys {
+ if strings.Contains(k, "timestamp") || strings.Contains(k, "labels") {
+ continue
+ }
+ v := keyPerfCounters[k]
+ if v1, ok := restCounters[k]; !ok {
+ restCounters[k] = v
+ } else {
+ v1.APIs = append(v1.APIs, v.APIs...)
+ restCounters[k] = v1
+ }
+ }
return restCounters
}
@@ -358,7 +379,7 @@ func handleZapiCounter(path []string, content string, object string) (string, st
}
// processRestConfigCounters process Rest config templates
-func processRestConfigCounters(path string) map[string]Counter {
+func processRestConfigCounters(path string, api string) map[string]Counter {
var (
counters = make(map[string]Counter)
)
@@ -383,7 +404,7 @@ func processRestConfigCounters(path string) map[string]Counter {
if templateCounters != nil {
metricLabels, labels = getAllExportedLabels(t, templateCounters.GetAllChildContentS())
- processCounters(templateCounters.GetAllChildContentS(), &model, path, model.Query, counters, metricLabels)
+ processCounters(templateCounters.GetAllChildContentS(), &model, path, model.Query, counters, metricLabels, api)
// This is for object_labels metrics
harvestName := model.Object + "_" + "labels"
counters[harvestName] = Counter{Name: harvestName, Labels: labels}
@@ -398,7 +419,7 @@ func processRestConfigCounters(path string) map[string]Counter {
query = line.GetContentS()
}
if line.GetNameS() == "counters" {
- processCounters(line.GetAllChildContentS(), &model, path, query, counters, metricLabels)
+ processCounters(line.GetAllChildContentS(), &model, path, query, counters, metricLabels, api)
}
}
}
@@ -411,7 +432,7 @@ func processRestConfigCounters(path string) map[string]Counter {
Name: model.Object + "_" + metric.Name,
APIs: []MetricDef{
{
- API: "REST",
+ API: api,
Endpoint: model.Query,
Template: path,
ONTAPCounter: metric.Source,
@@ -423,10 +444,17 @@ func processRestConfigCounters(path string) map[string]Counter {
}
}
+ if api == "KeyPerf" {
+ // handling for templates with common object names
+ if specialPerfObjects[model.Object] {
+ return specialHandlingPerfCounters(counters, model)
+ }
+ }
+
return counters
}
-func processCounters(counterContents []string, model *template2.Model, path, query string, counters map[string]Counter, metricLabels []string) {
+func processCounters(counterContents []string, model *template2.Model, path, query string, counters map[string]Counter, metricLabels []string, api string) {
for _, c := range counterContents {
if c == "" {
continue
@@ -444,7 +472,7 @@ func processCounters(counterContents []string, model *template2.Model, path, que
Description: description,
APIs: []MetricDef{
{
- API: "REST",
+ API: api,
Endpoint: query,
Template: path,
ONTAPCounter: name,
@@ -772,7 +800,7 @@ func updateDescription(description string) string {
return s
}
-func generateCounterTemplate(counters map[string]Counter, version [3]int) {
+func generateCounterTemplate(counters map[string]Counter, version string) {
targetPath := "docs/ontap-metrics.md"
t, err := template.New("counter.tmpl").ParseFiles("cmd/tools/generate/counter.tmpl")
if err != nil {
@@ -785,6 +813,9 @@ func generateCounterTemplate(counters map[string]Counter, version [3]int) {
keys := make([]string, 0, len(counters))
for k := range counters {
+ if strings.Contains(k, "_labels") {
+ continue
+ }
keys = append(keys, k)
}
sort.Strings(keys)
@@ -850,12 +881,11 @@ func generateCounterTemplate(counters map[string]Counter, version [3]int) {
}
}
table.Render()
- verWithDots := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(version)), "."), "[]")
c := CounterTemplate{
Counters: values,
CounterMetaData: CounterMetaData{
Date: time.Now().Format("2006-Jan-02"),
- OntapVersion: verWithDots,
+ OntapVersion: version,
},
}
diff --git a/cmd/tools/generate/counter.yaml b/cmd/tools/generate/counter.yaml
index 753469fb9..e66326695 100644
--- a/cmd/tools/generate/counter.yaml
+++ b/cmd/tools/generate/counter.yaml
@@ -1328,6 +1328,15 @@ counters:
ONTAPCounter: Harvest generated
Template: conf/rest/9.6.0/health.yaml
+ - Name: health_ems_alerts
+ Description: The health_ems_alerts metric monitors EMS (Event Management System), providing a count based on their severity and other attributes. This metric includes labels such as node, message, source, and severity (e.g., emergency, alert, error).
+ By default, it monitors alerts with emergency severity.
+ APIs:
+ - API: REST
+ Endpoint: NA
+ ONTAPCounter: Harvest generated
+ Template: conf/rest/9.6.0/health.yaml
+
- Name: qos_policy_adaptive_absolute_min_iops
Description: Specifies the absolute minimum IOPS that is used as an override when the expected_iops is less than this value.
APIs:
@@ -1927,3 +1936,15 @@ counters:
Endpoint: api/support/ems/events
ONTAPCounter: Harvest generated
Template: conf/ems/9.6.0/ems.yaml
+
+ - Name: net_port_status
+ Description: This metric indicates a value of 1 if the port state is up and a value of 0 for any other state.
+ APIs:
+ - API: REST
+ Endpoint: NA
+ ONTAPCounter: Harvest generated
+ Template: conf/rest/9.12.0/netport.yaml
+ - API: ZAPI
+ Endpoint: NA
+ ONTAPCounter: Harvest generated
+ Template: conf/zapi/cdot/9.8.0/netport.yaml
\ No newline at end of file
diff --git a/cmd/tools/generate/generate.go b/cmd/tools/generate/generate.go
index 4559e0877..128b32f96 100644
--- a/cmd/tools/generate/generate.go
+++ b/cmd/tools/generate/generate.go
@@ -554,7 +554,7 @@ func writeAdminSystemd(configFp string) {
println(color.Colorize("✓", color.Green) + " HTTP SD file: " + harvestAdminService + " created")
}
-func BuildMetrics(dir, configPath, pollerName string) (map[string]Counter, rest.Cluster) {
+func BuildMetrics(dir, configPath, pollerName string) (map[string]Counter, conf.Remote) {
var (
poller *conf.Poller
err error
@@ -612,7 +612,7 @@ func BuildMetrics(dir, configPath, pollerName string) (map[string]Counter, rest.
}
}
- return counters, restClient.Cluster()
+ return counters, restClient.Remote()
}
func generateDescription(dPath string, data []byte, counters map[string]Counter) {
diff --git a/cmd/tools/grafana/dashboard_test.go b/cmd/tools/grafana/dashboard_test.go
index 46c3844b1..a7a1f418f 100644
--- a/cmd/tools/grafana/dashboard_test.go
+++ b/cmd/tools/grafana/dashboard_test.go
@@ -21,6 +21,11 @@ var dashboards = []string{
"../../../grafana/dashboards/storagegrid",
}
+var cDotDashboards = []string{
+ "../../../grafana/dashboards/cmode",
+ "../../../grafana/dashboards/cmode-details",
+}
+
var throughputPattern = regexp.MustCompile(`(throughput|read_data|write_data|total_data)`)
var aggregationThroughputPattern = regexp.MustCompile(`(?i)(\w+)\(`)
@@ -1631,13 +1636,19 @@ func checkDescription(t *testing.T, path string, data []byte, count *int) {
}
func TestFSxFriendlyVariables(t *testing.T) {
- VisitDashboards(dashboards,
+ VisitDashboards(cDotDashboards,
func(path string, data []byte) {
checkVariablesAreFSxFriendly(t, path, data)
})
}
func checkVariablesAreFSxFriendly(t *testing.T, path string, data []byte) {
+
+ exceptionValues := map[string]bool{
+ "cmode/metadata.json": true,
+ "cmode/snapmirror_destinations.json": true,
+ }
+
gjson.GetBytes(data, "templating.list").ForEach(func(key, value gjson.Result) bool {
// Only consider query variables
if value.Get("type").String() != "query" {
@@ -1648,18 +1659,21 @@ func checkVariablesAreFSxFriendly(t *testing.T, path string, data []byte) {
definition := value.Get("definition").String()
varName := value.Get("name").String()
- if varName != "Cluster" && varName != "Datacenter" {
+ sPath := ShortPath(path)
+ isExceptionPath := exceptionValues[sPath]
+
+ if isExceptionPath || (varName != "Cluster" && varName != "Datacenter") {
return true
}
- if strings.Contains(query, "node_labels") {
- t.Errorf(`dashboard=%s path=templating.list[%s] variable="%s" has "node_labels" in query. Use "cluster_new_status" instead.`,
- ShortPath(path), key.String(), varName)
+ if !strings.Contains(query, "cluster_new_status") {
+ t.Errorf(`dashboard=%s path=templating.list[%s] variable="%s" does not have "cluster_new_status" in query. Found "%s" instead.`,
+ sPath, key.String(), varName, definition)
}
- if strings.Contains(definition, "node_labels") {
- t.Errorf(`dashboard=%s path=templating.list[%s] variable="%s" has "node_labels" in definition. Use "cluster_new_status" instead.`,
- ShortPath(path), key.String(), varName)
+ if !strings.Contains(definition, "cluster_new_status") {
+ t.Errorf(`dashboard=%s path=templating.list[%s] variable="%s" does not have "cluster_new_status" in definition. Found "%s" instead.`,
+ sPath, key.String(), varName, definition)
}
return true
})
diff --git a/cmd/tools/rest/client.go b/cmd/tools/rest/client.go
index 4eef5dd77..613335f98 100644
--- a/cmd/tools/rest/client.go
+++ b/cmd/tools/rest/client.go
@@ -40,7 +40,7 @@ type Client struct {
buffer *bytes.Buffer
Logger *slog.Logger
baseURL string
- cluster Cluster
+ remote conf.Remote
token string
Timeout time.Duration
logRest bool // used to log Rest request/response
@@ -48,13 +48,6 @@ type Client struct {
Metadata *util.Metadata
}
-type Cluster struct {
- Name string
- Info string
- UUID string
- Version [3]int
-}
-
func New(poller *conf.Poller, timeout time.Duration, credentials *auth.Credentials) (*Client, error) {
var (
client Client
@@ -347,12 +340,12 @@ func (c *Client) UpdateClusterInfo(retries int) error {
}
results := gjson.ParseBytes(content)
- c.cluster.Name = results.Get("name").String()
- c.cluster.UUID = results.Get("uuid").String()
- c.cluster.Info = results.Get("version.full").String()
- c.cluster.Version[0] = int(results.Get("version.generation").Int())
- c.cluster.Version[1] = int(results.Get("version.major").Int())
- c.cluster.Version[2] = int(results.Get("version.minor").Int())
+ c.remote.Name = results.Get("name").String()
+ c.remote.UUID = results.Get("uuid").String()
+ c.remote.Version =
+ results.Get("version.generation").String() + "." +
+ results.Get("version.major").String() + "." +
+ results.Get("version.minor").String()
return nil
}
return err
@@ -362,12 +355,6 @@ func (c *Client) Init(retries int) error {
return c.UpdateClusterInfo(retries)
}
-func (c *Client) Cluster() Cluster {
- return c.cluster
-}
-
-func (cl Cluster) GetVersion() string {
- ver := cl.Version
- return fmt.Sprintf("%d.%d.%d", ver[0], ver[1], ver[2])
-
+func (c *Client) Remote() conf.Remote {
+ return c.remote
}
diff --git a/cmd/tools/rest/rest.go b/cmd/tools/rest/rest.go
index b2a7658f8..3ca87f141 100644
--- a/cmd/tools/rest/rest.go
+++ b/cmd/tools/rest/rest.go
@@ -217,8 +217,8 @@ func fetchData(poller *conf.Poller, timeout time.Duration) (*Results, error) {
Poller: poller.Name,
Addr: poller.Addr,
API: args.API,
- Version: client.Cluster().GetVersion(),
- ClusterName: client.cluster.Name,
+ Version: client.remote.Version,
+ ClusterName: client.remote.Name,
Records: records,
NumRecords: len(records),
PollDurationMs: time.Since(now).Milliseconds(),
diff --git a/cmd/tools/template/template.go b/cmd/tools/template/template.go
index c616c5f82..93982ff5b 100644
--- a/cmd/tools/template/template.go
+++ b/cmd/tools/template/template.go
@@ -22,6 +22,7 @@ type Model struct {
Name string `yaml:"name"`
Query string `yaml:"query"`
Object string `yaml:"object"`
+ Ignore string `yaml:"ignore"`
ExportData string `yaml:"export_data"`
Endpoints []*Endpoint `yaml:"endpoints"`
ExportOptions struct {
@@ -80,6 +81,15 @@ func unmarshalModel(data []byte) (Model, error) {
return tm, errs.New(errs.ErrConfig, "template file is empty or does not exist")
}
contentNode := root.Content[0]
+ ignoreNode := searchNode(contentNode, "ignore")
+ if ignoreNode != nil && ignoreNode.Value == "true" {
+ tm.Ignore = ignoreNode.Value
+ nameNode := searchNode(contentNode, "name")
+ if nameNode != nil {
+ tm.Name = nameNode.Value
+ }
+ return tm, nil
+ }
err = readNameQueryObject(&tm, contentNode)
if err != nil {
return tm, err
diff --git a/cmd/tools/template/template_test.go b/cmd/tools/template/template_test.go
index abc861dff..8c3e1375f 100644
--- a/cmd/tools/template/template_test.go
+++ b/cmd/tools/template/template_test.go
@@ -372,6 +372,9 @@ func (m Metric) pathString() string {
func TestQueryPrefix(t *testing.T) {
visitTemplates(t, func(path string, model Model) {
+ if model.Ignore == "true" {
+ return
+ }
if !strings.HasPrefix(model.Query, "api/") {
t.Errorf("query should be prefixed with api/, got=%s path=[%s]", model.Query, shortPath(path))
}
@@ -547,7 +550,7 @@ func visitTemplates(t *testing.T, eachTemplate func(path string, model Model), d
if ext != ".yaml" {
return nil
}
- if strings.HasSuffix(path, "custom.yaml") || strings.HasSuffix(path, "default.yaml") {
+ if strings.HasSuffix(path, "custom.yaml") || strings.HasSuffix(path, "default.yaml") || strings.HasSuffix(path, "static_counter_definitions.yaml") {
return nil
}
model, err := ReadTemplate(path)
diff --git a/conf/keyperf/9.15.0/aggr.yaml b/conf/keyperf/9.15.0/aggr.yaml
index 5009c97fb..49e6e0b33 100644
--- a/conf/keyperf/9.15.0/aggr.yaml
+++ b/conf/keyperf/9.15.0/aggr.yaml
@@ -22,6 +22,8 @@ counters:
- statistics.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics
+ - filter:
+ - statistics.timestamp=!"-"
export_options:
diff --git a/conf/keyperf/9.15.0/cifs_vserver.yaml b/conf/keyperf/9.15.0/cifs_vserver.yaml
index 30172bdeb..63603e47b 100644
--- a/conf/keyperf/9.15.0/cifs_vserver.yaml
+++ b/conf/keyperf/9.15.0/cifs_vserver.yaml
@@ -14,13 +14,13 @@ counters:
- statistics.latency_raw.read => read_latency
- statistics.latency_raw.total => total_latency
- statistics.latency_raw.write => write_latency
- - statistics.throughput_raw.other => other_data
- statistics.throughput_raw.read => read_data
- statistics.throughput_raw.write => write_data
- statistics.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics
-
+ - filter:
+ - statistics.timestamp=!"-"
export_options:
instance_keys:
diff --git a/conf/keyperf/9.15.0/cluster.yaml b/conf/keyperf/9.15.0/cluster.yaml
index b60076bcc..74c1bc503 100644
--- a/conf/keyperf/9.15.0/cluster.yaml
+++ b/conf/keyperf/9.15.0/cluster.yaml
@@ -20,7 +20,8 @@ counters:
- statistics.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics
-
+ - filter:
+ - statistics.timestamp=!"-"
export_options:
instance_keys:
diff --git a/conf/keyperf/9.15.0/iscsi_svm.yaml b/conf/keyperf/9.15.0/iscsi_svm.yaml
deleted file mode 100644
index 1bbc20597..000000000
--- a/conf/keyperf/9.15.0/iscsi_svm.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-name: ISCSISvm
-query: api/protocols/san/iscsi/services
-object: iscsi_svm
-
-counters:
- - ^^svm.name => svm
- - ^statistics.status => status
- - ^target.name => target
- - statistics.iops_raw.other => other_ops
- - statistics.iops_raw.read => read_ops
- - statistics.iops_raw.total => total_ops
- - statistics.iops_raw.write => write_ops
- - statistics.latency_raw.other => other_latency
- - statistics.latency_raw.read => read_latency
- - statistics.latency_raw.total => total_latency
- - statistics.latency_raw.write => write_latency
- - statistics.throughput_raw.read => read_data
- - statistics.throughput_raw.total => total_data
- - statistics.throughput_raw.write => write_data
- - statistics.timestamp(timestamp) => timestamp
- - hidden_fields:
- - statistics
-
-export_options:
- instance_keys:
- - svm
- - target
diff --git a/conf/keyperf/9.15.0/lif.yaml b/conf/keyperf/9.15.0/lif.yaml
index b0d8aca82..e65b7e585 100644
--- a/conf/keyperf/9.15.0/lif.yaml
+++ b/conf/keyperf/9.15.0/lif.yaml
@@ -15,7 +15,8 @@ counters:
- statistics.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics
-
+ - filter:
+ - statistics.timestamp=!"-"
export_options:
instance_keys:
diff --git a/conf/keyperf/9.15.0/lun.yaml b/conf/keyperf/9.15.0/lun.yaml
deleted file mode 100644
index f90c3d38a..000000000
--- a/conf/keyperf/9.15.0/lun.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Lun
-query: api/storage/luns
-object: lun
-
-counters:
- - ^^uuid => uuid
- - ^location.volume.name => volume
- - ^name => path
- - ^statistics.status => status
- - ^svm.name => svm
- - statistics.iops_raw.other => other_ops
- - statistics.iops_raw.read => read_ops
- - statistics.iops_raw.total => total_ops
- - statistics.iops_raw.write => write_ops
- - statistics.latency_raw.other => other_latency
- - statistics.latency_raw.read => avg_read_latency
- - statistics.latency_raw.total => total_latency
- - statistics.latency_raw.write => avg_write_latency
- - statistics.throughput_raw.other => other_data
- - statistics.throughput_raw.read => read_data
- - statistics.throughput_raw.total => total_data
- - statistics.throughput_raw.write => write_data
- - statistics.timestamp(timestamp) => timestamp
- - hidden_fields:
- - statistics
-
-
-plugins:
- LabelAgent:
- split_regex:
- - path `^/[^/]+/([^/]+)(?:/.*?|)/([^/]+)$` volume,lun
- - path `^([^/]+)$` lun
-
-export_options:
- instance_keys:
- - lun
- - svm
- - volume
diff --git a/conf/keyperf/9.15.0/namespace.yaml b/conf/keyperf/9.15.0/namespace.yaml
deleted file mode 100644
index 30d314dde..000000000
--- a/conf/keyperf/9.15.0/namespace.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-name: Namespace
-query: api/storage/namespaces
-object: namespace
-
-counters:
- - ^^uuid => uuid
- - ^name => path
- - ^statistics.status => status
- - ^svm.name => svm
- - statistics.iops_raw.other => other_ops
- - statistics.iops_raw.read => read_ops
- - statistics.iops_raw.total => total_ops
- - statistics.iops_raw.write => write_ops
- - statistics.latency_raw.other => avg_other_latency
- - statistics.latency_raw.read => avg_read_latency
- - statistics.latency_raw.total => avg_total_latency
- - statistics.latency_raw.write => avg_write_latency
- - statistics.throughput_raw.other => other_data
- - statistics.throughput_raw.read => read_data
- - statistics.throughput_raw.total => total_data
- - statistics.throughput_raw.write => write_data
- - statistics.timestamp(timestamp) => timestamp
- - hidden_fields:
- - statistics
-
-plugins:
- LabelAgent:
- split:
- - path `/` ,,volume,namespace
-
-export_options:
- instance_keys:
- - namespace
- - path
- - svm
- - volume
diff --git a/conf/keyperf/9.15.0/nfsv3.yaml b/conf/keyperf/9.15.0/nfsv3.yaml
index 54f59ff6b..e3110544f 100644
--- a/conf/keyperf/9.15.0/nfsv3.yaml
+++ b/conf/keyperf/9.15.0/nfsv3.yaml
@@ -23,6 +23,8 @@ counters:
- statistics.v3.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics.v3
+ - filter:
+ - statistics.v3.timestamp=!"-"
export_options:
instance_keys:
diff --git a/conf/keyperf/9.15.0/nfsv4.yaml b/conf/keyperf/9.15.0/nfsv4.yaml
index 8c6580f43..6014f9d27 100644
--- a/conf/keyperf/9.15.0/nfsv4.yaml
+++ b/conf/keyperf/9.15.0/nfsv4.yaml
@@ -23,6 +23,8 @@ counters:
- statistics.v4.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics.v4
+ - filter:
+ - statistics.v4.timestamp=!"-"
export_options:
instance_keys:
diff --git a/conf/keyperf/9.15.0/nfsv4_1.yaml b/conf/keyperf/9.15.0/nfsv4_1.yaml
index bc533636a..5bca83688 100644
--- a/conf/keyperf/9.15.0/nfsv4_1.yaml
+++ b/conf/keyperf/9.15.0/nfsv4_1.yaml
@@ -23,6 +23,8 @@ counters:
- statistics.v41.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics.v41
+ - filter:
+ - statistics.v41.timestamp=!"-"
export_options:
instance_keys:
diff --git a/conf/keyperf/9.15.0/nfsv4_2.yaml b/conf/keyperf/9.15.0/nfsv4_2.yaml
deleted file mode 100644
index d2aa597b7..000000000
--- a/conf/keyperf/9.15.0/nfsv4_2.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-name: NFSv42
-query: api/protocols/nfs/services
-object: svm_nfs
-
-global_labels:
- - nfsv: v4.2
-
-counters:
- - ^^svm.uuid => uuid
- - ^statistics.v42.status => status
- - ^svm.name => svm
- - statistics.v42.iops_raw.other => other_ops
- - statistics.v42.iops_raw.read => read_ops
- - statistics.v42.iops_raw.total => ops
- - statistics.v42.iops_raw.write => write_ops
- - statistics.v42.latency_raw.other => other_latency
- - statistics.v42.latency_raw.read => read_avg_latency
- - statistics.v42.latency_raw.total => latency
- - statistics.v42.latency_raw.write => write_avg_latency
- - statistics.v42.throughput_raw.read => read_throughput
- - statistics.v42.throughput_raw.total => total_throughput
- - statistics.v42.throughput_raw.write => write_throughput
- - statistics.v42.timestamp(timestamp) => timestamp
- - hidden_fields:
- - statistics.v42
-
-export_options:
- instance_keys:
- - svm
\ No newline at end of file
diff --git a/conf/keyperf/9.15.0/node.yaml b/conf/keyperf/9.15.0/node.yaml
index b552fd0dd..938cd90c4 100644
--- a/conf/keyperf/9.15.0/node.yaml
+++ b/conf/keyperf/9.15.0/node.yaml
@@ -10,6 +10,8 @@ counters:
- statistics.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics
+ - filter:
+ - statistics.timestamp=!"-"
export_options:
instance_keys:
diff --git a/conf/keyperf/9.15.0/nvme_services.yaml b/conf/keyperf/9.15.0/nvme_services.yaml
deleted file mode 100644
index 20588b9b4..000000000
--- a/conf/keyperf/9.15.0/nvme_services.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-name: NvmeServices
-query: api/protocols/nvme/services
-object: nvme_services
-
-counters:
- - ^^svm.uuid => uuid
- - ^statistics.status => status
- - ^svm.name => svm
- - statistics.iops_raw.other => other_ops
- - statistics.iops_raw.read => read_ops
- - statistics.iops_raw.total => total_ops
- - statistics.iops_raw.write => write_ops
- - statistics.latency_raw.other => other_latency
- - statistics.latency_raw.read => read_latency
- - statistics.latency_raw.total => total_latency
- - statistics.latency_raw.write => write_latency
- - statistics.throughput_raw.read => read_data
- - statistics.throughput_raw.total => total_data
- - statistics.throughput_raw.write => write_data
- - statistics.timestamp(timestamp) => timestamp
- - hidden_fields:
- - statistics
-
-
-export_options:
- instance_keys:
- - svm
diff --git a/conf/keyperf/9.15.0/ontap_s3_svm.yaml b/conf/keyperf/9.15.0/ontap_s3_svm.yaml
deleted file mode 100644
index 48320c22f..000000000
--- a/conf/keyperf/9.15.0/ontap_s3_svm.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-name: OntapS3SVM
-query: api/protocols/s3/services
-object: ontaps3_svm
-
-counters:
- - ^^svm.name => svm
- - ^name => name
- - ^statistics.status => status
- - statistics.iops_raw.other => other_ops
- - statistics.iops_raw.read => read_ops
- - statistics.iops_raw.total => total_ops
- - statistics.iops_raw.write => write_ops
- - statistics.latency_raw.other => other_latency
- - statistics.latency_raw.read => read_latency
- - statistics.latency_raw.total => total_latency
- - statistics.latency_raw.write => write_latency
- - statistics.throughput_raw.read => read_data
- - statistics.throughput_raw.total => total_data
- - statistics.throughput_raw.write => write_data
- - statistics.timestamp(timestamp) => timestamp
- - hidden_fields:
- - statistics
-
-export_options:
- instance_keys:
- - name
- - svm
\ No newline at end of file
diff --git a/conf/keyperf/9.15.0/qtree.yaml b/conf/keyperf/9.15.0/qtree.yaml
index 0e13c072f..bba55d38d 100644
--- a/conf/keyperf/9.15.0/qtree.yaml
+++ b/conf/keyperf/9.15.0/qtree.yaml
@@ -20,6 +20,7 @@ counters:
- statistics.timestamp(timestamp) => timestamp
- filter:
- name=!""
+ - statistics.timestamp=!"-"
- hidden_fields:
- statistics
diff --git a/conf/keyperf/9.15.0/volume.yaml b/conf/keyperf/9.15.0/volume.yaml
index 1bfc2add9..b994c050b 100644
--- a/conf/keyperf/9.15.0/volume.yaml
+++ b/conf/keyperf/9.15.0/volume.yaml
@@ -22,6 +22,8 @@ counters:
- statistics.timestamp(timestamp) => timestamp
- hidden_fields:
- statistics
+ - filter:
+ - statistics.timestamp=!"-"
endpoints:
- query: api/private/cli/volume
diff --git a/conf/keyperf/default.yaml b/conf/keyperf/default.yaml
index 38d596b07..522eea2b9 100644
--- a/conf/keyperf/default.yaml
+++ b/conf/keyperf/default.yaml
@@ -9,16 +9,10 @@ objects:
Aggregate: aggr.yaml
CIFSvserver: cifs_vserver.yaml
Cluster: cluster.yaml
- ISCSISvm: iscsi_svm.yaml
LIF: lif.yaml
- Lun: lun.yaml
- Namespace: namespace.yaml
NFSv3: nfsv3.yaml
NFSv41: nfsv4_1.yaml
- NFSv42: nfsv4_2.yaml
NFSv4: nfsv4.yaml
Node: node.yaml
- NvmeServices: nvme_services.yaml
Volume: volume.yaml
Qtree: qtree.yaml
- OntapS3SVM: ontap_s3_svm.yaml
\ No newline at end of file
diff --git a/cmd/collectors/keyperf/static_counter_definitions.yaml b/conf/keyperf/static_counter_definitions.yaml
similarity index 100%
rename from cmd/collectors/keyperf/static_counter_definitions.yaml
rename to conf/keyperf/static_counter_definitions.yaml
diff --git a/conf/rest/9.6.0/aggr_efficiency.yaml b/conf/rest/9.6.0/aggr_efficiency.yaml
new file mode 100644
index 000000000..1d23f473d
--- /dev/null
+++ b/conf/rest/9.6.0/aggr_efficiency.yaml
@@ -0,0 +1,7 @@
+name: AggregateEfficiency
+# This template exists to prevent double exporting of aggregate efficiency metrics when
+# using both the Rest and Zapi collectors, in that order.
+# The Zapi collector exports aggregate efficiency objects via the AggregateEfficiency template
+# while the REST collector exports them via the Aggregate template. That means the normal object/collector dedup logic
+# won't handle these metrics.
+ignore: true
diff --git a/conf/rest/9.6.0/health.yaml b/conf/rest/9.6.0/health.yaml
index 41c0fe245..25c3ac3a6 100644
--- a/conf/rest/9.6.0/health.yaml
+++ b/conf/rest/9.6.0/health.yaml
@@ -7,6 +7,14 @@ counters:
- ^name
plugins:
- - Health
+ - Health:
+ # Description:
+ # This configuration enables the Health plugin to monitor EMS alerts based on specified severities.
+ # - severity: A list of severities to monitor. Possible values are emergency, alert, error, notice, informational, debug
+ ems:
+ severity:
+ - emergency
+# - alert
+# - error
export_data: false
diff --git a/conf/rest/default.yaml b/conf/rest/default.yaml
index d1ab7f59e..258357c71 100644
--- a/conf/rest/default.yaml
+++ b/conf/rest/default.yaml
@@ -10,6 +10,7 @@ schedule:
objects:
Aggregate: aggr.yaml
+ AggregateEfficiency: aggr_efficiency.yaml
# The CIFSSession template may slow down data collection due to a high number of metrics.
# CIFSSession: cifs_session.yaml
# CIFSShare: cifs_share.yaml
@@ -29,7 +30,7 @@ objects:
Namespace: namespace.yaml
# NDMPSession: ndmp_session.yaml
# NetConnections: netconnections.yaml
-# NetPort: netport.yaml
+ NetPort: netport.yaml
NetRoute: netroute.yaml
# NFSClients: nfs_clients.yaml
Node: node.yaml
diff --git a/conf/zapi/default.yaml b/conf/zapi/default.yaml
index 86e87dd7d..ada1502ae 100644
--- a/conf/zapi/default.yaml
+++ b/conf/zapi/default.yaml
@@ -19,7 +19,7 @@ objects:
LIF: lif.yaml
# Lock: lock.yaml
Lun: lun.yaml
-# NetPort: netport.yaml
+ NetPort: netport.yaml
Namespace: namespace.yaml
Node: node.yaml
NtpServer: ntpserver.yaml
diff --git a/docs/ontap-metrics.md b/docs/ontap-metrics.md
index 76c5d7f04..205ac2a1a 100644
--- a/docs/ontap-metrics.md
+++ b/docs/ontap-metrics.md
@@ -7,7 +7,7 @@ These can be generated on demand by running `bin/harvest grafana metrics`. See
- More information about ONTAP REST performance counters can be found [here](https://docs.netapp.com/us-en/ontap-pcmap-9121/index.html).
```
-Creation Date : 2024-Oct-03
+Creation Date : 2024-Oct-30
ONTAP Version: 9.15.1
```
## Understanding the structure
@@ -513,10 +513,6 @@ The percentage of disk space currently in use based on user-visible file count o
| ZAPI | `aggr-get-iter` | `aggr-attributes.aggr-inode-attributes.percent-inode-used-capacity` | conf/zapi/cdot/9.8.0/aggr.yaml |
-### aggr_labels
-
-
-
### aggr_logical_used_wo_snapshots
Logical used
@@ -565,6 +561,33 @@ Physical space usage of aggregates in the attached object store.
| REST | `api/private/cli/aggr/show-space` | `object_store_physical_used` | conf/rest/9.12.0/aggr.yaml |
+### aggr_other_data
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.throughput_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
+### aggr_other_latency
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
+### aggr_other_ops
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
### aggr_physical_used_wo_snapshots
Total Data Reduction Physical Used Without Snapshots
@@ -634,6 +657,33 @@ Option to specify the maximum number of disks that can be included in a RAID gro
| ZAPI | `aggr-get-iter` | `aggr-attributes.aggr-raid-attributes.raid-size` | conf/zapi/cdot/9.8.0/aggr.yaml |
+### aggr_read_data
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
+### aggr_read_latency
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
+### aggr_read_ops
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
### aggr_snapshot_files_total
Total files allowed in Snapshot copies
@@ -922,6 +972,24 @@ The percentage of disk space currently in use on the referenced file system
| ZAPI | `aggr-get-iter` | `aggr-attributes.aggr-space-attributes.percent-used-capacity` | conf/zapi/cdot/9.8.0/aggr.yaml |
+### aggr_total_data
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
+### aggr_total_latency
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
### aggr_total_logical_used
Logical used
@@ -932,6 +1000,15 @@ Logical used
| ZAPI | `aggr-efficiency-get-iter` | `aggr-efficiency-info.aggr-efficiency-cumulative-info.total-logical-used` | conf/zapi/cdot/9.9.0/aggr_efficiency.yaml |
+### aggr_total_ops
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+
+
### aggr_total_physical_used
Total Physical Used
@@ -952,27 +1029,42 @@ The aggregate's volume count, which includes both FlexVols and FlexGroup constit
| ZAPI | `aggr-get-iter` | `aggr-attributes.aggr-volume-count-attributes.flexvol-count` | conf/zapi/cdot/9.8.0/aggr.yaml |
-### cifs_session_connection_count
+### aggr_write_data
-A counter used to track requests that are sent to the volumes to the node.
+Peformance metric for write I/O operations.
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
-| REST | `api/protocols/cifs/sessions` | `connection_count` | conf/rest/9.8.0/cifs_session.yaml |
-| ZAPI | `cifs-session-get-iter` | `cifs-session.connection-count` | conf/zapi/cdot/9.8.0/cifs_session.yaml |
+| KeyPerf | `api/storage/aggregates` | `statistics.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
-### cifs_session_labels
+### aggr_write_latency
+Peformance metric for write I/O operations.
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
-### cifs_share_labels
+### aggr_write_ops
+Peformance metric for write I/O operations.
-### cloud_target_labels
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/aggregates` | `statistics.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/aggr.yaml |
+### cifs_session_connection_count
+
+A counter used to track requests that are sent to the volumes to the node.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| REST | `api/protocols/cifs/sessions` | `connection_count` | conf/rest/9.8.0/cifs_session.yaml |
+| ZAPI | `cifs-session-get-iter` | `cifs-session.connection-count` | conf/zapi/cdot/9.8.0/cifs_session.yaml |
+
### cloud_target_used
@@ -984,10 +1076,6 @@ The amount of cloud space used by all the aggregates attached to the target, in
| ZAPI | `aggr-object-store-config-get-iter` | `aggr-object-store-config-info.used-space` | conf/zapi/cdot/9.10.0/aggr_object_store_config.yaml |
-### cluster_labels
-
-
-
### cluster_new_status
It is an indicator of the overall health status of the cluster, with a value of 1 indicating a healthy status and a value of 0 indicating an unhealthy status.
@@ -998,9 +1086,32 @@ It is an indicator of the overall health status of the cluster, with a value of
| ZAPI | `NA` | `Harvest generated` | conf/zapi/cdot/9.8.0/status.yaml |
-### cluster_peer_labels
+### cluster_other_data
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.throughput_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+
+### cluster_other_latency
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+### cluster_other_ops
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
### cluster_peer_non_encrypted
@@ -1012,8 +1123,31 @@ This metric indicates a value of 1 if the cluster peer encryption state is none
| ZAPI | `NA` | `Harvest generated` | conf/zapi/cdot/9.8.0/clusterpeer.yaml |
-### cluster_subsystem_labels
+### cluster_read_data
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+
+### cluster_read_latency
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+### cluster_read_ops
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
### cluster_subsystem_new_status
@@ -1046,6 +1180,60 @@ Number of suppressed alerts
| ZAPI | `diagnosis-subsystem-config-get-iter` | `diagnosis-subsystem-config-info.suppressed-alert-count` | conf/zapi/cdot/9.8.0/subsystem.yaml |
+### cluster_total_data
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+
+### cluster_total_latency
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+
+### cluster_total_ops
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+
+### cluster_write_data
+
+Peformance metric for write I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+
+### cluster_write_latency
+
+Peformance metric for write I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+
+### cluster_write_ops
+
+Peformance metric for write I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/cluster` | `statistics.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cluster.yaml |
+
+
### copy_manager_bce_copy_count_curr
Current number of copy requests being processed by the Block Copy Engine.
@@ -1176,10 +1364,6 @@ Number of I/Os queued to the disk but not yet issued
| ZAPI | `perf-object-get-instances disk:constituent` | `io_queued`
Unit: none
Type: average
Base: base_for_disk_busy | conf/zapiperf/cdot/9.8.0/disk.yaml |
-### disk_labels
-
-
-
### disk_new_status
This metric indicates a value of 1 if the disk is not in an outage (i.e., the outage label is empty) and a value of 0 if the shelf is in an outage.
@@ -1368,10 +1552,6 @@ Number of disk write operations initiated each second for storing data or metada
| ZAPI | `perf-object-get-instances disk:constituent` | `user_writes`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/disk.yaml |
-### ems_destination_labels
-
-
-
### ems_events
Indicates EMS events that have occurred in the ONTAP as configured in the ems.yaml.
@@ -1411,10 +1591,6 @@ Average temperature of all non-ambient sensors for node in Celsius.
| ZAPI | `NA` | `Harvest generated` | conf/zapi/cdot/9.8.0/sensor.yaml |
-### environment_sensor_labels
-
-
-
### environment_sensor_max_fan_speed
Maximum fan speed for node in rpm.
@@ -1495,10 +1671,6 @@ Provides the sensor reading.
| ZAPI | `environment-sensors-get-iter` | `environment-sensors-info.threshold-sensor-value` | conf/zapi/cdot/9.8.0/sensor.yaml |
-### export_rule_labels
-
-
-
### external_service_op_num_not_found_responses
Number of 'Not Found' responses for calls to this operation.
@@ -1725,10 +1897,6 @@ Number of interrupt responses
| ZAPI | `perf-object-get-instances fcp_port` | `isr_count`
Unit: none
Type: delta
Base: | conf/zapiperf/cdot/9.8.0/fcp.yaml |
-### fcp_labels
-
-
-
### fcp_lif_avg_latency
Average latency for FCP operations
@@ -2809,10 +2977,6 @@ Total number of invalidate operation is skipped because cache volume is offline.
| ZAPI | `perf-object-get-instances flexcache_per_volume` | `invalidate_skipped_reason_offline`
Unit: none
Type: delta,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/flexcache.yaml |
-### flexcache_labels
-
-
-
### flexcache_miss_percent
This metric represents the percentage of block requests from a client that resulted in a "miss" in the FlexCache. A "miss" occurs when the requested data is not found in the cache and has to be retrieved from the origin volume.
@@ -3124,17 +3288,22 @@ Provides any issues related to Disks health check if disks are broken or unassig
| REST | `NA` | `Harvest generated` | conf/rest/9.6.0/health.yaml |
-### health_ha_alerts
+### health_ems_alerts
-Provides any issues related to HA health check. Value of 1 means issue is happening and 0 means that issue is resolved.
+The health_ems_alerts metric monitors EMS (Event Management System), providing a count based on their severity and other attributes. This metric includes labels such as node, message, source, and severity (e.g., emergency, alert, error). By default, it monitors alerts with emergency severity.
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `NA` | `Harvest generated` | conf/rest/9.6.0/health.yaml |
-### health_labels
+### health_ha_alerts
+
+Provides any issues related to HA health check. Value of 1 means issue is happening and 0 means that issue is resolved.
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| REST | `NA` | `Harvest generated` | conf/rest/9.6.0/health.yaml |
### health_license_alerts
@@ -3388,10 +3557,6 @@ Number of RDMA write I/Os issued.
| ZAPI | `perf-object-get-instances iwarp` | `iw_write_ops`
Unit: none
Type: delta
Base: | conf/zapiperf/cdot/9.8.0/iwarp.yaml |
-### lif_labels
-
-
-
### lif_recv_data
Number of bytes received per second
@@ -3399,6 +3564,7 @@ Number of bytes received per second
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/lif` | `received_data`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/lif.yaml |
+| KeyPerf | `api/network/ip/interfaces` | `statistics.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/lif.yaml |
| ZAPI | `perf-object-get-instances lif` | `recv_data`
Unit: b_per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/lif.yaml |
@@ -3429,6 +3595,7 @@ Number of bytes sent per second
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/lif` | `sent_data`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/lif.yaml |
+| KeyPerf | `api/network/ip/interfaces` | `statistics.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/lif.yaml |
| ZAPI | `perf-object-get-instances lif` | `sent_data`
Unit: b_per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/lif.yaml |
@@ -3452,8 +3619,13 @@ Number of packets sent per second
| ZAPI | `perf-object-get-instances lif` | `sent_packet`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/lif.yaml |
-### lock_labels
+### lif_total_data
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/network/ip/interfaces` | `statistics.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/lif.yaml |
### lun_avg_read_latency
@@ -3506,10 +3678,6 @@ Number of operations receiving ENOSPC errors
| ZAPI | `perf-object-get-instances lun` | `enospc`
Unit: none
Type: delta
Base: | conf/zapiperf/cdot/9.8.0/lun.yaml |
-### lun_labels
-
-
-
### lun_new_status
This metric indicates a value of 1 if the LUN state is online (indicating the LUN is operational) and a value of 0 for any other state. and a value of 0 for any other state.
@@ -3700,10 +3868,6 @@ Total number of xcopy operations on the LUN
| ZAPI | `perf-object-get-instances lun` | `xcopy_reqs`
Unit: none
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/lun.yaml |
-### mediator_labels
-
-
-
### metadata_collector_api_time
amount of time to collect data from monitored cluster object
@@ -3922,10 +4086,6 @@ Detail of the type of diagnostic operation run for the Cluster with diagnostic o
| REST | `NA` | `Harvest generated` | conf/rest/9.12.0/metrocluster_check.yaml |
-### metrocluster_check_labels
-
-
-
### metrocluster_check_node_status
Detail of the type of diagnostic operation run for the Node with diagnostic operation result.
@@ -3984,10 +4144,6 @@ The size of blocks in the namespace in bytes.
Valid in POST when creating an
| ZAPI | `nvme-namespace-get-iter` | `nvme-namespace-info.block-size` | conf/zapi/cdot/9.8.0/namespace.yaml |
-### namespace_labels
-
-
-
### namespace_other_ops
Number of other operations
@@ -4107,10 +4263,6 @@ Indicates the NDMP data bytes processed.
| REST | `api/protocols/ndmp/sessions` | `data.bytes_processed` | conf/rest/9.7.0/ndmp_session.yaml |
-### ndmp_session_labels
-
-
-
### ndmp_session_mover_bytes_moved
Indicates the NDMP mover bytes moved.
@@ -4120,14 +4272,6 @@ Indicates the NDMP mover bytes moved.
| REST | `api/protocols/ndmp/sessions` | `mover.bytes_moved` | conf/rest/9.7.0/ndmp_session.yaml |
-### net_connection_labels
-
-
-
-### net_port_labels
-
-
-
### net_port_mtu
Maximum transmission unit, largest packet size on this network
@@ -4138,8 +4282,14 @@ Maximum transmission unit, largest packet size on this network
| ZAPI | `net-port-get-iter` | `net-port-info.mtu` | conf/zapi/cdot/9.8.0/netport.yaml |
-### net_route_labels
+### net_port_status
+
+This metric indicates a value of 1 if the port state is up and a value of 0 for any other state.
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| REST | `NA` | `Harvest generated` | conf/rest/9.12.0/netport.yaml |
+| ZAPI | `NA` | `Harvest generated` | conf/zapi/cdot/9.8.0/netport.yaml |
### netstat_bytes_recvd
@@ -4223,10 +4373,6 @@ Specifies an ISO-8601 format of date and time to retrieve the idle time duration
| REST | `api/protocols/nfs/connected-clients` | `idle_duration` | conf/rest/9.7.0/nfs_clients.yaml |
-### nfs_clients_labels
-
-
-
### nfs_diag_storePool_ByteLockAlloc
Current number of byte range lock objects allocated.
@@ -4744,6 +4890,7 @@ Average processor utilization across active processors in the system
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/system:node` | `average_processor_busy_percent`
Unit: percent
Type: percent
Base: cpu_elapsed_time | conf/restperf/9.12.0/system_node.yaml |
+| KeyPerf | `api/cluster/nodes` | `statistics.processor_utilization_raw`
Unit:
Type:
Base: | conf/keyperf/9.15.0/node.yaml |
| ZAPI | `perf-object-get-instances system:node` | `avg_processor_busy`
Unit: percent
Type: percent
Base: cpu_elapsed_time | conf/zapiperf/cdot/9.8.0/system_node.yaml |
@@ -5337,10 +5484,6 @@ Number of iSCSI operations per second
| ZAPI | `perf-object-get-instances system:node` | `iscsi_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/system_node.yaml |
-### node_labels
-
-
-
### node_memory
Total memory in megabytes (MB)
@@ -7840,6 +7983,15 @@ Number of NFS write operations per second to the volume. node_volume_nfs_write_o
| ZAPI | `perf-object-get-instances volume` | `nfs_write_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
+### node_volume_other_data
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on. node_volume_other_data is [volume_other_data](#volume_other_data) aggregated by `node`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
### node_volume_other_latency
Average latency in microseconds for the WAFL filesystem to process other operations to the volume; not including request processing or network communication time. node_volume_other_latency is [volume_other_latency](#volume_other_latency) aggregated by `node`.
@@ -7847,6 +7999,7 @@ Average latency in microseconds for the WAFL filesystem to process other operati
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `other_latency`
Unit: microsec
Type: average
Base: total_other_ops | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `other_latency`
Unit: microsec
Type: average
Base: other_ops | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -7857,6 +8010,7 @@ Number of other operations per second to the volume. node_volume_other_ops is [v
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `total_other_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `other_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -7867,6 +8021,7 @@ Bytes read per second. node_volume_read_data is [volume_read_data](#volume_read_
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `bytes_read`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `read_data`
Unit: b_per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -7877,6 +8032,7 @@ Average latency in microseconds for the WAFL filesystem to process read request
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `read_latency`
Unit: microsec
Type: average
Base: total_read_ops | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `read_latency`
Unit: microsec
Type: average
Base: read_ops | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -7887,6 +8043,7 @@ Number of read operations per second from the volume. node_volume_read_ops is [v
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `total_read_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `read_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -7896,10 +8053,20 @@ This metric represents the total amount of data that has been read from and writ
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| REST | `NA` | `Harvest generated`
Unit:
Type:
Base: | conf/restperf/9.12.0/volume.yaml |
| ZAPI | `NA` | `Harvest generated`
Unit:
Type:
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
+### node_volume_total_latency
+
+Performance metric aggregated over all types of I/O operations. node_volume_total_latency is [volume_total_latency](#volume_total_latency) aggregated by `node`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
### node_volume_total_ops
Number of operations per second serviced by the volume. node_volume_total_ops is [volume_total_ops](#volume_total_ops) aggregated by `node`.
@@ -7907,6 +8074,7 @@ Number of operations per second serviced by the volume. node_volume_total_ops is
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -7917,6 +8085,7 @@ Bytes written per second. node_volume_write_data is [volume_write_data](#volume_
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `bytes_written`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `write_data`
Unit: b_per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -7927,6 +8096,7 @@ Average latency in microseconds for the WAFL filesystem to process write request
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `write_latency`
Unit: microsec
Type: average
Base: total_write_ops | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `write_latency`
Unit: microsec
Type: average
Base: write_ops | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -7937,13 +8107,10 @@ Number of write operations per second to the volume. node_volume_write_ops is [v
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `total_write_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `write_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
-### ntpserver_labels
-
-
-
### nvme_lif_avg_latency
Average latency for NVMF operations
@@ -8264,10 +8431,6 @@ Number of write operations
| ZAPI | `perf-object-get-instances nvmf_tcp_port` | `write_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/nvmf_tcp_port.yaml |
-### ontaps3_labels
-
-
-
### ontaps3_logical_used_size
Specifies the bucket logical used size up to this point. This field cannot be specified using a POST or PATCH method.
@@ -8286,10 +8449,6 @@ Specifies the bucket logical used size up to this point. This field cannot be sp
| REST | `api/private/cli/vserver/object-store-server/bucket` | `object_count` | conf/rest/9.7.0/ontap_s3.yaml |
-### ontaps3_policy_labels
-
-
-
### ontaps3_size
Specifies the bucket size in bytes; ranges from 190MB to 62PB.
@@ -9961,10 +10120,6 @@ Specifies the size to be used to calculate expected IOPS per TB.
| ZAPI | `NA` | `Harvest generated` | conf/zapi/cdot/9.8.0/qos_policy_adaptive.yaml |
-### qos_policy_adaptive_labels
-
-
-
### qos_policy_adaptive_peak_iops
Specifies the maximum possible IOPS per TB allocated based on the storage object allocated size or the storage object used size.
@@ -9975,10 +10130,6 @@ Specifies the maximum possible IOPS per TB allocated based on the storage object
| ZAPI | `NA` | `Harvest generated` | conf/zapi/cdot/9.8.0/qos_policy_adaptive.yaml |
-### qos_policy_fixed_labels
-
-
-
### qos_policy_fixed_max_throughput_iops
Maximum throughput defined by this policy. It is specified in terms of IOPS. 0 means no maximum throughput is enforced.
@@ -10089,10 +10240,6 @@ This is the total amount of data read/written per second from/to the filer by th
| ZAPI | `perf-object-get-instances workload_volume` | `total_data`
Unit: b_per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/workload_volume.yaml |
-### qos_workload_labels
-
-
-
### qos_workload_max_throughput_iops
Maximum throughput IOPs allowed for the workload.
@@ -10172,10 +10319,6 @@ Number of internal operations generated by activites such as snapmirror and back
| ZAPI | `perf-object-get-instances qtree` | `internal_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/qtree.yaml |
-### qtree_labels
-
-
-
### qtree_nfs_ops
Number of NFS operations per second to the qtree
@@ -10186,6 +10329,51 @@ Number of NFS operations per second to the qtree
| ZAPI | `perf-object-get-instances qtree` | `nfs_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/qtree.yaml |
+### qtree_other_data
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/qtrees` | `statistics.throughput_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/qtree.yaml |
+
+
+### qtree_other_ops
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/qtrees` | `statistics.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/qtree.yaml |
+
+
+### qtree_read_data
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/qtrees` | `statistics.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/qtree.yaml |
+
+
+### qtree_read_ops
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/qtrees` | `statistics.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/qtree.yaml |
+
+
+### qtree_total_data
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/qtrees` | `statistics.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/qtree.yaml |
+
+
### qtree_total_ops
Summation of NFS ops, CIFS ops, CSS ops and internal ops
@@ -10193,9 +10381,28 @@ Summation of NFS ops, CIFS ops, CSS ops and internal ops
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/qtree` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/qtree.yaml |
+| KeyPerf | `api/storage/qtrees` | `statistics.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/qtree.yaml |
| ZAPI | `perf-object-get-instances qtree` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/qtree.yaml |
+### qtree_write_data
+
+Peformance metric for write I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/qtrees` | `statistics.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/qtree.yaml |
+
+
+### qtree_write_ops
+
+Peformance metric for write I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/qtrees` | `statistics.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/qtree.yaml |
+
+
### quota_disk_limit
Maximum amount of disk space, in kilobytes, allowed for the quota target (hard disk space limit). The value is -1 if the limit is unlimited.
@@ -10285,10 +10492,6 @@ Current number of files used expressed as a percentage of soft file limit.
| ZAPI | `quota-report-iter` | `files-used-pct-soft-file-limit` | conf/zapi/cdot/9.8.0/qtree.yaml |
-### quota_labels
-
-
-
### quota_soft_disk_limit
soft disk space limit, in kilobytes, for the quota target. The value is -1 if the limit is unlimited.
@@ -10543,14 +10746,6 @@ The number of restarts after a rewind because of QoS limiting.
| ZAPI | `perf-object-get-instances rw_ctx` | `qos_rewinds`
Unit: none
Type: delta
Base: | conf/zapiperf/cdot/9.8.0/rwctx.yaml |
-### security_account_labels
-
-
-
-### security_audit_destination_labels
-
-
-
### security_audit_destination_port
The destination port used to forward the message.
@@ -10570,22 +10765,6 @@ The destination port used to forward the message.
| ZAPI | `security-certificate-get-iter` | `certificate-info.expiration-date` | conf/zapi/cdot/9.8.0/security_certificate.yaml |
-### security_certificate_labels
-
-
-
-### security_labels
-
-
-
-### security_login_labels
-
-
-
-### security_ssh_labels
-
-
-
### security_ssh_max_instances
Maximum possible simultaneous connections.
@@ -10655,10 +10834,6 @@ Fan Operational Status.
| ZAPI | `NA` | `Harvest generated`
Unit:
Type:
Base: | conf/zapiperf/cdot/9.8.0/disk.yaml |
-### shelf_labels
-
-
-
### shelf_max_fan_speed
Maximum fan speed for shelf in rpm.
@@ -11079,10 +11254,6 @@ The number of successful SnapMirror break operations for the relationship
| ZAPI | `snapmirror-get-iter` | `snapmirror-info.break-successful-count` | conf/zapi/cdot/9.8.0/snapmirror.yaml |
-### snapmirror_labels
-
-
-
### snapmirror_lag_time
Amount of time since the last snapmirror transfer in seconds
@@ -11193,10 +11364,6 @@ Number of Successful Updates
| ZAPI | `snapmirror-get-iter` | `snapmirror-info.update-successful-count` | conf/zapi/cdot/9.8.0/snapmirror.yaml |
-### snapshot_policy_labels
-
-
-
### snapshot_policy_total_schedules
Total Number of Schedules in this Policy
@@ -11207,14 +11374,6 @@ Total Number of Schedules in this Policy
| ZAPI | `snapshot-policy-get-iter` | `snapshot-policy-info.total-schedules` | conf/zapi/cdot/9.8.0/snapshotpolicy.yaml |
-### support_auto_update_labels
-
-
-
-### support_labels
-
-
-
### svm_cifs_connections
Number of connections
@@ -11275,6 +11434,33 @@ Total number of CIFS operations
| ZAPI | `perf-object-get-instances cifs:vserver` | `cifs_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/cifs_vserver.yaml |
+### svm_cifs_other_latency
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/cifs/services` | `statistics.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
+
+
+### svm_cifs_other_ops
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/cifs/services` | `statistics.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
+
+
+### svm_cifs_read_data
+
+Performance metric for read I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/cifs/services` | `statistics.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
+
+
### svm_cifs_read_latency
Average latency for CIFS read operations
@@ -11282,6 +11468,7 @@ Average latency for CIFS read operations
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_cifs` | `average_read_latency`
Unit: microsec
Type: average
Base: total_read_ops | conf/restperf/9.12.0/cifs_vserver.yaml |
+| KeyPerf | `api/protocols/cifs/services` | `statistics.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
| ZAPI | `perf-object-get-instances cifs:vserver` | `cifs_read_latency`
Unit: microsec
Type: average
Base: cifs_read_ops | conf/zapiperf/cdot/9.8.0/cifs_vserver.yaml |
@@ -11292,6 +11479,7 @@ Total number of CIFS read operations
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_cifs` | `total_read_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/cifs_vserver.yaml |
+| KeyPerf | `api/protocols/cifs/services` | `statistics.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
| ZAPI | `perf-object-get-instances cifs:vserver` | `cifs_read_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/cifs_vserver.yaml |
@@ -11305,6 +11493,33 @@ Number of signed SMB and SMB2 sessions.
| ZAPI | `perf-object-get-instances cifs:vserver` | `signed_sessions`
Unit: none
Type: raw
Base: | conf/zapiperf/cdot/9.8.0/cifs_vserver.yaml |
+### svm_cifs_total_latency
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/cifs/services` | `statistics.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
+
+
+### svm_cifs_total_ops
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/cifs/services` | `statistics.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
+
+
+### svm_cifs_write_data
+
+Peformance metric for write I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/cifs/services` | `statistics.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
+
+
### svm_cifs_write_latency
Average latency for CIFS write operations
@@ -11312,6 +11527,7 @@ Average latency for CIFS write operations
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_cifs` | `average_write_latency`
Unit: microsec
Type: average
Base: total_write_ops | conf/restperf/9.12.0/cifs_vserver.yaml |
+| KeyPerf | `api/protocols/cifs/services` | `statistics.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
| ZAPI | `perf-object-get-instances cifs:vserver` | `cifs_write_latency`
Unit: microsec
Type: average
Base: cifs_write_ops | conf/zapiperf/cdot/9.8.0/cifs_vserver.yaml |
@@ -11322,13 +11538,10 @@ Total number of CIFS write operations
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_cifs` | `total_write_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/cifs_vserver.yaml |
+| KeyPerf | `api/protocols/cifs/services` | `statistics.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/cifs_vserver.yaml |
| ZAPI | `perf-object-get-instances cifs:vserver` | `cifs_write_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/cifs_vserver.yaml |
-### svm_labels
-
-
-
### svm_new_status
This metric indicates a value of 1 if the SVM state is online (indicating the SVM is operational) and a value of 0 for any other state.
@@ -11866,8 +12079,11 @@ Average latency of NFSv3 requests. This counter keeps track of the average respo
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_nfs_v3` | `latency`
Unit: microsec
Type: average
Base: total_ops | conf/restperf/9.12.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v4` | `latency`
Unit: microsec
Type: average
Base: total_ops | conf/restperf/9.12.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v41` | `latency`
Unit: microsec
Type: average
Base: total_ops | conf/restperf/9.12.0/nfsv4_1.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v42` | `latency`
Unit: microsec
Type: average
Base: total_ops | conf/restperf/9.12.0/nfsv4_2.yaml |
| ZAPI | `perf-object-get-instances nfsv3` | `latency`
Unit: microsec
Type: average,no-zero-values
Base: total_ops | conf/zapiperf/cdot/9.8.0/nfsv3.yaml |
| ZAPI | `perf-object-get-instances nfsv4` | `latency`
Unit: microsec
Type: average,no-zero-values
Base: total_ops | conf/zapiperf/cdot/9.8.0/nfsv4.yaml |
@@ -12334,8 +12550,11 @@ Total number of NFSv3 procedure requests per second.
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_nfs_v3` | `ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v4` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v41` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4_1.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v42` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4_2.yaml |
| ZAPI | `perf-object-get-instances nfsv3` | `nfsv3_ops`
Unit: per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/nfsv3.yaml |
| ZAPI | `perf-object-get-instances nfsv4` | `total_ops`
Unit: per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/nfsv4.yaml |
@@ -12343,6 +12562,28 @@ Total number of NFSv3 procedure requests per second.
| ZAPI | `perf-object-get-instances nfsv4_2` | `total_ops`
Unit: per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.11.0/nfsv4_2.yaml |
+### svm_nfs_other_latency
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
+
+
+### svm_nfs_other_ops
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
+
+
### svm_nfs_pathconf_avg_latency
Average latency of PathConf procedure requests. The counter keeps track of the average response time of PathConf requests.
@@ -12454,8 +12695,11 @@ Average latency of Read procedure requests. The counter keeps track of the avera
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_nfs_v3` | `read.average_latency`
Unit: microsec
Type: average
Base: read.total | conf/restperf/9.12.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v4` | `read.average_latency`
Unit: microsec
Type: average
Base: read.total | conf/restperf/9.12.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v41` | `read.average_latency`
Unit: microsec
Type: average
Base: read.total | conf/restperf/9.12.0/nfsv4_1.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v42` | `read.average_latency`
Unit: microsec
Type: average
Base: read.total | conf/restperf/9.12.0/nfsv4_2.yaml |
| ZAPI | `perf-object-get-instances nfsv3` | `read_avg_latency`
Unit: microsec
Type: average,no-zero-values
Base: read_total | conf/zapiperf/cdot/9.8.0/nfsv3.yaml |
| ZAPI | `perf-object-get-instances nfsv4` | `read_avg_latency`
Unit: microsec
Type: average,no-zero-values
Base: read_total | conf/zapiperf/cdot/9.8.0/nfsv4.yaml |
@@ -12470,6 +12714,9 @@ Total observed NFSv3 read operations per second.
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_nfs_v3` | `read_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
| ZAPI | `perf-object-get-instances nfsv3` | `nfsv3_read_ops`
Unit: per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/nfsv3.yaml |
@@ -12500,8 +12747,11 @@ Rate of NFSv3 read data transfers per second.
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_nfs_v3` | `read_throughput`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v4` | `total.read_throughput`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v41` | `total.read_throughput`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4_1.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v42` | `total.read_throughput`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4_2.yaml |
| ZAPI | `perf-object-get-instances nfsv3` | `nfsv3_read_throughput`
Unit: b_per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/nfsv3.yaml |
| ZAPI | `perf-object-get-instances nfsv4` | `nfs4_read_throughput`
Unit: b_per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/nfsv4.yaml |
@@ -13041,6 +13291,17 @@ Rate of NFSv3 data transfers per second.
| ZAPI | `perf-object-get-instances nfsv4_2` | `nfs42_throughput`
Unit: b_per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.11.0/nfsv4_2.yaml |
+### svm_nfs_total_throughput
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
+
+
### svm_nfs_verify_avg_latency
Average latency of VERIFY procedures
@@ -13100,8 +13361,11 @@ Average latency of Write procedure requests. The counter keeps track of the aver
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_nfs_v3` | `write.average_latency`
Unit: microsec
Type: average
Base: write.total | conf/restperf/9.12.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v4` | `write.average_latency`
Unit: microsec
Type: average
Base: write.total | conf/restperf/9.12.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v41` | `write.average_latency`
Unit: microsec
Type: average
Base: write.total | conf/restperf/9.12.0/nfsv4_1.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v42` | `write.average_latency`
Unit: microsec
Type: average
Base: write.total | conf/restperf/9.12.0/nfsv4_2.yaml |
| ZAPI | `perf-object-get-instances nfsv3` | `write_avg_latency`
Unit: microsec
Type: average,no-zero-values
Base: write_total | conf/zapiperf/cdot/9.8.0/nfsv3.yaml |
| ZAPI | `perf-object-get-instances nfsv4` | `write_avg_latency`
Unit: microsec
Type: average,no-zero-values
Base: write_total | conf/zapiperf/cdot/9.8.0/nfsv4.yaml |
@@ -13116,6 +13380,9 @@ Total observed NFSv3 write operations per second.
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_nfs_v3` | `write_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
| ZAPI | `perf-object-get-instances nfsv3` | `nfsv3_write_ops`
Unit: per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/nfsv3.yaml |
@@ -13126,8 +13393,11 @@ Rate of NFSv3 write data transfers per second.
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/svm_nfs_v3` | `write_throughput`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv3.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v3.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv3.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v4` | `total.write_throughput`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v4.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v41` | `total.throughput`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4_1.yaml |
+| KeyPerf | `api/protocols/nfs/services` | `statistics.v41.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/nfsv4_1.yaml |
| REST | `api/cluster/counter/tables/svm_nfs_v42` | `total.throughput`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/nfsv4_2.yaml |
| ZAPI | `perf-object-get-instances nfsv3` | `nfsv3_write_throughput`
Unit: b_per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/nfsv3.yaml |
| ZAPI | `perf-object-get-instances nfsv4` | `nfs4_write_throughput`
Unit: b_per_sec
Type: rate,no-zero-values
Base: | conf/zapiperf/cdot/9.8.0/nfsv4.yaml |
@@ -14531,6 +14801,114 @@ Number of write operations per second to the volume
| ZAPI | `perf-object-get-instances volume:vserver` | `write_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume_svm.yaml |
+### svm_volume_other_data
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on. svm_volume_other_data is [volume_other_data](#volume_other_data) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_other_latency
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on. svm_volume_other_latency is [volume_other_latency](#volume_other_latency) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_other_ops
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on. svm_volume_other_ops is [volume_other_ops](#volume_other_ops) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_read_data
+
+Performance metric for read I/O operations. svm_volume_read_data is [volume_read_data](#volume_read_data) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_read_latency
+
+Performance metric for read I/O operations. svm_volume_read_latency is [volume_read_latency](#volume_read_latency) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_read_ops
+
+Performance metric for read I/O operations. svm_volume_read_ops is [volume_read_ops](#volume_read_ops) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_total_data
+
+Performance metric aggregated over all types of I/O operations. svm_volume_total_data is [volume_total_data](#volume_total_data) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_total_latency
+
+Performance metric aggregated over all types of I/O operations. svm_volume_total_latency is [volume_total_latency](#volume_total_latency) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_total_ops
+
+Performance metric aggregated over all types of I/O operations. svm_volume_total_ops is [volume_total_ops](#volume_total_ops) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_write_data
+
+Peformance metric for write I/O operations. svm_volume_write_data is [volume_write_data](#volume_write_data) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_write_latency
+
+Peformance metric for write I/O operations. svm_volume_write_latency is [volume_write_latency](#volume_write_latency) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
+### svm_volume_write_ops
+
+Peformance metric for write I/O operations. svm_volume_write_ops is [volume_write_ops](#volume_write_ops) aggregated by `svm`.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
### svm_vscan_connections_active
Total number of current active connections
@@ -14834,10 +15212,6 @@ volume_inode_files_used / volume_inode_total
| ZAPI | `volume-get-iter` | `inode_files_used, inode_files_total` | conf/zapi/cdot/9.8.0/volume.yaml |
-### volume_labels
-
-
-
### volume_new_status
This metric indicates a value of 1 if the volume state is online (indicating the volume is operational) and a value of 0 for any other state.
@@ -15036,6 +15410,15 @@ Number of NFS write operations per second to the volume
| REST | `api/private/cli/volume/efficiency/stat` | `num_compress_fail` | conf/rest/9.14.0/volume.yaml |
+### volume_other_data
+
+Performance metric for other I/O operations. Other I/O operations can be metadata operations, such as directory lookups and so on.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
### volume_other_latency
Average latency in microseconds for the WAFL filesystem to process other operations to the volume; not including request processing or network communication time
@@ -15043,6 +15426,7 @@ Average latency in microseconds for the WAFL filesystem to process other operati
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `other_latency`
Unit: microsec
Type: average
Base: total_other_ops | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `other_latency`
Unit: microsec
Type: average
Base: other_ops | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -15053,6 +15437,7 @@ Number of other operations per second to the volume
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `total_other_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.other`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `other_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -15113,6 +15498,7 @@ Bytes read per second
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `bytes_read`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `read_data`
Unit: b_per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -15123,6 +15509,7 @@ Average latency in microseconds for the WAFL filesystem to process read request
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `read_latency`
Unit: microsec
Type: average
Base: total_read_ops | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `read_latency`
Unit: microsec
Type: average
Base: read_ops | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -15133,6 +15520,7 @@ Number of read operations per second from the volume
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `total_read_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.read`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `read_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -15469,9 +15857,19 @@ This metric represents the total amount of data that has been read from and writ
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `bytes_read, bytes_written`
Unit:
Type:
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `volume` | `read_data, write_data`
Unit:
Type:
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
+### volume_total_latency
+
+Performance metric aggregated over all types of I/O operations.
+
+| API | Endpoint | Metric | Template |
+|--------|----------|--------|---------|
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
+
+
### volume_total_ops
Number of operations per second serviced by the volume
@@ -15479,6 +15877,7 @@ Number of operations per second serviced by the volume
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.total`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `total_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -15489,6 +15888,7 @@ Bytes written per second
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `bytes_written`
Unit: b_per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.throughput_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `write_data`
Unit: b_per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -15499,6 +15899,7 @@ Average latency in microseconds for the WAFL filesystem to process write request
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `write_latency`
Unit: microsec
Type: average
Base: total_write_ops | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.latency_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `write_latency`
Unit: microsec
Type: average
Base: write_ops | conf/zapiperf/cdot/9.8.0/volume.yaml |
@@ -15509,6 +15910,7 @@ Number of write operations per second to the volume
| API | Endpoint | Metric | Template |
|--------|----------|--------|---------|
| REST | `api/cluster/counter/tables/volume` | `total_write_ops`
Unit: per_sec
Type: rate
Base: | conf/restperf/9.12.0/volume.yaml |
+| KeyPerf | `api/storage/volumes` | `statistics.iops_raw.write`
Unit:
Type:
Base: | conf/keyperf/9.15.0/volume.yaml |
| ZAPI | `perf-object-get-instances volume` | `write_ops`
Unit: per_sec
Type: rate
Base: | conf/zapiperf/cdot/9.8.0/volume.yaml |
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 9026255a9..61ab9a79f 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -353,7 +353,7 @@ You will be prompted to save your API key (token) for later use. Press `n` to no
After a few seconds, all the dashboards will be imported into Grafana.
-### 9. Verify Dashboards in Grafana
+### 11. Verify Dashboards in Grafana
After adding the Prometheus datasource, you can verify that your dashboards are correctly displaying data. Follow these steps:
diff --git a/go.mod b/go.mod
index 357b571b9..59d186d0a 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ require (
github.com/go-openapi/spec v0.21.0
github.com/google/go-cmp v0.6.0
github.com/rivo/uniseg v0.4.7
- github.com/shirou/gopsutil/v4 v4.24.9
+ github.com/shirou/gopsutil/v4 v4.24.10
github.com/spf13/cobra v1.8.1
github.com/tidwall/gjson v1.18.0
github.com/zekroTJA/timedmap/v2 v2.0.0
@@ -18,7 +18,7 @@ require (
)
require (
- github.com/ebitengine/purego v0.8.0 // indirect
+ github.com/ebitengine/purego v0.8.1 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
diff --git a/go.sum b/go.sum
index d48be9533..90eb82a10 100644
--- a/go.sum
+++ b/go.sum
@@ -3,6 +3,8 @@ 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/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE=
github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
+github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
+github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
@@ -41,6 +43,8 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI=
github.com/shirou/gopsutil/v4 v4.24.9/go.mod h1:3fkaHNeYsUFCGZ8+9vZVWtbyM1k2eRnlL+bWO8Bxa/Q=
+github.com/shirou/gopsutil/v4 v4.24.10 h1:7VOzPtfw/5YDU+jLEoBwXwxJbQetULywoSV4RYY7HkM=
+github.com/shirou/gopsutil/v4 v4.24.10/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
diff --git a/grafana/dashboards/cmode-details/volumeBySVM.json b/grafana/dashboards/cmode-details/volumeBySVM.json
index d1fd5d19a..88c84851b 100644
--- a/grafana/dashboards/cmode-details/volumeBySVM.json
+++ b/grafana/dashboards/cmode-details/volumeBySVM.json
@@ -446,7 +446,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -456,7 +456,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -469,7 +469,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -479,7 +479,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode-details/volumeDeepDive.json b/grafana/dashboards/cmode-details/volumeDeepDive.json
index b3821b2f0..36d4fa128 100644
--- a/grafana/dashboards/cmode-details/volumeDeepDive.json
+++ b/grafana/dashboards/cmode-details/volumeDeepDive.json
@@ -3687,7 +3687,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -3697,7 +3697,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -3713,7 +3713,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -3723,7 +3723,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/aggregate.json b/grafana/dashboards/cmode/aggregate.json
index ecc0a2f50..b5d7c9c5e 100644
--- a/grafana/dashboards/cmode/aggregate.json
+++ b/grafana/dashboards/cmode/aggregate.json
@@ -6601,7 +6601,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(aggr_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -6611,7 +6611,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(aggr_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/data_protection_snapshot.json b/grafana/dashboards/cmode/data_protection_snapshot.json
index 70930d053..b05b5c6e3 100644
--- a/grafana/dashboards/cmode/data_protection_snapshot.json
+++ b/grafana/dashboards/cmode/data_protection_snapshot.json
@@ -1603,7 +1603,7 @@
"value": "DC-01"
},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"},datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"},datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -1613,7 +1613,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"},datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"},datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -1629,7 +1629,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -1639,7 +1639,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/datacenter.json b/grafana/dashboards/cmode/datacenter.json
index fae108468..57aca3ccb 100644
--- a/grafana/dashboards/cmode/datacenter.json
+++ b/grafana/dashboards/cmode/datacenter.json
@@ -3402,7 +3402,7 @@
"refId": "A"
}
],
- "title": "Data Reduction with Snapshots &FlexClones",
+ "title": "Data Reduction with Snapshots & FlexClones",
"type": "stat"
},
{
diff --git a/grafana/dashboards/cmode/disk.json b/grafana/dashboards/cmode/disk.json
index 3442fe93a..b1673ade9 100644
--- a/grafana/dashboards/cmode/disk.json
+++ b/grafana/dashboards/cmode/disk.json
@@ -3012,7 +3012,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(disk_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -3022,7 +3022,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(disk_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"refId": "Prometheus-Cluster-Variable-Query"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/external_service_op.json b/grafana/dashboards/cmode/external_service_op.json
index 76714920c..84ec56821 100644
--- a/grafana/dashboards/cmode/external_service_op.json
+++ b/grafana/dashboards/cmode/external_service_op.json
@@ -823,7 +823,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(external_service_op_request_latency{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -833,7 +833,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(external_service_op_request_latency{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -849,7 +849,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(external_service_op_request_latency{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -859,7 +859,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(external_service_op_request_latency{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/flexgroup.json b/grafana/dashboards/cmode/flexgroup.json
index b7e02855b..6b24d1240 100644
--- a/grafana/dashboards/cmode/flexgroup.json
+++ b/grafana/dashboards/cmode/flexgroup.json
@@ -2871,7 +2871,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -2881,7 +2881,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -2897,7 +2897,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -2907,7 +2907,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/fsa.json b/grafana/dashboards/cmode/fsa.json
index 0870fc7d3..b90ef1de5 100644
--- a/grafana/dashboards/cmode/fsa.json
+++ b/grafana/dashboards/cmode/fsa.json
@@ -1523,7 +1523,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -1533,7 +1533,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -1549,7 +1549,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -1559,7 +1559,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/headroom.json b/grafana/dashboards/cmode/headroom.json
index cd51ccebb..3a2c35127 100644
--- a/grafana/dashboards/cmode/headroom.json
+++ b/grafana/dashboards/cmode/headroom.json
@@ -2460,7 +2460,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -2470,7 +2470,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -2483,7 +2483,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -2493,7 +2493,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/health.json b/grafana/dashboards/cmode/health.json
index c5b8f8ddf..e6466a135 100644
--- a/grafana/dashboards/cmode/health.json
+++ b/grafana/dashboards/cmode/health.json
@@ -71,7 +71,7 @@
"gnetId": null,
"graphTooltip": 1,
"id": null,
- "iteration": 1718007936255,
+ "iteration": 1730271272394,
"links": [
{
"asDropdown": true,
@@ -106,14 +106,14 @@
{
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
- "h": 5,
+ "h": 3,
"w": 24,
"x": 0,
"y": 1
},
"id": 241,
"options": {
- "content": "This dashboard requires ONTAP 9.6+ and the REST collector. Two actions are required to use this dashboard:\n1. Enable the REST collector in your harvest.yml config\n2. Enable the EMS collector in your harvest.yml config for EMS events\n\nHarvest only detects Health and EMS events that are generated after the two collectors are enabled. By default, Harvest collects a focused set of [EMS events](https://github.com/NetApp/harvest/blob/main/conf/ems/9.6.0/ems.yaml) and this dashboard only shows the emergency level events.",
+ "content": "This dashboard is compatible with ONTAP 9.6+ and requires the REST collector. To use this dashboard, please follow the step below:\n\n1. **Enable the REST Collector**: Update your `harvest.yml` configuration file to enable the REST collector.",
"mode": "markdown"
},
"pluginVersion": "8.1.8",
@@ -126,7 +126,7 @@
"h": 1,
"w": 24,
"x": 0,
- "y": 6
+ "y": 4
},
"id": 225,
"panels": [],
@@ -191,7 +191,7 @@
"h": 6,
"w": 8,
"x": 0,
- "y": 7
+ "y": 5
},
"id": 277,
"options": {
@@ -282,7 +282,7 @@
"h": 6,
"w": 8,
"x": 8,
- "y": 7
+ "y": 5
},
"id": 278,
"options": {
@@ -358,7 +358,7 @@
"h": 6,
"w": 8,
"x": 16,
- "y": 7
+ "y": 5
},
"id": 270,
"options": {
@@ -380,14 +380,14 @@
"targets": [
{
"exemplar": false,
- "expr": "(count(last_over_time(ems_events{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",severity=\"emergency\"}[$__range]) == 1) or vector(0))",
+ "expr": "sum(health_ems_alerts{datacenter=~\"$Datacenter\", cluster=~\"$Cluster\", severity=\"emergency\"}) or vector(0)",
"instant": true,
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
- "title": "Total Active Emergency EMS",
+ "title": "Active Emergency EMS Alerts (Last 24 Hours)",
"transformations": [],
"type": "stat"
},
@@ -416,7 +416,7 @@
"h": 16,
"w": 8,
"x": 0,
- "y": 13
+ "y": 11
},
"id": 268,
"options": {
@@ -567,7 +567,7 @@
"h": 16,
"w": 8,
"x": 8,
- "y": 13
+ "y": 11
},
"id": 269,
"options": {
@@ -721,17 +721,23 @@
"h": 16,
"w": 8,
"x": 16,
- "y": 13
+ "y": 11
},
"id": 272,
"options": {
- "showHeader": true
+ "showHeader": true,
+ "sortBy": [
+ {
+ "desc": false,
+ "displayName": "EMS"
+ }
+ ]
},
"pluginVersion": "8.1.8",
"targets": [
{
"exemplar": false,
- "expr": "count(last_over_time(ems_events{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",severity=\"emergency\"}[$__range]) == 1) by (message)",
+ "expr": "sum(health_ems_alerts{datacenter=~\"$Datacenter\", cluster=~\"$Cluster\", severity=\"emergency\"}) by (message)",
"format": "table",
"instant": true,
"interval": "",
@@ -739,7 +745,7 @@
"refId": "A"
}
],
- "title": "Active Emergency EMS",
+ "title": "Active Emergency EMS Alerts (Last 24 Hours)",
"transformations": [
{
"id": "organize",
@@ -759,14 +765,14 @@
},
{
"collapsed": true,
- "datasource": "${DS_PROMETHEUS}",
+ "datasource": null,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
- "y": 29
+ "y": 27
},
- "id": 251,
+ "id": 283,
"panels": [
{
"datasource": "${DS_PROMETHEUS}",
@@ -815,6 +821,28 @@
}
]
},
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "Takeover Possible"
+ },
+ "properties": [
+ {
+ "id": "mappings",
+ "value": [
+ {
+ "options": {
+ "false": {
+ "index": 0,
+ "text": "No"
+ }
+ },
+ "type": "value"
+ }
+ ]
+ }
+ ]
+ },
{
"matcher": {
"id": "byName",
@@ -880,6 +908,28 @@
]
}
]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "partner"
+ },
+ "properties": [
+ {
+ "id": "displayName",
+ "value": "Partner Node"
+ },
+ {
+ "id": "links",
+ "value": [
+ {
+ "targetBlank": true,
+ "title": "",
+ "url": "/d/cdot-node/ontap-node?orgId=1&${Datacenter:queryparam}&${Cluster:queryparam}&${__url_time_range}&var-Node=${__value.raw}"
+ }
+ ]
+ }
+ ]
}
]
},
@@ -887,9 +937,9 @@
"h": 6,
"w": 24,
"x": 0,
- "y": 28
+ "y": 29
},
- "id": 253,
+ "id": 281,
"options": {
"showHeader": true
},
@@ -897,7 +947,7 @@
"targets": [
{
"exemplar": false,
- "expr": "node_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} * on(cluster,node,datacenter) group_left(severity) (health_node_alerts{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} == 1)",
+ "expr": "node_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} * on(cluster,node,datacenter) group_left(severity,takeover_possible,partner,partner_state,state_description) (health_ha_alerts{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} == 1)",
"format": "table",
"instant": true,
"interval": "",
@@ -905,7 +955,7 @@
"refId": "A"
}
],
- "title": "Node Issues",
+ "title": "HA Issues",
"transformations": [
{
"id": "organize",
@@ -913,26 +963,47 @@
"excludeByName": {
"Time": true,
"Value": true,
+ "cpu_firmware_release": true,
"instance": true,
- "job": true
+ "job": true,
+ "max_aggr_size": true,
+ "max_vol_num": true,
+ "max_vol_size": true
},
"indexByName": {
"Time": 0,
- "Value": 10,
+ "Value": 14,
"cluster": 2,
+ "cpu_firmware_release": 15,
"datacenter": 1,
- "healthy": 4,
- "instance": 8,
- "job": 9,
+ "healthy": 5,
+ "instance": 12,
+ "job": 13,
+ "location": 16,
+ "max_aggr_size": 17,
+ "max_vol_num": 18,
+ "max_vol_size": 19,
+ "model": 20,
"node": 3,
- "severity": 6,
- "state": 5,
- "version": 7
+ "partner": 7,
+ "partner_state": 8,
+ "serial": 21,
+ "severity": 10,
+ "state": 6,
+ "state_description": 9,
+ "takeover_possible": 4,
+ "vendor": 22,
+ "version": 11,
+ "warnings": 23
},
"renameByName": {
+ "cpu_firmware_release": "",
"healthy": "Healthy",
+ "partner_state": "Partner State",
"severity": "Severity",
"state": "State",
+ "state_description": "State Description",
+ "takeover_possible": "Takeover Possible",
"version": "Version"
}
}
@@ -941,19 +1012,19 @@
"type": "table"
}
],
- "title": "Node",
+ "title": "HA",
"type": "row"
},
{
"collapsed": true,
- "datasource": null,
+ "datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 28
},
- "id": 283,
+ "id": 251,
"panels": [
{
"datasource": "${DS_PROMETHEUS}",
@@ -1002,28 +1073,6 @@
}
]
},
- {
- "matcher": {
- "id": "byName",
- "options": "Takeover Possible"
- },
- "properties": [
- {
- "id": "mappings",
- "value": [
- {
- "options": {
- "false": {
- "index": 0,
- "text": "No"
- }
- },
- "type": "value"
- }
- ]
- }
- ]
- },
{
"matcher": {
"id": "byName",
@@ -1089,28 +1138,6 @@
]
}
]
- },
- {
- "matcher": {
- "id": "byName",
- "options": "partner"
- },
- "properties": [
- {
- "id": "displayName",
- "value": "Partner Node"
- },
- {
- "id": "links",
- "value": [
- {
- "targetBlank": true,
- "title": "",
- "url": "/d/cdot-node/ontap-node?orgId=1&${Datacenter:queryparam}&${Cluster:queryparam}&${__url_time_range}&var-Node=${__value.raw}"
- }
- ]
- }
- ]
}
]
},
@@ -1118,9 +1145,9 @@
"h": 6,
"w": 24,
"x": 0,
- "y": 29
+ "y": 28
},
- "id": 281,
+ "id": 253,
"options": {
"showHeader": true
},
@@ -1128,7 +1155,7 @@
"targets": [
{
"exemplar": false,
- "expr": "node_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} * on(cluster,node,datacenter) group_left(severity,takeover_possible,partner,partner_state,state_description) (health_ha_alerts{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} == 1)",
+ "expr": "node_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} * on(cluster,node,datacenter) group_left(severity) (health_node_alerts{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"} == 1)",
"format": "table",
"instant": true,
"interval": "",
@@ -1136,7 +1163,7 @@
"refId": "A"
}
],
- "title": "HA Issues",
+ "title": "Node Issues",
"transformations": [
{
"id": "organize",
@@ -1144,47 +1171,26 @@
"excludeByName": {
"Time": true,
"Value": true,
- "cpu_firmware_release": true,
"instance": true,
- "job": true,
- "max_aggr_size": true,
- "max_vol_num": true,
- "max_vol_size": true
+ "job": true
},
"indexByName": {
"Time": 0,
- "Value": 14,
+ "Value": 10,
"cluster": 2,
- "cpu_firmware_release": 15,
"datacenter": 1,
- "healthy": 5,
- "instance": 12,
- "job": 13,
- "location": 16,
- "max_aggr_size": 17,
- "max_vol_num": 18,
- "max_vol_size": 19,
- "model": 20,
+ "healthy": 4,
+ "instance": 8,
+ "job": 9,
"node": 3,
- "partner": 7,
- "partner_state": 8,
- "serial": 21,
- "severity": 10,
- "state": 6,
- "state_description": 9,
- "takeover_possible": 4,
- "vendor": 22,
- "version": 11,
- "warnings": 23
+ "severity": 6,
+ "state": 5,
+ "version": 7
},
"renameByName": {
- "cpu_firmware_release": "",
"healthy": "Healthy",
- "partner_state": "Partner State",
"severity": "Severity",
"state": "State",
- "state_description": "State Description",
- "takeover_possible": "Takeover Possible",
"version": "Version"
}
}
@@ -1193,7 +1199,7 @@
"type": "table"
}
],
- "title": "HA",
+ "title": "Node",
"type": "row"
},
{
@@ -4137,7 +4143,7 @@
"h": 8,
"w": 24,
"x": 0,
- "y": 35
+ "y": 37
},
"id": 237,
"options": {
@@ -4147,7 +4153,7 @@
"targets": [
{
"exemplar": false,
- "expr": "last_over_time(ems_events{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",severity=\"emergency\"}[$__range]) == 1",
+ "expr": "sum(health_ems_alerts{datacenter=~\"$Datacenter\", cluster=~\"$Cluster\", severity=\"emergency\"}) by (datacenter,cluster,node,message,severity)",
"format": "table",
"instant": true,
"interval": "",
@@ -4155,13 +4161,20 @@
"refId": "A"
}
],
- "title": "Emergency EMS",
+ "title": "Active Emergency EMS Alerts (Last 24 Hours)",
"transformations": [
{
"id": "filterFieldsByName",
"options": {
"include": {
- "pattern": "/^(datacenter|cluster|message|node|severity)$/"
+ "names": [
+ "cluster",
+ "datacenter",
+ "message",
+ "node",
+ "severity",
+ "Value"
+ ]
}
}
},
@@ -4177,6 +4190,7 @@
"severity": 4
},
"renameByName": {
+ "Value": "Count",
"message": "Message",
"severity": "Severity"
}
@@ -4473,11 +4487,11 @@
"options": [
{
"selected": true,
- "text": "The EMS collector gathers EMS events as defined in your ems.yml file. This panel displays events with emergency severity that occurred within the selected time range.",
- "value": "The EMS collector gathers EMS events as defined in your ems.yml file. This panel displays events with emergency severity that occurred within the selected time range."
+ "text": "This panel displays all emergency EMS alerts active in the past 24 hours.",
+ "value": "This panel displays all emergency EMS alerts active in the past 24 hours."
}
],
- "query": "The EMS collector gathers EMS events as defined in your ems.yml file. This panel displays events with emergency severity that occurred within the selected time range.",
+ "query": "This panel displays all emergency EMS alerts active in the past 24 hours. ",
"skipUrlSync": false,
"type": "textbox"
}
@@ -4503,5 +4517,5 @@
"timezone": "",
"title": "ONTAP: Health",
"uid": "cdot-health",
- "version": 4
+ "version": 5
}
diff --git a/grafana/dashboards/cmode/lun.json b/grafana/dashboards/cmode/lun.json
index 6d06149d3..53f0fae4e 100644
--- a/grafana/dashboards/cmode/lun.json
+++ b/grafana/dashboards/cmode/lun.json
@@ -5111,7 +5111,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(lun_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -5121,7 +5121,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(lun_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/mcc_cluster.json b/grafana/dashboards/cmode/mcc_cluster.json
index 56718d1a5..35eac2043 100644
--- a/grafana/dashboards/cmode/mcc_cluster.json
+++ b/grafana/dashboards/cmode/mcc_cluster.json
@@ -4152,7 +4152,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(aggr_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -4163,7 +4163,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(aggr_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/network.json b/grafana/dashboards/cmode/network.json
index bcfba1693..e39d1c769 100644
--- a/grafana/dashboards/cmode/network.json
+++ b/grafana/dashboards/cmode/network.json
@@ -569,8 +569,11 @@
"defaults": {
"custom": {
"align": "left",
- "displayMode": "auto",
- "filterable": true
+ "cellOptions": {
+ "type": "auto"
+ },
+ "filterable": true,
+ "inspect": false
},
"decimals": 2,
"mappings": [],
@@ -595,13 +598,331 @@
}
]
},
- "unit": "Bps"
+ "unit": "Bps",
+ "unitScale": true
},
"overrides": [
{
"matcher": {
"id": "byName",
- "options": "speed"
+ "options": "MTU"
+ },
+ "properties": [
+ {
+ "id": "unit",
+ "value": "bps"
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "port"
+ },
+ "properties": [
+ {
+ "id": "custom.width",
+ "value": 122
+ },
+ {
+ "id": "displayName",
+ "value": "Port"
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "node"
+ },
+ "properties": [
+ {
+ "id": "displayName",
+ "value": "Node"
+ },
+ {
+ "id": "custom.width",
+ "value": 184
+ },
+ {
+ "id": "links",
+ "value": [
+ {
+ "targetBlank": true,
+ "title": "",
+ "url": "/d/cdot-node/ontap-node?orgId=1&${Datacenter:queryparam}&${Cluster:queryparam}&${__url_time_range}&var-Node=${__value.raw}"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "datacenter"
+ },
+ "properties": [
+ {
+ "id": "displayName",
+ "value": "Datacenter"
+ },
+ {
+ "id": "links",
+ "value": [
+ {
+ "targetBlank": true,
+ "title": "",
+ "url": "/d/cdot-datacenter/ontap-datacenter?orgId=1&${__url_time_range}&var-Datacenter=${__value.raw}"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "cluster"
+ },
+ "properties": [
+ {
+ "id": "displayName",
+ "value": "Cluster"
+ },
+ {
+ "id": "links",
+ "value": [
+ {
+ "targetBlank": true,
+ "title": "",
+ "url": "/d/cdot-cluster/ontap-cluster?orgId=1&${Datacenter:queryparam}&${__url_time_range}&var-Cluster=${__value.raw}"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "Link Speed"
+ },
+ "properties": [
+ {
+ "id": "unit",
+ "value": "bps"
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "Status"
+ },
+ "properties": [
+ {
+ "id": "custom.cellOptions",
+ "value": {
+ "type": "color-background"
+ }
+ },
+ {
+ "id": "mappings",
+ "value": [
+ {
+ "options": {
+ "degraded": {
+ "color": "red",
+ "index": 2,
+ "text": "degraded"
+ },
+ "down": {
+ "color": "red",
+ "index": 1,
+ "text": "down"
+ },
+ "up ": {
+ "color": "green",
+ "index": 0,
+ "text": "up"
+ }
+ },
+ "type": "value"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 11,
+ "w": 24,
+ "x": 0,
+ "y": 2
+ },
+ "id": 59,
+ "interval": "",
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true,
+ "sortBy": [
+ {
+ "desc": false,
+ "displayName": "Status"
+ }
+ ]
+ },
+ "pluginVersion": "8.1.8",
+ "targets": [
+ {
+ "datasource": "${DS_PROMETHEUS}",
+ "editorMode": "code",
+ "expr": "net_port_status{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",node=~\"$Node\",port=~\"$Eth\"}",
+ "format": "table",
+ "hide": false,
+ "instant": true,
+ "interval": "",
+ "legendFormat": "",
+ "refId": "A"
+ },
+ {
+ "datasource": "${DS_PROMETHEUS}",
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "net_port_mtu{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",node=~\"$Node\",port=~\"$Eth\"}",
+ "format": "table",
+ "hide": false,
+ "instant": true,
+ "legendFormat": "__auto",
+ "range": false,
+ "refId": "B"
+ }
+ ],
+ "title": "Ethernet ports",
+ "transformations": [
+ {
+ "id": "filterFieldsByName",
+ "options": {
+ "include": {
+ "names": [
+ "admin_speed",
+ "cluster",
+ "datacenter",
+ "ipspace",
+ "node",
+ "op_speed",
+ "port",
+ "port_type",
+ "role",
+ "status",
+ "Value #B"
+ ]
+ }
+ }
+ },
+ {
+ "id": "merge",
+ "options": {}
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {
+ "Time": true,
+ "Value": false,
+ "__name__": true,
+ "cluster": false,
+ "datacenter": false,
+ "instance": true,
+ "job": true,
+ "speed": false,
+ "state": true
+ },
+ "includeByName": {},
+ "indexByName": {
+ "Value #B": 4,
+ "admin_speed": 7,
+ "cluster": 1,
+ "datacenter": 0,
+ "ipspace": 8,
+ "node": 2,
+ "op_speed": 5,
+ "port": 3,
+ "port_type": 9,
+ "role": 10,
+ "status": 6
+ },
+ "renameByName": {
+ "Value #B": "MTU",
+ "admin_duplex": "",
+ "admin_speed": "Admin Speed",
+ "admin_up": "",
+ "cluster": "",
+ "datacenter": "",
+ "ipspace": "IPspace",
+ "node": "",
+ "op_speed": "Link Speed",
+ "port": "",
+ "port_type": "Port Type",
+ "role": "Role",
+ "status": "Status"
+ }
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": "${DS_PROMETHEUS}",
+ "description": "NIC port details.",
+ "fieldConfig": {
+ "defaults": {
+ "custom": {
+ "align": "left",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "filterable": true,
+ "inspect": false
+ },
+ "decimals": 2,
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "rgb(80, 220, 20)",
+ "value": null
+ },
+ {
+ "color": "light-yellow",
+ "value": 1000000
+ },
+ {
+ "color": "semi-dark-orange",
+ "value": 10000000
+ },
+ {
+ "color": "semi-dark-red",
+ "value": 100000000
+ }
+ ]
+ },
+ "unit": "Bps",
+ "unitScale": true
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "Speed"
},
"properties": [
{
@@ -625,12 +946,15 @@
"value": "percentunit"
},
{
- "id": "custom.displayMode",
- "value": "gradient-gauge"
+ "id": "custom.cellOptions",
+ "value": {
+ "mode": "gradient",
+ "type": "gauge"
+ }
},
{
"id": "displayName",
- "value": "used %"
+ "value": "Used %"
},
{
"id": "noValue",
@@ -720,8 +1044,11 @@
}
},
{
- "id": "custom.displayMode",
- "value": "color-background"
+ "id": "custom.cellOptions",
+ "value": {
+ "mode": "gradient",
+ "type": "color-background"
+ }
}
]
},
@@ -766,7 +1093,7 @@
{
"matcher": {
"id": "byName",
- "options": "type"
+ "options": "Type"
},
"properties": [
{
@@ -783,11 +1110,14 @@
"properties": [
{
"id": "displayName",
- "value": "send"
+ "value": "Send"
},
{
- "id": "custom.displayMode",
- "value": "gradient-gauge"
+ "id": "custom.cellOptions",
+ "value": {
+ "mode": "gradient",
+ "type": "gauge"
+ }
}
]
},
@@ -799,11 +1129,14 @@
"properties": [
{
"id": "displayName",
- "value": "receive"
+ "value": "Receive"
},
{
- "id": "custom.displayMode",
- "value": "gradient-gauge"
+ "id": "custom.cellOptions",
+ "value": {
+ "mode": "gradient",
+ "type": "gauge"
+ }
}
]
},
@@ -857,22 +1190,32 @@
"h": 11,
"w": 24,
"x": 0,
- "y": 2
+ "y": 13
},
"id": 58,
"interval": "",
"options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
"showHeader": true,
"sortBy": [
{
- "desc": true,
- "displayName": "send"
+ "desc": false,
+ "displayName": "status"
}
]
},
"pluginVersion": "8.1.8",
"targets": [
{
+ "datasource": "${DS_PROMETHEUS}",
"exemplar": false,
"expr": "nic_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",node=~\"$Node\",nic=~\"$Eth\"}",
"format": "table",
@@ -882,6 +1225,7 @@
"refId": "A"
},
{
+ "datasource": "${DS_PROMETHEUS}",
"expr": "nic_new_status{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",node=~\"$Node\",nic=~\"$Eth\"}",
"format": "table",
"hide": false,
@@ -891,6 +1235,7 @@
"refId": "B"
},
{
+ "datasource": "${DS_PROMETHEUS}",
"expr": "nic_util_percent{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",node=~\"$Node\",nic=~\"$Eth\"}",
"format": "table",
"hide": false,
@@ -900,6 +1245,7 @@
"refId": "C"
},
{
+ "datasource": "${DS_PROMETHEUS}",
"expr": "nic_tx_bytes{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",node=~\"$Node\",nic=~\"$Eth\"}",
"format": "table",
"hide": false,
@@ -909,6 +1255,7 @@
"refId": "D"
},
{
+ "datasource": "${DS_PROMETHEUS}",
"expr": "nic_rx_bytes{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",node=~\"$Node\",nic=~\"$Eth\"}",
"format": "table",
"hide": false,
@@ -918,9 +1265,7 @@
"refId": "E"
}
],
- "timeFrom": null,
- "timeShift": null,
- "title": "Ethernet ports",
+ "title": "NIC ports",
"transformations": [
{
"id": "filterFieldsByName",
@@ -959,6 +1304,7 @@
"speed": false,
"state": true
},
+ "includeByName": {},
"indexByName": {
"Value #B": 6,
"Value #C": 7,
@@ -966,13 +1312,16 @@
"Value #E": 9,
"cluster": 1,
"datacenter": 0,
- "nic": 2,
- "node": 3,
+ "nic": 3,
+ "node": 2,
"speed": 4,
"type": 5
},
"renameByName": {
- "datacenter": ""
+ "datacenter": "",
+ "nic": "Port",
+ "speed": "Speed",
+ "type": "Type"
}
}
}
@@ -1039,7 +1388,7 @@
"h": 10,
"w": 12,
"x": 0,
- "y": 13
+ "y": 24
},
"id": 12,
"options": {
@@ -1132,7 +1481,7 @@
"h": 10,
"w": 12,
"x": 12,
- "y": 13
+ "y": 24
},
"id": 28,
"options": {
@@ -1226,7 +1575,7 @@
"h": 8,
"w": 8,
"x": 0,
- "y": 23
+ "y": 34
},
"id": 61,
"options": {
@@ -1318,7 +1667,7 @@
"h": 8,
"w": 8,
"x": 8,
- "y": 23
+ "y": 34
},
"id": 29,
"options": {
@@ -1415,7 +1764,7 @@
"h": 8,
"w": 8,
"x": 16,
- "y": 23
+ "y": 34
},
"id": 30,
"options": {
@@ -1670,7 +2019,7 @@
"h": 9,
"w": 24,
"x": 0,
- "y": 31
+ "y": 42
},
"id": 119,
"options": {
@@ -1983,7 +2332,7 @@
}
]
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "8.1.8",
"targets": [
{
"editorMode": "code",
@@ -4814,5 +5163,5 @@
"timezone": "",
"title": "ONTAP: Network",
"uid": "cdot-network",
- "version": 11
+ "version": 12
}
diff --git a/grafana/dashboards/cmode/nfsTroubleshooting.json b/grafana/dashboards/cmode/nfsTroubleshooting.json
index 6c55065b0..e31655b6c 100644
--- a/grafana/dashboards/cmode/nfsTroubleshooting.json
+++ b/grafana/dashboards/cmode/nfsTroubleshooting.json
@@ -1702,7 +1702,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -1712,7 +1712,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -1725,7 +1725,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -1735,7 +1735,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/nfs_clients.json b/grafana/dashboards/cmode/nfs_clients.json
index 1a049007d..216a148de 100644
--- a/grafana/dashboards/cmode/nfs_clients.json
+++ b/grafana/dashboards/cmode/nfs_clients.json
@@ -564,7 +564,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -574,7 +574,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -590,7 +590,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -600,7 +600,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/qtree.json b/grafana/dashboards/cmode/qtree.json
index f40e30e05..690f8aeb0 100644
--- a/grafana/dashboards/cmode/qtree.json
+++ b/grafana/dashboards/cmode/qtree.json
@@ -767,7 +767,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -777,7 +777,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -794,7 +794,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -805,7 +805,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/quotaReport.json b/grafana/dashboards/cmode/quotaReport.json
index 584fa2581..98b2d93e1 100644
--- a/grafana/dashboards/cmode/quotaReport.json
+++ b/grafana/dashboards/cmode/quotaReport.json
@@ -838,7 +838,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -848,7 +848,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -865,7 +865,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -876,7 +876,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/s3ObjectStorage.json b/grafana/dashboards/cmode/s3ObjectStorage.json
index 3e1f61e35..ba7073f93 100644
--- a/grafana/dashboards/cmode/s3ObjectStorage.json
+++ b/grafana/dashboards/cmode/s3ObjectStorage.json
@@ -1686,7 +1686,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(ontaps3_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -1696,7 +1696,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(ontaps3_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -1713,7 +1713,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(ontaps3_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -1724,7 +1724,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(ontaps3_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/security.json b/grafana/dashboards/cmode/security.json
index f4cfa719f..9b6028d26 100644
--- a/grafana/dashboards/cmode/security.json
+++ b/grafana/dashboards/cmode/security.json
@@ -5065,7 +5065,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(svm_labels{system_type!=\"7mode\"},datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"},datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -5075,7 +5075,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(svm_labels{system_type!=\"7mode\"},datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"},datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -5091,7 +5091,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(svm_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -5101,7 +5101,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(svm_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"},cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/shelf.json b/grafana/dashboards/cmode/shelf.json
index 25eb996d1..dab574e51 100644
--- a/grafana/dashboards/cmode/shelf.json
+++ b/grafana/dashboards/cmode/shelf.json
@@ -1936,7 +1936,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(shelf_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -1946,7 +1946,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(shelf_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -1962,7 +1962,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(shelf_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -1972,7 +1972,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(shelf_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/smb.json b/grafana/dashboards/cmode/smb.json
index 28de4c687..072207419 100644
--- a/grafana/dashboards/cmode/smb.json
+++ b/grafana/dashboards/cmode/smb.json
@@ -1741,7 +1741,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -1751,7 +1751,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -1767,7 +1767,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -1777,7 +1777,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/snapmirror_destinations.json b/grafana/dashboards/cmode/snapmirror_destinations.json
index 70a62fcd8..3ed00e7bc 100644
--- a/grafana/dashboards/cmode/snapmirror_destinations.json
+++ b/grafana/dashboards/cmode/snapmirror_destinations.json
@@ -74,9 +74,10 @@
},
"description": "",
"editable": true,
- "fiscalYearStartMonth": 0,
+ "gnetId": null,
"graphTooltip": 1,
"id": null,
+ "iteration": 1730300177877,
"links": [
{
"asDropdown": true,
@@ -93,7 +94,6 @@
"url": ""
}
],
- "liveNow": false,
"panels": [
{
"datasource": "${DS_PROMETHEUS}",
@@ -113,13 +113,7 @@
"content": "The SnapMirror Destinations dashboard displays the destination view of all SnapMirror relationships. The filters provided above are applied from the destination side of SnapMirror.",
"mode": "markdown"
},
- "pluginVersion": "10.3.1",
- "targets": [
- {
- "datasource": "${DS_PROMETHEUS}",
- "refId": "A"
- }
- ],
+ "pluginVersion": "8.1.8",
"title": "Important Information about SnapMirror Destinations dashboard",
"type": "text"
},
@@ -134,125 +128,75 @@
},
"id": 15,
"panels": [],
- "targets": [
- {
- "datasource": "${DS_PROMETHEUS}",
- "refId": "A"
- }
- ],
"title": "Highlights",
"type": "row"
},
{
"datasource": "${DS_PROMETHEUS}",
- "description": "This panel displays volume relationship count based on the relationship health.",
+ "description": "Number of unhealhty snapmirrors.",
"fieldConfig": {
"defaults": {
"color": {
- "mode": "palette-classic"
- },
- "custom": {
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- }
+ "mode": "thresholds"
},
- "decimals": 0,
"mappings": [],
- "min": 0,
- "unitScale": true
- },
- "overrides": [
- {
- "matcher": {
- "id": "byName",
- "options": "Healthy"
- },
- "properties": [
+ "noValue": "0",
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
{
- "id": "color",
- "value": {
- "fixedColor": "green",
- "mode": "fixed"
- }
+ "color": "red",
+ "value": null
}
]
},
- {
- "matcher": {
- "id": "byName",
- "options": "Unhealthy"
- },
- "properties": [
- {
- "id": "color",
- "value": {
- "fixedColor": "red",
- "mode": "fixed"
- }
- }
- ]
- }
- ]
+ "unit": "short"
+ },
+ "overrides": []
},
"gridPos": {
- "h": 12,
- "w": 11,
+ "h": 6,
+ "w": 6,
"x": 0,
"y": 3
},
- "id": 112,
+ "id": 142,
+ "links": [],
"options": {
- "legend": {
- "displayMode": "table",
- "placement": "right",
- "showLegend": true,
- "values": [
- "value"
- ]
- },
- "pieType": "donut",
+ "colorMode": "value",
+ "graphMode": "none",
+ "justifyMode": "center",
+ "orientation": "horizontal",
"reduceOptions": {
"calcs": [
- "last"
+ "lastNotNull"
],
"fields": "",
"values": false
},
- "tooltip": {
- "mode": "none",
- "sort": "none"
- }
+ "showPercentChange": false,
+ "text": {},
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "8.1.2",
+ "pluginVersion": "8.1.8",
"targets": [
{
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",healthy=\"true\",relationship_id!=\"\"}) or vector (0)",
- "format": "time_series",
- "instant": true,
- "interval": "",
- "legendFormat": "Healthy",
- "refId": "A"
- },
- {
- "datasource": "${DS_PROMETHEUS}",
- "editorMode": "code",
- "exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",healthy=\"false\",relationship_id!=\"\"}) or vector (0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",healthy=\"false\",relationship_id!=\"\"}) or vector (0)",
"format": "time_series",
"hide": false,
"instant": true,
"interval": "",
- "legendFormat": "Unhealthy",
- "refId": "B"
+ "intervalFactor": 1,
+ "legendFormat": "",
+ "refId": "A"
}
],
- "title": "Relationship Health Overview",
- "type": "piechart"
+ "title": "Unhealthy",
+ "type": "stat"
},
{
"datasource": "${DS_PROMETHEUS}",
@@ -270,15 +214,14 @@
}
},
"decimals": 0,
- "mappings": [],
- "unitScale": true
+ "mappings": []
},
"overrides": []
},
"gridPos": {
"h": 12,
- "w": 13,
- "x": 11,
+ "w": 18,
+ "x": 6,
"y": 3
},
"id": 111,
@@ -311,7 +254,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",derived_relationship_type=\"extended_data_protection\",relationship_id!=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\".*$Volume.*\",derived_relationship_type=\"extended_data_protection\",relationship_id!=\"\"}) or vector(0)",
"instant": true,
"interval": "",
"legendFormat": "Asynchronous Mirror",
@@ -321,7 +264,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",derived_relationship_type=\"mirror_vault\",relationship_id!=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\".*$Volume.*\",derived_relationship_type=\"mirror_vault\",relationship_id!=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -332,7 +275,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",derived_relationship_type=\"vault\",relationship_id!=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\".*$Volume.*\",derived_relationship_type=\"vault\",relationship_id!=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -343,7 +286,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",derived_relationship_type=\"sync_mirror_strict\",relationship_id!=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\".*$Volume.*\",derived_relationship_type=\"sync_mirror_strict\",relationship_id!=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -354,7 +297,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",derived_relationship_type=\"sync_mirror\",relationship_id!=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\".*$Volume.*\",derived_relationship_type=\"sync_mirror\",relationship_id!=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -365,7 +308,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",derived_relationship_type=\"automated_failover\",relationship_id!=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\".*$Volume.*\",derived_relationship_type=\"automated_failover\",relationship_id!=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -376,7 +319,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",derived_relationship_type=\"automated_failover_duplex\",relationship_id!=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\".*$Volume.*\",derived_relationship_type=\"automated_failover_duplex\",relationship_id!=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -388,6 +331,73 @@
"transformations": [],
"type": "piechart"
},
+ {
+ "datasource": "${DS_PROMETHEUS}",
+ "description": "Number of healhty snapmirrors.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [],
+ "noValue": "0",
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 6,
+ "x": 0,
+ "y": 9
+ },
+ "id": 143,
+ "links": [],
+ "options": {
+ "colorMode": "value",
+ "graphMode": "none",
+ "justifyMode": "center",
+ "orientation": "horizontal",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "text": {},
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "8.1.8",
+ "targets": [
+ {
+ "datasource": "${DS_PROMETHEUS}",
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",healthy=\"true\",relationship_id!=\"\"}) or vector (0)",
+ "format": "time_series",
+ "hide": false,
+ "instant": true,
+ "interval": "",
+ "intervalFactor": 1,
+ "legendFormat": "",
+ "refId": "A"
+ }
+ ],
+ "title": "Healthy",
+ "type": "stat"
+ },
{
"datasource": "${DS_PROMETHEUS}",
"description": "This panel displays detail of all the snapmirror relationships from destination side of view.",
@@ -398,14 +408,10 @@
},
"custom": {
"align": "left",
- "cellOptions": {
- "type": "auto"
- },
- "filterable": true,
- "inspect": false
+ "displayMode": "auto",
+ "filterable": true
},
"decimals": 2,
- "fieldMinMax": true,
"links": [],
"mappings": [],
"min": 0,
@@ -417,8 +423,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -427,13 +432,6 @@
"options": "Size"
},
"properties": [
- {
- "id": "custom.cellOptions",
- "value": {
- "mode": "lcd",
- "type": "gauge"
- }
- },
{
"id": "unit",
"value": "bytes"
@@ -456,6 +454,10 @@
{
"id": "custom.width",
"value": 240
+ },
+ {
+ "id": "custom.displayMode",
+ "value": "lcd-gauge"
}
]
},
@@ -465,13 +467,6 @@
"options": "Duration"
},
"properties": [
- {
- "id": "custom.cellOptions",
- "value": {
- "mode": "lcd",
- "type": "gauge"
- }
- },
{
"id": "unit",
"value": "s"
@@ -490,6 +485,10 @@
"type": "special"
}
]
+ },
+ {
+ "id": "custom.displayMode",
+ "value": "lcd-gauge"
}
]
},
@@ -503,14 +502,6 @@
"id": "unit",
"value": "s"
},
- {
- "id": "custom.cellOptions",
- "value": {
- "mode": "lcd",
- "type": "gauge",
- "valueDisplayMode": "text"
- }
- },
{
"id": "mappings",
"value": [
@@ -524,6 +515,10 @@
"type": "special"
}
]
+ },
+ {
+ "id": "custom.displayMode",
+ "value": "lcd-gauge"
}
]
},
@@ -686,11 +681,8 @@
]
},
{
- "id": "custom.cellOptions",
- "value": {
- "mode": "gradient",
- "type": "color-background"
- }
+ "id": "custom.displayMode",
+ "value": "color-background"
}
]
}
@@ -723,12 +715,12 @@
}
]
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "8.1.8",
"targets": [
{
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
- "expr": "snapmirror_last_transfer_duration{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\",relationship_id!=\"\"}",
+ "expr": "snapmirror_last_transfer_duration{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\",relationship_id!=\"\"}",
"format": "table",
"hide": false,
"instant": true,
@@ -740,7 +732,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "snapmirror_last_transfer_size{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\", destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\",relationship_id!=\"\"}",
+ "expr": "snapmirror_last_transfer_size{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\",relationship_id!=\"\"}",
"format": "table",
"hide": false,
"instant": true,
@@ -751,7 +743,7 @@
{
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
- "expr": "snapmirror_lag_time{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\",relationship_id!=\"\"}",
+ "expr": "snapmirror_lag_time{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\",relationship_id!=\"\"}",
"format": "table",
"hide": false,
"instant": true,
@@ -763,7 +755,7 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_location=~\".*$ConsistencyGroup\",derived_relationship_type!=\"load_sharing\",relationship_id!=\"\"} ",
+ "expr": "snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\",derived_relationship_type!=\"load_sharing\",relationship_id!=\"\"} ",
"format": "table",
"hide": false,
"instant": true,
@@ -866,9 +858,6 @@
"mode": "palette-classic"
},
"custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@@ -880,7 +869,6 @@
"tooltip": false,
"viz": false
},
- "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -913,8 +901,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -950,10 +937,10 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "snapmirror_last_transfer_duration{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}\nand\ntopk($TopResources, avg_over_time(snapmirror_last_transfer_duration{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}[3h] @ end()))",
+ "expr": "snapmirror_last_transfer_duration{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}\nand\ntopk($TopResources, avg_over_time(snapmirror_last_transfer_duration{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}[3h] @ end()))",
"hide": false,
"interval": "",
- "legendFormat": "{{destination_volume}} - {{source_volume}}",
+ "legendFormat": "{{source_location}} -> {{destination_location}}",
"range": true,
"refCount": 0,
"refId": "B",
@@ -972,9 +959,6 @@
"mode": "palette-classic"
},
"custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@@ -986,7 +970,6 @@
"tooltip": false,
"viz": false
},
- "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -1020,8 +1003,7 @@
}
]
},
- "unit": "s",
- "unitScale": true
+ "unit": "s"
},
"overrides": []
},
@@ -1057,10 +1039,10 @@
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "snapmirror_lag_time{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}\nand\ntopk($TopResources, avg_over_time(snapmirror_lag_time{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}[3h] @ end()))",
+ "expr": "snapmirror_lag_time{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}\nand\ntopk($TopResources, avg_over_time(snapmirror_lag_time{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}[3h] @ end()))",
"hide": false,
"interval": "",
- "legendFormat": "{{destination_volume}} - {{source_volume}}",
+ "legendFormat": "{{source_location}} -> {{destination_location}}",
"range": true,
"refCount": 0,
"refId": "B",
@@ -1079,9 +1061,6 @@
"mode": "palette-classic"
},
"custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@@ -1093,7 +1072,6 @@
"tooltip": false,
"viz": false
},
- "insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
@@ -1126,8 +1104,7 @@
}
]
},
- "unit": "bytes",
- "unitScale": true
+ "unit": "bytes"
},
"overrides": []
},
@@ -1161,11 +1138,13 @@
"targets": [
{
"datasource": "${DS_PROMETHEUS}",
+ "editorMode": "code",
"exemplar": false,
- "expr": "snapmirror_last_transfer_size{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}\nand\ntopk($TopResources, avg_over_time(snapmirror_last_transfer_size{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\"$Volume\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}[3h] @ end()))",
+ "expr": "snapmirror_last_transfer_size{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}\nand\ntopk($TopResources, avg_over_time(snapmirror_last_transfer_size{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",destination_location=~\".*$ConsistencyGroup\"}[3h] @ end()))",
"hide": false,
"interval": "",
- "legendFormat": "{{destination_volume}} - {{source_volume}}",
+ "legendFormat": "{{source_location}} -> {{destination_location}}",
+ "range": true,
"refCount": 0,
"refId": "B",
"textEditor": false
@@ -1187,113 +1166,70 @@
"panels": [
{
"datasource": "${DS_PROMETHEUS}",
- "description": "This panel displays consistency group relationship count based on the relationship health.",
+ "description": "Number of unhealhty snapmirrors.",
"fieldConfig": {
"defaults": {
"color": {
- "mode": "palette-classic"
+ "mode": "thresholds"
},
- "custom": {
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- }
- },
- "decimals": 0,
"mappings": [],
- "unitScale": true
- },
- "overrides": [
- {
- "matcher": {
- "id": "byName",
- "options": "Healthy"
- },
- "properties": [
+ "noValue": "0",
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
{
- "id": "color",
- "value": {
- "fixedColor": "green",
- "mode": "fixed"
- }
+ "color": "red",
+ "value": null
}
]
},
- {
- "matcher": {
- "id": "byName",
- "options": "Unhealthy"
- },
- "properties": [
- {
- "id": "color",
- "value": {
- "fixedColor": "dark-yellow",
- "mode": "fixed"
- }
- }
- ]
- }
- ]
+ "unit": "short"
+ },
+ "overrides": []
},
"gridPos": {
- "h": 12,
- "w": 11,
+ "h": 6,
+ "w": 6,
"x": 0,
"y": 35
},
- "id": 114,
+ "id": 144,
+ "links": [],
"options": {
- "legend": {
- "displayMode": "table",
- "placement": "right",
- "showLegend": true,
- "values": [
- "value"
- ]
- },
- "pieType": "donut",
+ "colorMode": "value",
+ "graphMode": "none",
+ "justifyMode": "center",
+ "orientation": "horizontal",
"reduceOptions": {
"calcs": [
- "last"
+ "lastNotNull"
],
"fields": "",
"values": false
},
- "tooltip": {
- "mode": "single",
- "sort": "none"
- }
+ "showPercentChange": false,
+ "text": {},
+ "textMode": "auto",
+ "wideLayout": true
},
- "pluginVersion": "8.1.2",
+ "pluginVersion": "8.1.8",
"targets": [
{
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",healthy=\"true\",destination_cg_name=~\"$ConsistencyGroup\",relationship_id=\"\"}) or vector (0)",
- "format": "time_series",
- "instant": true,
- "interval": "",
- "legendFormat": "Healthy",
- "refId": "A"
- },
- {
- "datasource": "${DS_PROMETHEUS}",
- "editorMode": "code",
- "exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",healthy=\"false\",destination_cg_name=~\"$ConsistencyGroup\",relationship_id=\"\"}) or vector (0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",group_type=\"consistencygroup\",healthy=\"false\",destination_cg_name=~\"$ConsistencyGroup\",relationship_id=\"\"}) or vector (0)",
"format": "time_series",
"hide": false,
"instant": true,
"interval": "",
- "legendFormat": "Unhealthy",
- "refId": "B"
+ "intervalFactor": 1,
+ "legendFormat": "",
+ "refId": "A"
}
],
- "title": "Consistency Group Relationship Health Overview",
- "type": "piechart"
+ "title": "Unhealthy",
+ "type": "stat"
},
{
"datasource": "${DS_PROMETHEUS}",
@@ -1311,15 +1247,14 @@
}
},
"decimals": 0,
- "mappings": [],
- "unitScale": true
+ "mappings": []
},
"overrides": []
},
"gridPos": {
"h": 12,
- "w": 13,
- "x": 11,
+ "w": 18,
+ "x": 6,
"y": 35
},
"id": 113,
@@ -1351,7 +1286,7 @@
{
"datasource": "${DS_PROMETHEUS}",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"extended_data_protection\",relationship_id=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\"$Volume\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"extended_data_protection\",relationship_id=\"\"}) or vector(0)",
"instant": true,
"interval": "",
"legendFormat": "Asynchronous Mirror",
@@ -1360,7 +1295,7 @@
{
"datasource": "${DS_PROMETHEUS}",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"mirror_vault\",relationship_id=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\"$Volume\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"mirror_vault\",relationship_id=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -1370,7 +1305,7 @@
{
"datasource": "${DS_PROMETHEUS}",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"vault\",relationship_id=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\"$Volume\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"vault\",relationship_id=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -1380,7 +1315,7 @@
{
"datasource": "${DS_PROMETHEUS}",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"sync_mirror_strict\",relationship_id=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\"$Volume\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"sync_mirror_strict\",relationship_id=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -1390,7 +1325,7 @@
{
"datasource": "${DS_PROMETHEUS}",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"sync_mirror\",relationship_id=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\"$Volume\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"sync_mirror\",relationship_id=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -1400,7 +1335,7 @@
{
"datasource": "${DS_PROMETHEUS}",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"automated_failover\",relationship_id=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\"$Volume\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"automated_failover\",relationship_id=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -1410,7 +1345,7 @@
{
"datasource": "${DS_PROMETHEUS}",
"exemplar": false,
- "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"automated_failover_duplex\",relationship_id=\"\"}) or vector(0)",
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\"$Volume\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",derived_relationship_type=\"automated_failover_duplex\",relationship_id=\"\"}) or vector(0)",
"hide": false,
"instant": true,
"interval": "",
@@ -1422,6 +1357,73 @@
"transformations": [],
"type": "piechart"
},
+ {
+ "datasource": "${DS_PROMETHEUS}",
+ "description": "Number of healthy snapmirrors.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [],
+ "noValue": "0",
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 6,
+ "x": 0,
+ "y": 41
+ },
+ "id": 145,
+ "links": [],
+ "options": {
+ "colorMode": "value",
+ "graphMode": "none",
+ "justifyMode": "center",
+ "orientation": "horizontal",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "text": {},
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "8.1.8",
+ "targets": [
+ {
+ "datasource": "${DS_PROMETHEUS}",
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "count(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_volume=~\".*$Volume.*\",destination_vserver=~\"$SVM\",group_type=\"consistencygroup\",healthy=\"true\",destination_cg_name=~\"$ConsistencyGroup\",relationship_id=\"\"}) or vector (0)",
+ "format": "time_series",
+ "hide": false,
+ "instant": true,
+ "interval": "",
+ "intervalFactor": 1,
+ "legendFormat": "",
+ "refId": "A"
+ }
+ ],
+ "title": "Healthy",
+ "type": "stat"
+ },
{
"datasource": "${DS_PROMETHEUS}",
"description": "This panel displays detail of all Consistency Group relationships from destination side of view.",
@@ -1433,11 +1435,8 @@
},
"custom": {
"align": "left",
- "cellOptions": {
- "type": "auto"
- },
- "filterable": true,
- "inspect": false
+ "displayMode": "auto",
+ "filterable": true
},
"mappings": [],
"thresholds": {
@@ -1448,8 +1447,7 @@
"value": null
}
]
- },
- "unitScale": true
+ }
},
"overrides": [
{
@@ -1595,10 +1593,8 @@
"value": 140
},
{
- "id": "custom.cellOptions",
- "value": {
- "type": "color-background"
- }
+ "id": "custom.displayMode",
+ "value": "color-background"
}
]
},
@@ -1668,13 +1664,13 @@
"showHeader": true,
"sortBy": []
},
- "pluginVersion": "10.3.1",
+ "pluginVersion": "8.1.8",
"targets": [
{
"datasource": "${DS_PROMETHEUS}",
"editorMode": "code",
"exemplar": false,
- "expr": "snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",relationship_id=\"\"}",
+ "expr": "snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\",destination_volume=~\"$Volume\",group_type=\"consistencygroup\",destination_cg_name=~\"$ConsistencyGroup\",relationship_id=\"\"}",
"format": "table",
"instant": true,
"interval": "",
@@ -1743,18 +1739,13 @@
"type": "table"
}
],
- "targets": [
- {
- "datasource": "${DS_PROMETHEUS}",
- "refId": "A"
- }
- ],
"title": "Consistency Group Data Protection",
"type": "row"
}
],
"refresh": "",
- "schemaVersion": 39,
+ "schemaVersion": 30,
+ "style": "dark",
"tags": [
"harvest",
"ontap",
@@ -1766,8 +1757,10 @@
"current": {
"selected": false,
"text": "Prometheus",
- "value": "c6938c7d-3e1c-4ff1-9741-ef4164e5259a"
+ "value": "Prometheus"
},
+ "description": null,
+ "error": null,
"hide": 2,
"includeAll": false,
"label": "Data Source",
@@ -1781,12 +1774,15 @@
"type": "datasource"
},
{
+ "allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values(cluster_new_status{system_type!=\"7mode\"},datacenter)",
"description": "Select all the datacenters that contain the ONTAP clusters acting as source for SnapMirror relationships.",
+ "error": null,
"hide": 0,
"includeAll": false,
+ "label": null,
"multi": true,
"name": "Datacenter",
"options": [],
@@ -1808,8 +1804,11 @@
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "query_result(snapmirror_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"})",
+ "description": null,
+ "error": null,
"hide": 0,
"includeAll": true,
+ "label": null,
"multi": true,
"name": "Cluster",
"options": [],
@@ -1832,8 +1831,11 @@
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\"}, destination_vserver)",
+ "description": null,
+ "error": null,
"hide": 0,
"includeAll": true,
+ "label": null,
"multi": true,
"name": "SVM",
"options": [],
@@ -1855,8 +1857,11 @@
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",destination_vserver=~\"$SVM\"}, destination_volume)",
+ "description": null,
+ "error": null,
"hide": 0,
"includeAll": true,
+ "label": null,
"multi": true,
"name": "Volume",
"options": [],
@@ -1865,7 +1870,7 @@
"refId": "StandardVariableQuery"
},
"refresh": 2,
- "regex": "",
+ "regex": "^[a-zA-Z0-9~@#$^*()_+=[\\]{}|\\\\.?: -]*$",
"skipUrlSync": false,
"sort": 1,
"tagValuesQuery": "",
@@ -1878,8 +1883,11 @@
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values(snapmirror_labels{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\", destination_vserver=~\"$SVM\"}, source_cg_name)",
+ "description": null,
+ "error": null,
"hide": 0,
"includeAll": true,
+ "label": null,
"multi": true,
"name": "ConsistencyGroup",
"options": [],
@@ -1903,8 +1911,11 @@
"text": "5",
"value": "5"
},
+ "description": null,
+ "error": null,
"hide": 0,
"includeAll": true,
+ "label": null,
"multi": false,
"name": "TopResources",
"options": [
@@ -2022,6 +2033,5 @@
"timezone": "",
"title": "ONTAP: SnapMirror Destinations",
"uid": "cdot-snapmirror-destinations",
- "version": 1,
- "weekStart": ""
+ "version": 2
}
diff --git a/grafana/dashboards/cmode/svm.json b/grafana/dashboards/cmode/svm.json
index 9dbf3ce8f..7c95537c0 100644
--- a/grafana/dashboards/cmode/svm.json
+++ b/grafana/dashboards/cmode/svm.json
@@ -16425,7 +16425,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(svm_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -16435,7 +16435,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(svm_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -16451,7 +16451,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(svm_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -16461,7 +16461,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(svm_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/volume.json b/grafana/dashboards/cmode/volume.json
index 51a7a47c9..1f2ee2b61 100644
--- a/grafana/dashboards/cmode/volume.json
+++ b/grafana/dashboards/cmode/volume.json
@@ -8981,7 +8981,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -8991,7 +8991,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -9007,7 +9007,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -9017,7 +9017,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/vscan.json b/grafana/dashboards/cmode/vscan.json
index 6844c7813..3041c75da 100644
--- a/grafana/dashboards/cmode/vscan.json
+++ b/grafana/dashboards/cmode/vscan.json
@@ -1124,7 +1124,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(svm_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -1134,7 +1134,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(svm_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -1150,7 +1150,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(svm_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -1160,7 +1160,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(svm_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/grafana/dashboards/cmode/workload.json b/grafana/dashboards/cmode/workload.json
index 93f35eac5..32ff538c1 100644
--- a/grafana/dashboards/cmode/workload.json
+++ b/grafana/dashboards/cmode/workload.json
@@ -6110,7 +6110,7 @@
"allValue": null,
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"description": null,
"error": null,
"hide": 0,
@@ -6120,7 +6120,7 @@
"name": "Datacenter",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\"}, datacenter)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\"}, datacenter)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
@@ -6136,7 +6136,7 @@
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
- "definition": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "definition": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"description": null,
"error": null,
"hide": 0,
@@ -6146,7 +6146,7 @@
"name": "Cluster",
"options": [],
"query": {
- "query": "label_values(volume_labels{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
+ "query": "label_values(cluster_new_status{system_type!=\"7mode\",datacenter=~\"$Datacenter\"}, cluster)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
diff --git a/integration/Jenkinsfile b/integration/Jenkinsfile
index 0d83fb084..d9814085f 100644
--- a/integration/Jenkinsfile
+++ b/integration/Jenkinsfile
@@ -284,7 +284,7 @@ def void stopAndRemoveDockers() {
sh '''
for container_id in $(docker ps -a -q);do docker stop $container_id;done
for container_id in $(docker ps -a -q);do docker rm $container_id;done
- docker system prune --all --force --volumes
+ docker system prune --force --volumes
volumes=$(docker volume ls -qf dangling=true)
if [ "$volumes" ]; then
docker volume rm $volumes
diff --git a/integration/test/copy_logs_test.go b/integration/test/copy_logs_test.go
index ba96da752..7f9b165f7 100644
--- a/integration/test/copy_logs_test.go
+++ b/integration/test/copy_logs_test.go
@@ -37,19 +37,34 @@ func TestCopyLogs(t *testing.T) {
}
}
+type containerInfo struct {
+ name string
+ ignorePattern string
+ errorPattern string
+}
+
func TestNoErrors(t *testing.T) {
utils.SkipIfMissing(t, utils.AnalyzeDockerLogs)
- containerIDs, err := docker.Containers("bin/poller")
- if err != nil {
- panic(err)
+
+ containerPatterns := []containerInfo{
+ {name: "bin/poller", ignorePattern: pollerIgnore(), errorPattern: "ERR"},
+ {name: "prometheus", errorPattern: "level=error|level=warn"},
+ {name: "grafana", errorPattern: "level=error"},
}
- for _, container := range containerIDs {
- checkLogs(t, container)
+
+ for _, containerPattern := range containerPatterns {
+ containers, err := docker.Containers(containerPattern.name)
+ if err != nil {
+ panic(err)
+ }
+ for _, container := range containers {
+ checkLogs(t, container, containerPattern)
+ }
}
}
-func checkLogs(t *testing.T, container docker.Container) {
- cli := fmt.Sprintf(`docker logs %s 2>&1 | grep -Ev '%s' | grep -E "ERR"`, container.ID, ignoreList())
+func checkLogs(t *testing.T, container docker.Container, info containerInfo) {
+ cli := fmt.Sprintf(`docker logs %s 2>&1 | grep -Ev '%s' | grep -E '%s'`, container.ID, info.ignorePattern, info.errorPattern)
command := exec.Command("bash", "-c", cli)
output, err := command.CombinedOutput()
// The grep checks for matching lines.
@@ -76,7 +91,7 @@ func checkLogs(t *testing.T, container docker.Container) {
}
}
-// ignoreList returns a list of regex patterns that will be ignored
-func ignoreList() any {
+// pollerIgnore returns a list of regex patterns that will be ignored
+func pollerIgnore() string {
return `RPC: Remote system error|connection error|Code: 2426405`
}
diff --git a/integration/test/counter_test.go b/integration/test/counter_test.go
index a55a07536..311f12955 100644
--- a/integration/test/counter_test.go
+++ b/integration/test/counter_test.go
@@ -92,7 +92,7 @@ func invokeRestCall(client *rest2.Client, counters map[string][]counterData) err
CounterSchema(counterDetail.perfCounters).
Build()
- if _, err := collectors.InvokeRestCall(client, href, slog.Default()); err != nil {
+ if _, err := collectors.InvokeRestCall(client, href); err != nil {
return fmt.Errorf("failed to invoke rest href=%s call: %w", href, err)
}
}
@@ -134,7 +134,7 @@ func visitRestTemplates(dir string, client *rest2.Client, eachTemp func(path str
return nil
}
- r := eachTemp(path, client.Cluster().GetVersion(), client)
+ r := eachTemp(path, client.Remote().Version, client)
for k, v := range r {
result[k] = v
}
diff --git a/integration/test/installer/grafana.go b/integration/test/installer/grafana.go
index 0eb3cc709..d5ecac7f2 100644
--- a/integration/test/installer/grafana.go
+++ b/integration/test/installer/grafana.go
@@ -22,21 +22,26 @@ func (g *Grafana) Install() bool {
g.image = "grafana/grafana:8.1.8"
slog.Info("Grafana image : " + g.image)
imageName := "grafana"
- _ = docker.StopContainers(imageName)
- cmd := exec.Command("docker", "run", "-d", "-e", "GF_LOG_LEVEL=debug", "-p", utils.GrafanaPort+":"+utils.GrafanaPort, g.image) //nolint:gosec
+ err := docker.StopContainers(imageName)
+ if err != nil {
+ slog.Warn("Error while stopping Grafana container", slog.Any("err", err))
+ }
+ cmd := exec.Command("docker", "run", "-d", "--name", "grafana", "-e", "GF_LOG_LEVEL=debug", "-p", utils.GrafanaPort+":"+utils.GrafanaPort, g.image) //nolint:gosec
cmd.Stdout = os.Stdout
- err := cmd.Start()
+ cmd.Stderr = os.Stderr
+ err = cmd.Start()
utils.PanicIfNotNil(err)
waitCount := 0
- maxWaitCount := 15
+ maxWaitCount := 3
for waitCount < maxWaitCount {
waitCount++
time.Sleep(1 * time.Minute)
if utils.IsURLReachable("http://localhost:" + utils.GrafanaPort) {
return true
}
+ slog.Info("Grafana is not yet reachable.", slog.Int("waitCount", waitCount), slog.Int("maxWaitCount", maxWaitCount))
}
- slog.Info("Reached maximum timeout. Grafana is failed to start", slog.Int("maxWaitCount", maxWaitCount))
+ slog.Info("Reached maximum wait count. Grafana failed to start")
return false
}
diff --git a/integration/test/installer/harvest.go b/integration/test/installer/harvest.go
index dd8836656..c07b8a1f0 100644
--- a/integration/test/installer/harvest.go
+++ b/integration/test/installer/harvest.go
@@ -36,10 +36,16 @@ func (h *Harvest) Stop() {
fmt.Println(status)
}
-func (h *Harvest) AllRunning() bool {
+func (h *Harvest) AllRunning(ignoring ...string) bool {
pollerArray := h.GetPollerInfo()
+outer:
for _, poller := range pollerArray {
if poller.Status != "running" {
+ for _, ignore := range ignoring {
+ if strings.Contains(poller.Poller, ignore) {
+ continue outer
+ }
+ }
return false
}
}
diff --git a/integration/test/installer/rpm.go b/integration/test/installer/rpm.go
index 018f79f07..033ffb379 100644
--- a/integration/test/installer/rpm.go
+++ b/integration/test/installer/rpm.go
@@ -41,7 +41,7 @@ func (r *RPM) Install() bool {
return false
} // use file directly from the repo
harvestObj.Start()
- status := harvestObj.AllRunning()
+ status := harvestObj.AllRunning("keyperf")
asupExecPath := HarvestHome + "/autosupport/asup"
isValidAsup := harvestObj.IsValidAsup(asupExecPath)
return status && isValidAsup
@@ -51,7 +51,7 @@ func (r *RPM) Upgrade() bool {
rpmFileName := "harvest.rpm"
utils.RemoveSafely(rpmFileName)
harvestObj := new(Harvest)
- if !harvestObj.AllRunning() {
+ if !harvestObj.AllRunning("keyperf") {
utils.PanicIfNotNil(errors.New("pollers are not in a running state before upgrade"))
}
versionCmd := []string{"-qa", "harvest"}
diff --git a/integration/test/rpm_installer_test.go b/integration/test/rpm_installer_test.go
index 4fa133a84..19e2076cc 100644
--- a/integration/test/rpm_installer_test.go
+++ b/integration/test/rpm_installer_test.go
@@ -3,7 +3,7 @@ package main
import (
"github.com/Netapp/harvest-automation/test/installer"
"github.com/Netapp/harvest-automation/test/utils"
- "log"
+ "log/slog"
"os"
"testing"
)
@@ -16,7 +16,7 @@ func TestRHELInstall(t *testing.T) {
}
installObject, err := installer.GetInstaller(installer.GRAFANA, "grafana/grafana")
if err != nil {
- log.Println("Unable to initialize installer object for " + installer.GRAFANA)
+ slog.Error("Unable to initialize installer object", slog.String("object", installer.GRAFANA))
panic(err)
}
if !installObject.Install() {
@@ -27,24 +27,24 @@ func TestRHELInstall(t *testing.T) {
installObject, err2 := installer.GetInstaller(installer.RHEL, path)
if err2 != nil {
- log.Println("Unable to initialize installer object")
+ slog.Error("Unable to initialize installer object", slog.String("object", installer.RHEL))
panic(err2)
}
if installObject.Install() {
- log.Println("Installation is successful..")
+ slog.Info("Installation is successful..")
} else {
- log.Println("Setup completed")
- panic("installation is failed.")
+ slog.Error("Installation failed")
+ panic("installation failed.")
}
harvestObj := new(installer.Harvest)
- if harvestObj.AllRunning() {
- log.Println("All pollers are running")
+ if harvestObj.AllRunning("keyperf") {
+ slog.Info("All pollers but keyperf are running")
} else {
t.Errorf("One or more pollers are not running.")
}
installObject, err = installer.GetInstaller(installer.PROMETHEUS, "prom/prometheus")
if err != nil {
- log.Println("Unable to initialize installer object for " + installer.PROMETHEUS)
+ slog.Error("Unable to initialize installer object", slog.String("object", installer.PROMETHEUS))
panic(err)
}
if !installObject.Install() {
@@ -58,11 +58,11 @@ func TestRHELStop(t *testing.T) {
var path = os.Getenv("BUILD_PATH")
installObject, err2 := installer.GetInstaller(installer.RHEL, path)
if err2 != nil {
- log.Println("Unable to initialize installer object")
+ slog.Info("Unable to initialize installer object")
panic(err2)
}
if installObject.Stop() {
- log.Println("Stop is successful..")
+ slog.Info("Stop is successful..")
} else {
panic("Stop is failed.")
}
diff --git a/integration/test/utils/utils.go b/integration/test/utils/utils.go
index f2b2894b9..146cef172 100644
--- a/integration/test/utils/utils.go
+++ b/integration/test/utils/utils.go
@@ -2,9 +2,11 @@ package utils
import (
"bytes"
+ "context"
"encoding/json"
"errors"
"fmt"
+ "github.com/carlmjohnson/requests"
"github.com/netapp/harvest/v2/cmd/tools/grafana"
"github.com/netapp/harvest/v2/pkg/conf"
"github.com/netapp/harvest/v2/pkg/slogx"
@@ -179,12 +181,8 @@ func WaitForGrafana() bool {
}
func IsURLReachable(url string) bool {
- response, err := http.Get(url) //nolint:gosec
- if err != nil {
- return false
- }
- defer response.Body.Close()
- return response.StatusCode == http.StatusOK
+ err := requests.URL(url).Fetch(context.Background())
+ return err == nil
}
func AddPrometheusToGrafana() {
diff --git a/jenkins/artifacts/jenkinsfile b/jenkins/artifacts/jenkinsfile
index 6afecf2cc..325cdb258 100644
--- a/jenkins/artifacts/jenkinsfile
+++ b/jenkins/artifacts/jenkinsfile
@@ -9,6 +9,7 @@ pipeline {
string(name: 'DOCKER_PUBLISH', defaultValue: 'false', description: 'true to publish to dockerhub')
string(name: 'RUN_TEST', defaultValue: 'true', description: 'false to skip test')
string(name: 'OVERWRITE_DOCKER_LATEST_TAG', defaultValue: 'false', description: 'true to overwrite latest tag at dockerhub. Works only if DOCKER_PUBLISH is true')
+ string(name: 'RUN_TRIVY_SCAN', defaultValue: 'false', description: 'true to run Trivy image scan')
}
environment {
@@ -40,6 +41,13 @@ pipeline {
}
stages {
+ stage('Docker Login') {
+ steps {
+ withDockerRegistry([credentialsId: "DockerHub", url: ""]) {
+ sh 'docker login'
+ }
+ }
+ }
stage("Initialization") {
steps {
@@ -185,6 +193,25 @@ pipeline {
}
}
+ stage('Trivy Image Scan') {
+ when {
+ expression {
+ return params.RUN_TRIVY_SCAN == 'true';
+ }
+ }
+ steps {
+ script {
+ currentStage = 'Trivy Image Scan'
+ }
+ sh '''
+ curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
+ export PATH=/usr/local/bin:$PATH
+ trivy image --db-repository public.ecr.aws/aquasecurity/trivy-db --exit-code 1 ${ghcrImage}:latest
+ trivy image --db-repository public.ecr.aws/aquasecurity/trivy-db --exit-code 1 ${ghcrImage}:latest-fips
+ '''
+ }
+ }
+
stage('Publish builds locally'){
steps {
script {
@@ -357,7 +384,7 @@ def void stopAndRemoveDockers() {
rm -rf /opt/home/nightly/
mkdir -p /opt/home/nightly/
for container_id in $(docker ps -a -q);do docker stop $container_id;done
- docker system prune --all --force --volumes
+ docker system prune --force --volumes
volumes=$(docker volume ls -qf dangling=true)
if [ "$volumes" ]; then
docker volume rm $volumes
diff --git a/pkg/conf/remotes.go b/pkg/conf/remotes.go
new file mode 100644
index 000000000..eac95f8a1
--- /dev/null
+++ b/pkg/conf/remotes.go
@@ -0,0 +1,8 @@
+package conf
+
+type Remote struct {
+ Name string
+ Model string
+ UUID string
+ Version string
+}
diff --git a/pkg/util/util.go b/pkg/util/util.go
index 7356ea96e..b44ff2631 100644
--- a/pkg/util/util.go
+++ b/pkg/util/util.go
@@ -27,6 +27,15 @@ import (
var arrayRegex = regexp.MustCompile(`^([a-zA-Z][\w.]*)(\.[0-9#])`)
+var IsONTAPCollector = map[string]struct{}{
+ "ZapiPerf": {},
+ "Zapi": {},
+ "Rest": {},
+ "RestPerf": {},
+ "KeyPerf": {},
+ "Ems": {},
+}
+
var IsCollector = map[string]struct{}{
"ZapiPerf": {},
"Zapi": {},
diff --git a/vendor/github.com/ebitengine/purego/struct_amd64.go b/vendor/github.com/ebitengine/purego/struct_amd64.go
index 06a82dd8c..f3514c984 100644
--- a/vendor/github.com/ebitengine/purego/struct_amd64.go
+++ b/vendor/github.com/ebitengine/purego/struct_amd64.go
@@ -111,7 +111,7 @@ func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFl
return keepAlive
}
-func postMerger(t reflect.Type) bool {
+func postMerger(t reflect.Type) (passInMemory bool) {
// (c) If the size of the aggregate exceeds two eightbytes and the first eight- byte isn’t SSE or any other
// eightbyte isn’t SSEUP, the whole argument is passed in memory.
if t.Kind() != reflect.Struct {
@@ -120,19 +120,7 @@ func postMerger(t reflect.Type) bool {
if t.Size() <= 2*8 {
return false
}
- first := getFirst(t).Kind()
- if first != reflect.Float32 && first != reflect.Float64 {
- return false
- }
- return true
-}
-
-func getFirst(t reflect.Type) reflect.Type {
- first := t.Field(0).Type
- if first.Kind() == reflect.Struct {
- return getFirst(first)
- }
- return first
+ return true // Go does not have an SSE/SEEUP type so this is always true
}
func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) (ok bool) {
@@ -196,7 +184,7 @@ func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintp
val |= uint64(f.Int()&0xFFFF_FFFF) << shift
shift += 32
class |= _INTEGER
- case reflect.Int64:
+ case reflect.Int64, reflect.Int:
val = uint64(f.Int())
shift = 64
class = _INTEGER
@@ -212,7 +200,7 @@ func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintp
val |= f.Uint() << shift
shift += 32
class |= _INTEGER
- case reflect.Uint64:
+ case reflect.Uint64, reflect.Uint:
val = f.Uint()
shift = 64
class = _INTEGER
diff --git a/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd_arm.go b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd_arm.go
new file mode 100644
index 000000000..e4799bcf5
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/cpu/cpu_netbsd_arm.go
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package cpu
+
+type cpuTimes struct {
+ User uint32
+ Nice uint32
+ Sys uint32
+ Intr uint32
+ Idle uint32
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/ex_windows.go b/vendor/github.com/shirou/gopsutil/v4/mem/ex_windows.go
index 4f1573b3c..5c49a478c 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/ex_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/ex_windows.go
@@ -11,7 +11,10 @@ import (
// ExVirtualMemory represents Windows specific information
// https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-memorystatusex
+// https://learn.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-performance_information
type ExVirtualMemory struct {
+ CommitLimit uint64 `json:"commitLimit"`
+ CommitTotal uint64 `json:"commitTotal"`
VirtualTotal uint64 `json:"virtualTotal"`
VirtualAvail uint64 `json:"virtualAvail"`
}
@@ -30,7 +33,16 @@ func (e *ExWindows) VirtualMemory() (*ExVirtualMemory, error) {
return nil, windows.GetLastError()
}
+ var perfInfo performanceInformation
+ perfInfo.cb = uint32(unsafe.Sizeof(perfInfo))
+ perf, _, _ := procGetPerformanceInfo.Call(uintptr(unsafe.Pointer(&perfInfo)), uintptr(perfInfo.cb))
+ if perf == 0 {
+ return nil, windows.GetLastError()
+ }
+
ret := &ExVirtualMemory{
+ CommitLimit: perfInfo.commitLimit * perfInfo.pageSize,
+ CommitTotal: perfInfo.commitTotal * perfInfo.pageSize,
VirtualTotal: memInfo.ullTotalVirtual,
VirtualAvail: memInfo.ullAvailVirtual,
}
diff --git a/vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go b/vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go
index 522cfd1b3..a94b61f4b 100644
--- a/vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go
+++ b/vendor/github.com/shirou/gopsutil/v4/mem/mem_windows.go
@@ -82,6 +82,8 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
if err != nil {
return nil, err
}
+ defer common.PdhCloseQuery.Call(uintptr(counter.Query))
+
usedPercent, err := counter.GetValue()
if err != nil {
return nil, err
diff --git a/vendor/modules.txt b/vendor/modules.txt
index d7e24f093..8a1ae2d4b 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,4 +1,4 @@
-# github.com/ebitengine/purego v0.8.0
+# github.com/ebitengine/purego v0.8.1
## explicit; go 1.18
github.com/ebitengine/purego
github.com/ebitengine/purego/internal/cgo
@@ -49,7 +49,7 @@ github.com/power-devops/perfstat
# github.com/rivo/uniseg v0.4.7
## explicit; go 1.18
github.com/rivo/uniseg
-# github.com/shirou/gopsutil/v4 v4.24.9
+# github.com/shirou/gopsutil/v4 v4.24.10
## explicit; go 1.18
github.com/shirou/gopsutil/v4/common
github.com/shirou/gopsutil/v4/cpu