Skip to content

Commit

Permalink
feat: support prometheus metrics (#76)
Browse files Browse the repository at this point in the history
**Background**
To enhance monitoring and observability, we have introduced Prometheus
metrics support in the project. These metrics will help us better
understand the system's performance and identify potential bottlenecks.

**New Features**
In this PR, we have added the following eight Prometheus metrics:

1. `opengemini_client_query_total` Count all queries
2. `opengemini_client_query_database_total` Count of opengemini queries
and classify using database
3. `opengemini_client_query_latency` Calculate the average of the
queries
4. `opengemini_client_query_database_latency` Calculate the average of
the queries and classify using database
5. `opengemini_client_write_total` Count of opengemini writes
6. `opengemini_client_write_database_total` Count of opengemini writes
and classify using database
7. `opengemini_client_write_latency` Calculate the average of the writes
8. `opengemini_client_write_database_latency` Calculate the average of
the writes and classify using database

**Impact**
This change does not affect existing functionality; it solely adds
monitoring metrics.
Ensure that the Prometheus server configuration in the deployment
environment is set up to scrape these new metrics.
Prometheus dependency was introduced for this project, and the project
dependency is no longer pure.

Signed-off-by: Young Xu <[email protected]>
  • Loading branch information
xuthus5 authored Jun 26, 2024
1 parent a99a6e5 commit e61e99b
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 5 deletions.
13 changes: 12 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@ module github.com/openGemini/opengemini-client-go

go 1.19

require github.com/stretchr/testify v1.8.4
require (
github.com/prometheus/client_golang v1.19.1
github.com/stretchr/testify v1.9.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
golang.org/x/sys v0.17.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
28 changes: 25 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
2 changes: 2 additions & 0 deletions opengemini/client_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type client struct {
cli *http.Client
prevIdx atomic.Int32
dataChan sync.Map
metrics *metrics

cancel context.CancelFunc
}
Expand Down Expand Up @@ -62,6 +63,7 @@ func newClient(c *Config) (Client, error) {
config: c,
endpoints: buildEndpoints(c.Addresses, c.TlsEnabled),
cli: newHttpClient(*c),
metrics: newMetricsProvider(),
cancel: cancel,
}
client.prevIdx.Store(-1)
Expand Down
118 changes: 118 additions & 0 deletions opengemini/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package opengemini

import "github.com/prometheus/client_golang/prometheus"

const (
MetricsNamespace = "opengemini"
MetricsSubsystem = "client"
)

var _ prometheus.Collector = (*metrics)(nil)

// metrics custom indicators, implementing the prometheus.Collector interface
type metrics struct {
// queryCounter count all queries
queryCounter prometheus.Counter
// writeCounter count all write requests
writeCounter prometheus.Counter
// queryLatency calculate the average of the queries, unit milliseconds
queryLatency prometheus.Summary
// writeLatency calculate the average of the writes, unit milliseconds
writeLatency prometheus.Summary
// queryDatabaseCounter Count queries and classify using measurement
queryDatabaseCounter *prometheus.CounterVec
// writeDatabaseCounter count write requests and classify using measurement
writeDatabaseCounter *prometheus.CounterVec
// queryDatabaseLatency calculate the average of the queries for database, unit milliseconds
queryDatabaseLatency *prometheus.SummaryVec
// writeDatabaseLatency calculate the average of the writes for database, unit milliseconds
writeDatabaseLatency *prometheus.SummaryVec
}

func (m *metrics) Describe(chan<- *prometheus.Desc) {}

func (m *metrics) Collect(ch chan<- prometheus.Metric) {
ch <- m.queryCounter
ch <- m.writeCounter
ch <- m.queryLatency
ch <- m.writeLatency
m.queryDatabaseCounter.Collect(ch)
m.writeDatabaseCounter.Collect(ch)
m.queryDatabaseLatency.Collect(ch)
m.writeDatabaseLatency.Collect(ch)
}

// newMetricsProvider returns metrics registered to registerer.
func newMetricsProvider() *metrics {
constLabels := map[string]string{
"client": "go", // distinguish from other language client
}
constQuantiles := map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
labelNames := []string{"database"}

m := &metrics{
queryCounter: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystem,
Name: "query_total",
Help: "Count of opengemini queries",
ConstLabels: constLabels,
}),
writeCounter: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystem,
Name: "write_total",
Help: "Count of opengemini writes",
ConstLabels: constLabels,
}),
queryLatency: prometheus.NewSummary(prometheus.SummaryOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystem,
Name: "query_latency",
Help: "Calculate the average of the queries",
ConstLabels: constLabels,
Objectives: constQuantiles,
}),
writeLatency: prometheus.NewSummary(prometheus.SummaryOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystem,
Name: "write_latency",
Help: "Calculate the average of the writes",
ConstLabels: constLabels,
Objectives: constQuantiles,
}),
queryDatabaseCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystem,
Name: "query_database_total",
Help: "Count of opengemini queries and classify using measurement",
ConstLabels: constLabels,
}, labelNames),
writeDatabaseCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystem,
Name: "write_database_total",
Help: "Count of opengemini writes and classify using measurement",
ConstLabels: constLabels,
}, labelNames),
queryDatabaseLatency: prometheus.NewSummaryVec(prometheus.SummaryOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystem,
Name: "query_database_latency",
Help: "Calculate the average of the queries for database",
ConstLabels: constLabels,
Objectives: constQuantiles,
}, labelNames),
writeDatabaseLatency: prometheus.NewSummaryVec(prometheus.SummaryOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystem,
Name: "write_database_latency",
Help: "Calculate the average of the writes for database",
ConstLabels: constLabels,
Objectives: constQuantiles,
}, labelNames),
}

prometheus.MustRegister(m)
return m
}
11 changes: 11 additions & 0 deletions opengemini/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"io"
"net/http"
"time"
)

type Query struct {
Expand All @@ -30,7 +31,17 @@ func (c *client) Query(q Query) (*QueryResult, error) {
req.queryValues.Add("rp", q.RetentionPolicy)
req.queryValues.Add("epoch", q.Precision.Epoch())

// metric
c.metrics.queryCounter.Add(1)
c.metrics.queryDatabaseCounter.WithLabelValues(q.Database).Add(1)
startAt := time.Now()

resp, err := c.executeHttpGet(UrlQuery, req)

cost := float64(time.Since(startAt).Milliseconds())
c.metrics.queryLatency.Observe(cost)
c.metrics.queryDatabaseLatency.WithLabelValues(q.Database).Observe(cost)

if err != nil {
return nil, errors.New("query request failed, error: " + err.Error())
}
Expand Down
13 changes: 12 additions & 1 deletion opengemini/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,16 @@ func (c *client) innerWrite(database string, buffer *bytes.Buffer) (*http.Respon
req.header.Set("Accept-Encoding", "gzip")
}
req.queryValues.Add("db", database)
return c.executeHttpPost(UrlWrite, req)

c.metrics.writeCounter.Add(1)
c.metrics.writeDatabaseCounter.WithLabelValues(database).Add(1)
startAt := time.Now()

response, err := c.executeHttpPost(UrlWrite, req)

cost := float64(time.Since(startAt).Milliseconds())
c.metrics.writeLatency.Observe(cost)
c.metrics.writeDatabaseLatency.WithLabelValues(database).Observe(cost)

return response, err
}

0 comments on commit e61e99b

Please sign in to comment.