From b5eb8d185d98e281eac53923d383ae4e9441fb68 Mon Sep 17 00:00:00 2001
From: Pavel Pogodaev
Date: Wed, 20 Nov 2024 15:05:04 +0300
Subject: [PATCH] [#502] Add Dropped logs (by sampling) metric
Signed-off-by: Pavel Pogodaev
---
cmd/s3-gw/app.go | 6 ++++++
cmd/s3-gw/app_settings.go | 17 +++++++++++++++++
metrics/app.go | 4 ++++
metrics/desc.go | 16 ++++++++++++++++
metrics/gate.go | 6 ++++++
metrics/logs.go | 32 ++++++++++++++++++++++++++++++++
6 files changed, 81 insertions(+)
create mode 100644 metrics/logs.go
diff --git a/cmd/s3-gw/app.go b/cmd/s3-gw/app.go
index 1ac2b30..cfddda0 100644
--- a/cmd/s3-gw/app.go
+++ b/cmd/s3-gw/app.go
@@ -163,6 +163,7 @@ func (a *App) init(ctx context.Context) {
a.initPolicyStorage(ctx)
a.initAPI(ctx)
a.initMetrics()
+ a.initLogger()
a.initServers(ctx)
a.initTracing(ctx)
}
@@ -523,6 +524,11 @@ func (a *App) initMetrics() {
a.metrics.State().SetHealth(metrics.HealthStatusStarting)
}
+func (a *App) initLogger() {
+ coreWithContext := applyZapCoreMiddlewares(a.log.Core(), a.cfg, a.metrics)
+ a.log = zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)))
+}
+
func (a *App) initFrostfsID(ctx context.Context) {
cli, err := ffidcontract.New(ctx, ffidcontract.Config{
RPCAddress: a.cfg.GetString(cfgRPCEndpoint),
diff --git a/cmd/s3-gw/app_settings.go b/cmd/s3-gw/app_settings.go
index 691e231..be7f95d 100644
--- a/cmd/s3-gw/app_settings.go
+++ b/cmd/s3-gw/app_settings.go
@@ -18,6 +18,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
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/metrics"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
"git.frostfs.info/TrueCloudLab/zapjournald"
@@ -1221,3 +1222,19 @@ LOOP:
}
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
+}
diff --git a/metrics/app.go b/metrics/app.go
index 1a2ef07..363ac8a 100644
--- a/metrics/app.go
+++ b/metrics/app.go
@@ -42,6 +42,10 @@ func NewAppMetrics(cfg AppMetricsConfig) *AppMetrics {
}
}
+func (m *AppMetrics) DroppedLogsInc() {
+ m.gate.Logs.DroppedLogsInc()
+}
+
func (m *AppMetrics) SetEnabled(enabled bool) {
if !enabled {
m.logger.Warn(logs.MetricsAreDisabled)
diff --git a/metrics/desc.go b/metrics/desc.go
index 6affeef..e3827ec 100644
--- a/metrics/desc.go
+++ b/metrics/desc.go
@@ -93,6 +93,13 @@ var appMetricsDesc = map[string]map[string]Description{
},
},
statisticSubsystem: {
+ droppedLogs: Description{
+ Type: dto.MetricType_COUNTER,
+ Namespace: namespace,
+ Subsystem: statisticSubsystem,
+ Name: droppedLogs,
+ Help: "Dropped logs (by sampling) count",
+ },
requestsSecondsMetric: Description{
Type: dto.MetricType_HISTOGRAM,
Namespace: namespace,
@@ -252,3 +259,12 @@ func mustNewHistogramVec(description Description, buckets []float64) *prometheus
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)),
+ )
+}
diff --git a/metrics/gate.go b/metrics/gate.go
index 02d608b..4adea51 100644
--- a/metrics/gate.go
+++ b/metrics/gate.go
@@ -28,6 +28,7 @@ type GateMetrics struct {
Stats *APIStatMetrics
HTTPServer *httpServerMetrics
TreePool *treePoolMetricsCollector
+ Logs *logsMetric
}
func NewGateMetrics(scraper StatisticScraper, treeScraper TreePoolStatistic, registry prometheus.Registerer) *GateMetrics {
@@ -49,6 +50,9 @@ func NewGateMetrics(scraper StatisticScraper, treeScraper TreePoolStatistic, reg
treePoolMetric := newTreePoolMetricsCollector(treeScraper)
registry.MustRegister(treePoolMetric)
+ logsMetrics := newLogsMetrics()
+ registry.MustRegister(logsMetrics)
+
return &GateMetrics{
registry: registry,
State: stateMetric,
@@ -57,6 +61,7 @@ func NewGateMetrics(scraper StatisticScraper, treeScraper TreePoolStatistic, reg
Stats: statsMetric,
HTTPServer: serverMetric,
TreePool: treePoolMetric,
+ Logs: logsMetrics,
}
}
@@ -66,6 +71,7 @@ func (g *GateMetrics) Unregister() {
g.Billing.Unregister()
g.registry.Unregister(g.Stats)
g.registry.Unregister(g.HTTPServer)
+ g.registry.Unregister(g.Logs)
}
func (g *GateMetrics) Handler() http.Handler {
diff --git a/metrics/logs.go b/metrics/logs.go
new file mode 100644
index 0000000..662d2fc
--- /dev/null
+++ b/metrics/logs.go
@@ -0,0 +1,32 @@
+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() {
+ m.droppedLogs.Inc()
+}
+
+func (m *logsMetric) Describe(descs chan<- *prometheus.Desc) {
+ m.droppedLogs.Describe(descs)
+}
+
+func (m *logsMetric) Collect(metrics chan<- prometheus.Metric) {
+ if m == nil {
+ return
+ }
+ m.droppedLogs.Collect(metrics)
+}