From a746015709cf5aed31e33d6c7f85fa88642a6b26 Mon Sep 17 00:00:00 2001 From: Alexander Opryshko Date: Sat, 28 Aug 2021 21:21:42 +0300 Subject: [PATCH 1/2] fix issue "Refresh token #4" --- Dockerfile | 17 ++++++++--------- pkg/exporter/exporter.go | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/Dockerfile b/Dockerfile index b62b0ad..3b7eab8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,12 @@ FROM golang:1.16-alpine as builder -WORKDIR $GOPATH/src/kts/push +WORKDIR $GOPATH/src/github.com/ktsstudio/selectel-exporter COPY . . -RUN ls -al . -RUN go build pkg/main.go -RUN cp main / +RUN apk update && apk upgrade && apk add --no-cache ca-certificates +RUN update-ca-certificates +RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/selectel-exporter pkg/main.go -FROM alpine:3.14 - -COPY --from=builder /main /app/ -WORKDIR /app -CMD ./main +FROM scratch +COPY --from=builder /go/bin/selectel-exporter /go/bin/selectel-exporter +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +ENTRYPOINT ["/go/bin/selectel-exporter"] diff --git a/pkg/exporter/exporter.go b/pkg/exporter/exporter.go index 64c79a9..0946a2d 100644 --- a/pkg/exporter/exporter.go +++ b/pkg/exporter/exporter.go @@ -15,16 +15,16 @@ type selectelCollector interface { } type exporter struct { - token string - region string - project selapi.Project + token string + region string + project selapi.Project openstackAccountToken string - lastTokenUpdate time.Time + lastTokenUpdate time.Time refreshPeriod time.Duration - stopCh chan bool - wg sync.WaitGroup - collectors []selectelCollector + stopCh chan bool + wg sync.WaitGroup + collectors []selectelCollector datastores []selapi.Datastore } @@ -47,11 +47,11 @@ func Init(config *config.ExporterConfig, refreshPeriod time.Duration) (*exporter } e := &exporter{ - token: config.Token, - region: config.Region, - project: project, + token: config.Token, + region: config.Region, + project: project, refreshPeriod: refreshPeriod, - stopCh: make(chan bool), + stopCh: make(chan bool), } err = e.obtainToken() if err != nil { @@ -79,10 +79,10 @@ func (e *exporter) obtainToken() error { } func (e *exporter) checkToken() error { - if e.lastTokenUpdate.Sub(time.Now()) > 24 * time.Hour { - return e.obtainToken() - } - return nil + if time.Now().Sub(e.lastTokenUpdate) > 20*time.Hour { + return e.obtainToken() + } + return nil } func (e *exporter) fetchDatastores() error { @@ -119,7 +119,7 @@ func (e *exporter) runCollectors() { wg.Wait() } -func (e *exporter) loop() { +func (e *exporter) loop() { log.Println("exporter loop has started") e.wg.Add(1) for { From 221dcc2955648f181b21795339140ca5e2f7d644 Mon Sep 17 00:00:00 2001 From: Alexander Opryshko Date: Sat, 28 Aug 2021 23:31:26 +0300 Subject: [PATCH 2/2] add feature "Instance role label #3" --- README.md | 12 +++++++++++- pkg/exporter/dbcollector.go | 2 ++ pkg/exporter/dscollector.go | 12 +++++++++--- pkg/selapi/data.go | 17 +++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b817b5e..bd6f21a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Prometheus exporter для получения метрик облака [Selecte Полученные данные нужно передать в переменные selectel.token и selectel.region соответственно. ```shell helm repo add kts https://ktsstudio.github.io/helm-charts -helm install selexp --wait --set selectel.token=,selectel.region= kts/selectel-exporter +helm install selexp --wait --set selectel.token=,selectel.region= -n kts/selectel-exporter ``` Если вы используете prometheus-operator, то укажите serviceMonitor.enabled=true и serviceMonitor.additionalLabels. В additionalLabels нужно указать label, которые указаны в [serviceMonitorSelector](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md). @@ -27,6 +27,14 @@ export SELECTEL_REGION= ./selectel-exporter ``` +### Как проверить? + +```shell +helm test selexp -n +# или +curl --request GET --url 'http://:9100/metrics' +``` + # Доступные метрики ## Хранилище ([Datastore](https://developers.selectel.ru/docs/selectel-cloud-platform/dbaas_api/)) @@ -44,6 +52,7 @@ Label | Описание project|имя проекта datastore|имя хранилища ip|адрес узла в кластере +role|является ли instance мастером или репликой #### Пример selectel_datastore_cpu{datastore="kts",ip="10.0.0.210",project="kts"} 1.787500000209541 @@ -76,6 +85,7 @@ project|имя проекта datastore|имя хранилища ip|адрес узла в кластере database|имя базы данных +role|является ли instance мастером или репликой #### Пример selectel_database_tup_returned{database="kts",datastore="kts",ip="10.0.3.214",project="kts"} 2.1127298e+06 diff --git a/pkg/exporter/dbcollector.go b/pkg/exporter/dbcollector.go index 896fdd7..19db73a 100644 --- a/pkg/exporter/dbcollector.go +++ b/pkg/exporter/dbcollector.go @@ -29,6 +29,7 @@ func (col *databaseCollector) registerGauge(metricName string, metric selapi.Dat key := buildGaugeKey(metricName, metric.Ip, metric.DbName) g, ok := col.metrics[key] if !ok { + instance := col.datastore.GetInstance(metric.Ip) g = prometheus.NewGauge(prometheus.GaugeOpts{ Name: metricName, ConstLabels: prometheus.Labels{ @@ -36,6 +37,7 @@ func (col *databaseCollector) registerGauge(metricName string, metric selapi.Dat "datastore": col.datastore.Name, "ip": metric.Ip, "database": metric.DbName, + "role": instance.Role, }, }) prometheus.MustRegister(g) diff --git a/pkg/exporter/dscollector.go b/pkg/exporter/dscollector.go index e461ea4..45eb7e2 100644 --- a/pkg/exporter/dscollector.go +++ b/pkg/exporter/dscollector.go @@ -16,7 +16,7 @@ type datastoreMetrics struct { } type datastoreCollector struct { - project selapi.Project + project selapi.Project datastore selapi.Datastore metrics map[string]*datastoreMetrics } @@ -31,9 +31,15 @@ func NewDatastoreCollector(project selapi.Project, datastore selapi.Datastore) * func (col *datastoreCollector) registerGauge(name string, g prometheus.Gauge, ip string, value float64) prometheus.Gauge { if g == nil { + instance := col.datastore.GetInstance(ip) g = prometheus.NewGauge(prometheus.GaugeOpts{ - Name: name, - ConstLabels: prometheus.Labels{"project": col.project.Name, "datastore": col.datastore.Name, "ip": ip}, + Name: name, + ConstLabels: prometheus.Labels{ + "project": col.project.Name, + "datastore": col.datastore.Name, + "ip": ip, + "role": instance.Role, + }, }) prometheus.MustRegister(g) } diff --git a/pkg/selapi/data.go b/pkg/selapi/data.go index 538b801..56cf2a5 100644 --- a/pkg/selapi/data.go +++ b/pkg/selapi/data.go @@ -7,10 +7,27 @@ import ( "net/http" ) +type DatastoreInstance struct { + Hostname string `json:"hostname"` + IP string `json:"ip"` + Role string `json:"role"` + Status string `json:"status"` +} + type Datastore struct { Id string `json:"id"` Name string `json:"name"` Enabled bool `json:"enabled"` + Instances []DatastoreInstance `json:"instances"` +} + +func (d *Datastore) GetInstance(ip string) *DatastoreInstance { + for _, i := range d.Instances { + if i.IP == ip { + return &i + } + } + return &DatastoreInstance{} } type DatastoresResponse struct {