[#502] Add Dropped logs (by sampling) metric #557

Open
pogpp wants to merge 1 commit from pogpp/frostfs-s3-gw:feature/502_sampling_metric into master
6 changed files with 87 additions and 0 deletions

View file

@ -163,6 +163,7 @@ func (a *App) init(ctx context.Context) {
a.initPolicyStorage(ctx) a.initPolicyStorage(ctx)
a.initAPI(ctx) a.initAPI(ctx)
a.initMetrics() a.initMetrics()
a.initLogger()
a.initServers(ctx) a.initServers(ctx)
a.initTracing(ctx) a.initTracing(ctx)
} }
@ -523,6 +524,11 @@ func (a *App) initMetrics() {
a.metrics.State().SetHealth(metrics.HealthStatusStarting) a.metrics.State().SetHealth(metrics.HealthStatusStarting)
} }
func (a *App) initLogger() {
coreWithContext := applyZapCoreMiddlewares(a.log.Core(), a.cfg, a.metrics)
Review

I don't understand why do we applying new actually the same middleware that already has been added here

func samplingEnabling(v *viper.Viper, core zapcore.Core) zapcore.Core {

I don't understand why do we applying new actually the same middleware that already has been added here https://git.frostfs.info/pogpp/frostfs-s3-gw/src/commit/99ff86a0d1fa7697d94b21dd8e89d26e1fb48e9e/cmd/s3-gw/app_settings.go#L1173
a.log = zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)))
}
func (a *App) initFrostfsID(ctx context.Context) { func (a *App) initFrostfsID(ctx context.Context) {
cli, err := ffidcontract.New(ctx, ffidcontract.Config{ cli, err := ffidcontract.New(ctx, ffidcontract.Config{
RPCAddress: a.cfg.GetString(cfgRPCEndpoint), RPCAddress: a.cfg.GetString(cfgRPCEndpoint),

View file

@ -18,6 +18,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
internalnet "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/net" internalnet "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/net"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/version" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/version"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
"git.frostfs.info/TrueCloudLab/zapjournald" "git.frostfs.info/TrueCloudLab/zapjournald"
@ -1221,3 +1222,19 @@ LOOP:
} }
return validDomains return validDomains
} }
func applyZapCoreMiddlewares(core zapcore.Core, v *viper.Viper, appMetrics *metrics.AppMetrics) zapcore.Core {
if v.GetBool(cfgLoggerSamplingEnabled) {
core = zapcore.NewSamplerWithOptions(core,
v.GetDuration(cfgLoggerSamplingInterval),
v.GetInt(cfgLoggerSamplingInitial),
v.GetInt(cfgLoggerSamplingThereafter),
zapcore.SamplerHook(func(_ zapcore.Entry, dec zapcore.SamplingDecision) {
if dec&zapcore.LogDropped > 0 {
appMetrics.DroppedLogsInc()
}
}))
}
return core
}

View file

@ -42,6 +42,10 @@ func NewAppMetrics(cfg AppMetricsConfig) *AppMetrics {
} }
} }
func (m *AppMetrics) DroppedLogsInc() {
m.gate.Logs.DroppedLogsInc()

Please, use approach as for UsersAPIStats or APIStatMetrics or StateMetrics

Please, use approach as for `UsersAPIStats` or `APIStatMetrics` or `StateMetrics`
Outdated
Review

Now it's similar to StateMetrics

Now it's similar to `StateMetrics`

I'm not sure if this

func (m *AppMetrics) DroppedLogsInc() {
m.gate.Logs.DroppedLogsInc()
}


is similar to

func (m *AppMetrics) State() *StateMetrics {
if !m.isEnabled() {
return nil
}
return m.gate.State
}

I'm not sure if this https://git.frostfs.info/pogpp/frostfs-s3-gw/src/commit/99ff86a0d1fa7697d94b21dd8e89d26e1fb48e9e/metrics/app.go#L45-L47 is similar to https://git.frostfs.info/pogpp/frostfs-s3-gw/src/commit/99ff86a0d1fa7697d94b21dd8e89d26e1fb48e9e/metrics/app.go#L59-L65
}
func (m *AppMetrics) SetEnabled(enabled bool) { func (m *AppMetrics) SetEnabled(enabled bool) {
if !enabled { if !enabled {
m.logger.Warn(logs.MetricsAreDisabled) m.logger.Warn(logs.MetricsAreDisabled)

View file

@ -93,6 +93,13 @@ var appMetricsDesc = map[string]map[string]Description{
}, },
}, },
statisticSubsystem: { statisticSubsystem: {
droppedLogs: Description{
Review

I would suggest (if we use statistic subsystem) add new metric to APIStatMetrics

I would suggest (if we use `statistic` subsystem) add new metric to `APIStatMetrics`
Type: dto.MetricType_COUNTER,
Namespace: namespace,
Subsystem: statisticSubsystem,
Name: droppedLogs,
Help: "Dropped logs (by sampling) count",
},
requestsSecondsMetric: Description{ requestsSecondsMetric: Description{
Type: dto.MetricType_HISTOGRAM, Type: dto.MetricType_HISTOGRAM,
Namespace: namespace, Namespace: namespace,
@ -252,3 +259,12 @@ func mustNewHistogramVec(description Description, buckets []float64) *prometheus
description.VariableLabels, description.VariableLabels,
) )
} }
func mustNewCounter(description Description) prometheus.Counter {
if description.Type != dto.MetricType_COUNTER {
panic("invalid metric type")
}
return prometheus.NewCounter(
prometheus.CounterOpts(newOpts(description)),
)
}

View file

@ -28,6 +28,7 @@ type GateMetrics struct {
Stats *APIStatMetrics Stats *APIStatMetrics
HTTPServer *httpServerMetrics HTTPServer *httpServerMetrics
TreePool *treePoolMetricsCollector TreePool *treePoolMetricsCollector
Logs *logsMetric
} }
func NewGateMetrics(scraper StatisticScraper, treeScraper TreePoolStatistic, registry prometheus.Registerer) *GateMetrics { func NewGateMetrics(scraper StatisticScraper, treeScraper TreePoolStatistic, registry prometheus.Registerer) *GateMetrics {
@ -49,6 +50,9 @@ func NewGateMetrics(scraper StatisticScraper, treeScraper TreePoolStatistic, reg
treePoolMetric := newTreePoolMetricsCollector(treeScraper) treePoolMetric := newTreePoolMetricsCollector(treeScraper)
registry.MustRegister(treePoolMetric) registry.MustRegister(treePoolMetric)
logsMetrics := newLogsMetrics()
registry.MustRegister(logsMetrics)
return &GateMetrics{ return &GateMetrics{
registry: registry, registry: registry,
State: stateMetric, State: stateMetric,
@ -57,6 +61,7 @@ func NewGateMetrics(scraper StatisticScraper, treeScraper TreePoolStatistic, reg
Stats: statsMetric, Stats: statsMetric,
HTTPServer: serverMetric, HTTPServer: serverMetric,
TreePool: treePoolMetric, TreePool: treePoolMetric,
Logs: logsMetrics,
} }
} }
@ -66,6 +71,7 @@ func (g *GateMetrics) Unregister() {
g.Billing.Unregister() g.Billing.Unregister()
g.registry.Unregister(g.Stats) g.registry.Unregister(g.Stats)
g.registry.Unregister(g.HTTPServer) g.registry.Unregister(g.HTTPServer)
g.registry.Unregister(g.Logs)
} }
func (g *GateMetrics) Handler() http.Handler { func (g *GateMetrics) Handler() http.Handler {

38
metrics/logs.go Normal file
View file

@ -0,0 +1,38 @@
package metrics
import "github.com/prometheus/client_golang/prometheus"
const (
droppedLogs = "dropped_logs"
)
type logsMetric struct {
droppedLogs prometheus.Counter
}
func newLogsMetrics() *logsMetric {
return &logsMetric{
droppedLogs: mustNewCounter(appMetricsDesc[statisticSubsystem][droppedLogs]),
}
}
func (m *logsMetric) DroppedLogsInc() {
if m == nil {
return
}
m.droppedLogs.Inc()
}
func (m *logsMetric) Describe(descs chan<- *prometheus.Desc) {
if m == nil {
return
}
m.droppedLogs.Describe(descs)
}
func (m *logsMetric) Collect(metrics chan<- prometheus.Metric) {
if m == nil {
return
}
m.droppedLogs.Collect(metrics)
}