Skip to content

Commit

Permalink
Merge pull request #97 from PureStorage-OpenConnect/issue_94
Browse files Browse the repository at this point in the history
Add more detail to alerts
  • Loading branch information
sdodsley authored Dec 13, 2023
2 parents 372f430 + c905e2a commit 04ad46f
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 71 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ GOTEST=$(GOCMD) test
GOVET=$(GOCMD) vet
BINARY_NAME=pure-fa-om-exporter
MODULE_NAME=purestorage/fa-openmetrics-exporter
VERSION?=1.0.11
VERSION?=1.0.12
SERVICE_PORT?=9490
DOCKER_REGISTRY?= quay.io/purestorage/
EXPORT_RESULT?=false # for CI please set EXPORT_RESULT to true
Expand Down
2 changes: 1 addition & 1 deletion build/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM golang:alpine as build
ARG VERSION=1.0.11
ARG VERSION=1.0.12

WORKDIR /usr/src/app

Expand Down
6 changes: 3 additions & 3 deletions docs/deployment-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Deploying the binary requires [go](https://go.dev) to compile the code and runni
```console
$ ls out/bin
$ .out/bin/pure-fa-openmetrics-exporter
Start Pure FlashArray exporter v1.0.11 on 0.0.0.0:9490
Start Pure FlashArray exporter v1.0.12 on 0.0.0.0:9490
```

2. **Test the exporter**
Expand Down Expand Up @@ -234,7 +234,7 @@ Follow steps 1-4 and 7-8 of the default binary deployment, but substitute the fo
```console
$ ls out/bin
$ .out/bin/pure-fa-openmetrics-exporter --tokens /directorypath/tokens.yaml
Start Pure FlashArray exporter v1.0.11 on 0.0.0.0:9490
Start Pure FlashArray exporter v1.0.12 on 0.0.0.0:9490
```

3. **Test the exporter**
Expand Down Expand Up @@ -333,4 +333,4 @@ Create the certificate and key and pass the exporter the files. There are many d
Full check using certificate.
```console
$ curl --cacert pure-ome.crt -H 'Authorization: Bearer 11111111-1111-1111-1111-111111111111' -X GET 'http://pure-ome.fqdn.com:9490/metrics/array?endpoint=array01'
```
```
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.15.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -51,8 +51,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
Expand Down
15 changes: 12 additions & 3 deletions internal/openmetrics-exporter/alerts_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,24 @@ func (c *AlertsCollector) Collect(ch chan<- prometheus.Metric) {
}
al := make(map[string]float64)
for _, alert := range alerts.Items {
al[fmt.Sprintf("%s,%s", alert.ComponentType, alert.Severity)] += 1
al[fmt.Sprintf("%s,%d,%s,%d,%s,%s,%s,%s",
alert.Category,
alert.Code,
alert.ComponentType,
alert.Created,
alert.Issue,
alert.Name,
alert.Severity,
alert.Summary,
)] += 1
}
for a, n := range al {
alert := strings.Split(a, ",")
ch <- prometheus.MustNewConstMetric(
c.AlertsDesc,
prometheus.GaugeValue,
n,
alert[0], alert[1],
alert[0], alert[1], alert[2], alert[3], alert[4], alert[5], alert[6], alert[7],
)
}
}
Expand All @@ -42,7 +51,7 @@ func NewAlertsCollector(fa *client.FAClient) *AlertsCollector {
AlertsDesc: prometheus.NewDesc(
"purefa_alerts_open",
"FlashArray open alert events",
[]string{"component_type", "severity"},
[]string{"category", "code", "component_type", "created", "issue", "name", "severity", "summary"},
prometheus.Labels{},
),
Client: fa,
Expand Down
54 changes: 26 additions & 28 deletions internal/openmetrics-exporter/alerts_collector_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package collectors


import (
"encoding/json"
"fmt"
"testing"
"regexp"
"strings"
"net/http"
"net/http/httptest"
"encoding/json"
"os"

"purestorage/fa-openmetrics-exporter/internal/rest-client"
client "purestorage/fa-openmetrics-exporter/internal/rest-client"
"regexp"
"strings"
"testing"
)

func TestAlertsCollector(t *testing.T) {
Expand All @@ -24,38 +22,38 @@ func TestAlertsCollector(t *testing.T) {
json.Unmarshal(ropen, &aopen)
json.Unmarshal(rall, &aall)
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
urlall := regexp.MustCompile(`^/api/([0-9]+.[0-9]+)?/alerts$`)
urlopen := regexp.MustCompile(`^/api/([0-9]+.[0-9]+)?/alerts\?filter=state%3D%27open%27$`)
if r.URL.Path == "/api/api_version" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
urlall := regexp.MustCompile(`^/api/([0-9]+.[0-9]+)?/alerts$`)
urlopen := regexp.MustCompile(`^/api/([0-9]+.[0-9]+)?/alerts\?filter=state%3D%27open%27$`)
if r.URL.Path == "/api/api_version" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(vers))
} else if urlopen.MatchString(r.URL.Path + "?" + r.URL.RawQuery) {
} else if urlopen.MatchString(r.URL.Path + "?" + r.URL.RawQuery) {
w.Header().Set("x-auth-token", "faketoken")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(ropen))
} else if urlall.MatchString(r.URL.Path) {
} else if urlall.MatchString(r.URL.Path) {
w.Header().Set("x-auth-token", "faketoken")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(rall))
}
}))
endp := strings.Split(server.URL, "/")
e := endp[len(endp)-1]
al := make(map[string]float64)
for _, a := range aopen.Items {
al[fmt.Sprintf("%s,%s", a.ComponentType, a.Severity)] += 1
}
}))
endp := strings.Split(server.URL, "/")
e := endp[len(endp)-1]
al := make(map[string]float64)
for _, a := range aopen.Items {
al[fmt.Sprintf("%s,%d,%s,%d,%s,%s,%s,%s", a.Category, a.Code, a.ComponentType, a.Created, a.Issue, a.Name, a.Severity, a.Summary)] += 1
}
want := make(map[string]bool)
for a, n := range al {
alert := strings.Split(a, ",")
// want[fmt.Sprintf("label:{name:\"component_type\" value:\"%s\"} label:{name:\"severity\" value:\"%s\"} gauge:{value:%g}", alert[0], alert[1], n)] = true
want[fmt.Sprintf("label:{name:\"component_type\" value:\"%s\"} label:{name:\"severity\" value:\"%s\"} gauge:{value:%g}", alert[0], alert[1], n)] = true
for a, n := range al {
alert := strings.Split(a, ",")

want[fmt.Sprintf("label:{name:\"category\" value:\"%s\"} label:{name:\"code\" value:\"%s\"} label:{name:\"component_type\" value:\"%s\"} label:{name:\"created\" value:\"%s\"} label:{name:\"issue\" value:\"%s\"} label:{name:\"name\" value:\"%s\"} label:{name:\"severity\" value:\"%s\"} label:{name:\"summary\" value:\"%s\"} gauge:{value:%g}", alert[0], alert[1], alert[2], alert[3], alert[4], alert[5], alert[6], alert[7], n)] = true
}
c := client.NewRestClient(e, "fake-api-token", "latest", false)
c := client.NewRestClient(e, "fake-api-token", "latest", false)
ac := NewAlertsCollector(c)
metricsCheck(t, ac, want)
server.Close()
metricsCheck(t, ac, want)
server.Close()
}
49 changes: 24 additions & 25 deletions internal/rest-client/alerts.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
package client


type Alert struct {
Id string `json:"id"`
Name string `json:"name"`
Actual string `json:"actual"`
Closed int `json:"closed"`
Code int `json:"code"`
ComponentName string `json:"component_name"`
ComponentType string `json:"component_type"`
Created int `json:"created"`
Description string `json:"description"`
Expected string `json:"expected"`
Flagged bool `json:"flagged"`
Issue string `json:"issue"`
Index int `json:"index"`
KnowledgeBaseUrl string `json:"knowledge_base_url"`
Notified int `json:"notified"`
Severity string `json:"severity"`
State string `json:"state"`
Summary string `json:"summary"`
Updated int `json:"updated"`
Id string `json:"id"`
Name string `json:"name"`
Actual string `json:"actual"`
Category string `json:"category"`
Closed int64 `json:"closed"`
Code int64 `json:"code"`
ComponentName string `json:"component_name"`
ComponentType string `json:"component_type"`
Created int64 `json:"created"`
Description string `json:"description"`
Expected string `json:"expected"`
Flagged bool `json:"flagged"`
Issue string `json:"issue"`
KnowledgeBaseUrl string `json:"knowledge_base_url"`
Notified int64 `json:"notified"`
Severity string `json:"severity"`
State string `json:"state"`
Summary string `json:"summary"`
Updated int64 `json:"updated"`
}

type AlertsList struct {
ContinuationToken string `json:"continuation_token"`
TotalItemCount int `json:"total_item_count"`
MoreItemsRemaining bool `json:"more_items_remaining"`
Items []Alert `json:"items"`
ContinuationToken string `json:"continuation_token"`
TotalItemCount int32 `json:"total_item_count"`
MoreItemsRemaining bool `json:"more_items_remaining"`
Items []Alert `json:"items"`
}

func (fa *FAClient) GetAlerts(filter string) *AlertsList {
Expand All @@ -48,6 +47,6 @@ func (fa *FAClient) GetAlerts(filter string) *AlertsList {
if err != nil {
fa.Error = err
}

return result
}
15 changes: 11 additions & 4 deletions specification/metrics/purefa-metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,17 @@ This document describes the semantic conventions for Pure FlashArray Metrics.

**Description:** FlashArray Open Alerts

| Status | Name | Description | Units | Metric Type ([*](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#metric-types)) | Value Type | Attribute Key | Attribute Values |
| --------- | ------------------ | ---------------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------- | ---------- | ---------------- | ------------------------------------------------------------------------------------------------------------------ |
| Available | purefa_alerts_open | FlashArray open alert events | | Gauge | Double | `component_type` | `chassis`, `drive_bay`, `nvram_bay`, `power_supply`, `temp_sensor`, `controller`, `eth_port`, `cooling`, `fc_port` |
| | | | | | | `severity` | `info`, `warning`, `critical`, `hidden` |
| Status | Name | Description | Units | Metric Type ([*](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#metric-types)) | Value Type | Attribute Key | Attribute Values |
| --------- | ------------------ | ------------------------------------------------------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------- | ---------- | ---------------- | ------------------------------------------------------------------------------------------------------------------ |
| Available | purefa_alerts_open | FlashArray open alert event | | Gauge | Double | `name` | (name) |
| | | The code number of the event | | | | `code` | (code) |
| | | | | | | `component_type` | `chassis`, `drive_bay`, `nvram_bay`, `power_supply`, `temp_sensor`, `controller`, `eth_port`, `cooling`, `fc_port` |
| | | The time the alert was created in milliseconds since the UNIX epoch | | | | `created` | (created) |
| | | Information about the alert cause | | | | `issue` | (issue) |
| | | The category of the alert. | | | | `category` | `array`, `hardware`, `software` |
| | | | | | | `severity` | `info`, `warning`, `critical`, `hidden` |
| | | A summary of the alert | | | | `summary` | (summary) |
| |


### `purefa_array` - FlashArray metrics
Expand Down

0 comments on commit 04ad46f

Please sign in to comment.