Skip to content

Commit

Permalink
feat(server/v2): wire telemetry
Browse files Browse the repository at this point in the history
  • Loading branch information
julienrbrt committed Sep 16, 2024
1 parent c0eced8 commit d8b1c86
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 33 deletions.
5 changes: 4 additions & 1 deletion server/v2/api/grpcgateway/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import (
serverv2 "cosmossdk.io/server/v2"
)

var _ serverv2.ServerComponent[transaction.Tx] = (*GRPCGatewayServer[transaction.Tx])(nil)
var (
_ serverv2.ServerComponent[transaction.Tx] = (*GRPCGatewayServer[transaction.Tx])(nil)
_ serverv2.HasConfig = (*GRPCGatewayServer[transaction.Tx])(nil)
)

const (
ServerName = "grpc-gateway"
Expand Down
15 changes: 15 additions & 0 deletions server/v2/api/telemetry/config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
package telemetry

func DefaultConfig() *Config {
return &Config{
ServiceName: "",
Enabled: true,
EnableHostname: false,
EnableHostnameLabel: false,
EnableServiceLabel: false,
PrometheusRetentionTime: 0,
GlobalLabels: nil,
MetricsSink: "",
StatsdAddr: "",
DatadogHostname: "",
}
}

type Config struct {
// Prefixed with keys to separate services
ServiceName string `mapstructure:"service-name" toml:"service-name" comment:"Prefixed with keys to separate services."`
Expand Down
4 changes: 2 additions & 2 deletions server/v2/api/telemetry/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type GatherResponse struct {
}

// New creates a new instance of Metrics
func New(cfg Config) (_ *Metrics, rerr error) {
func NewMetrics(cfg *Config) (*Metrics, error) {
if !cfg.Enabled {
return nil, nil
}
Expand Down Expand Up @@ -89,7 +89,7 @@ func New(cfg Config) (_ *Metrics, rerr error) {
sink = memSink
inMemSig := metrics.DefaultInmemSignal(memSink)
defer func() {
if rerr != nil {
if err != nil {
inMemSig.Stop()
}
}()
Expand Down
48 changes: 48 additions & 0 deletions server/v2/api/telemetry/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package telemetry

import (
"encoding/json"
"fmt"
"net/http"
"strings"

"github.com/gorilla/mux"
)

// RegisterMetrics registers the metrics handler to the provided router.
func (s TelemetryServer[T]) RegisterMetrics(r mux.Router) (*Metrics, error) {
m, err := NewMetrics(s.config)
if err != nil {
return nil, err
}

metricsHandler := func(w http.ResponseWriter, r *http.Request) {
format := strings.TrimSpace(r.FormValue("format"))

gr, err := m.Gather(format)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
bz, err := json.Marshal(errorResponse{Code: 400, Error: fmt.Sprintf("failed to gather metrics: %s", err)})
if err != nil {
return
}
_, _ = w.Write(bz)

return
}

w.Header().Set("Content-Type", gr.ContentType)
_, _ = w.Write(gr.Metrics)
}

r.HandleFunc("/metrics", metricsHandler).Methods("GET")

return m, nil
}

// errorResponse defines the attributes of a JSON error response.
type errorResponse struct {
Code int `json:"code,omitempty"`
Error string `json:"error"`
}
75 changes: 45 additions & 30 deletions server/v2/api/telemetry/server.go
Original file line number Diff line number Diff line change
@@ -1,47 +1,62 @@
package telemetry

import (
"encoding/json"
"context"
"fmt"
"net/http"
"strings"

"github.com/gorilla/mux"
"cosmossdk.io/core/transaction"
"cosmossdk.io/log"
serverv2 "cosmossdk.io/server/v2"
)

func RegisterMetrics(r mux.Router, cfg Config) (*Metrics, error) {
m, err := New(cfg)
if err != nil {
return nil, err
}
var (
_ serverv2.ServerComponent[transaction.Tx] = (*TelemetryServer[transaction.Tx])(nil)
_ serverv2.HasConfig = (*TelemetryServer[transaction.Tx])(nil)
)

metricsHandler := func(w http.ResponseWriter, r *http.Request) {
format := strings.TrimSpace(r.FormValue("format"))
const ServerName = "telemetry"

gr, err := m.Gather(format)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
bz, err := json.Marshal(errorResponse{Code: 400, Error: fmt.Sprintf("failed to gather metrics: %s", err)})
if err != nil {
return
}
_, _ = w.Write(bz)
type TelemetryServer[T transaction.Tx] struct {
config *Config
logger log.Logger
}

return
}
// New creates a new telemtry server.
func New[T transaction.Tx]() *TelemetryServer[T] {
return &TelemetryServer[T]{}
}

// Name returns the server name.
func (s *TelemetryServer[T]) Name() string {
return ServerName
}

w.Header().Set("Content-Type", gr.ContentType)
_, _ = w.Write(gr.Metrics)
func (s *TelemetryServer[T]) Config() any {
if s.config == nil || s.config == (&Config{}) {
return DefaultConfig()
}

r.HandleFunc("/metrics", metricsHandler).Methods("GET")
return s.config
}

// Init implements serverv2.ServerComponent.
func (s *TelemetryServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.Logger) error {
serverCfg := s.Config().(*Config)
if len(cfg) > 0 {
if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &serverCfg); err != nil {
return fmt.Errorf("failed to unmarshal config: %w", err)
}
}
s.config = serverCfg
s.logger = logger

return nil
}

return m, nil
func (s *TelemetryServer[T]) Start(context.Context) error {
return nil
}

// errorResponse defines the attributes of a JSON error response.
type errorResponse struct {
Code int `json:"code,omitempty"`
Error string `json:"error"`
func (s *TelemetryServer[T]) Stop(context.Context) error {
return nil
}
2 changes: 2 additions & 0 deletions simapp/v2/simdv2/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
runtimev2 "cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2"
"cosmossdk.io/server/v2/api/grpc"
"cosmossdk.io/server/v2/api/telemetry"
"cosmossdk.io/server/v2/cometbft"
"cosmossdk.io/server/v2/store"
"cosmossdk.io/simapp/v2"
Expand Down Expand Up @@ -77,6 +78,7 @@ func initRootCmd[T transaction.Tx](
cometbft.New(&genericTxDecoder[T]{txConfig}, cometbft.DefaultServerOptions[T]()),
grpc.New[T](),
store.New[T](newApp),
telemetry.New[T](),
); err != nil {
panic(err)
}
Expand Down

0 comments on commit d8b1c86

Please sign in to comment.