| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
- // SPDX-License-Identifier: Apache-2.0
- package metric // import "miniflux.app/v2/internal/metric"
- import (
- "log/slog"
- "time"
- "miniflux.app/v2/internal/storage"
- "github.com/prometheus/client_golang/prometheus"
- )
- // Prometheus Metrics.
- var (
- BackgroundFeedRefreshDuration = prometheus.NewHistogramVec(
- prometheus.HistogramOpts{
- Namespace: "miniflux",
- Name: "background_feed_refresh_duration",
- Help: "Processing time to refresh feeds from the background workers",
- Buckets: prometheus.LinearBuckets(1, 2, 15),
- },
- []string{"status"},
- )
- ScraperRequestDuration = prometheus.NewHistogramVec(
- prometheus.HistogramOpts{
- Namespace: "miniflux",
- Name: "scraper_request_duration",
- Help: "Web scraper request duration",
- Buckets: prometheus.LinearBuckets(1, 2, 25),
- },
- []string{"status"},
- )
- ArchiveEntriesDuration = prometheus.NewHistogramVec(
- prometheus.HistogramOpts{
- Namespace: "miniflux",
- Name: "archive_entries_duration",
- Help: "Archive entries duration",
- Buckets: prometheus.LinearBuckets(1, 2, 30),
- },
- []string{"status"},
- )
- usersGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "users",
- Help: "Number of users",
- },
- )
- feedsGauge = prometheus.NewGaugeVec(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "feeds",
- Help: "Number of feeds by status",
- },
- []string{"status"},
- )
- brokenFeedsGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "broken_feeds",
- Help: "Number of broken feeds",
- },
- )
- entriesGauge = prometheus.NewGaugeVec(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "entries",
- Help: "Number of entries by status",
- },
- []string{"status"},
- )
- dbOpenConnectionsGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "db_open_connections",
- Help: "The number of established connections both in use and idle",
- },
- )
- dbConnectionsInUseGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "db_connections_in_use",
- Help: "The number of connections currently in use",
- },
- )
- dbConnectionsIdleGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "db_connections_idle",
- Help: "The number of idle connections",
- },
- )
- dbConnectionsWaitCountGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "db_connections_wait_count",
- Help: "The total number of connections waited for",
- },
- )
- dbConnectionsMaxIdleClosedGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "db_connections_max_idle_closed",
- Help: "The total number of connections closed due to SetMaxIdleConns",
- },
- )
- dbConnectionsMaxIdleTimeClosedGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "db_connections_max_idle_time_closed",
- Help: "The total number of connections closed due to SetConnMaxIdleTime",
- },
- )
- dbConnectionsMaxLifetimeClosedGauge = prometheus.NewGauge(
- prometheus.GaugeOpts{
- Namespace: "miniflux",
- Name: "db_connections_max_lifetime_closed",
- Help: "The total number of connections closed due to SetConnMaxLifetime",
- },
- )
- )
- // collector represents a metric collector.
- type collector struct {
- store *storage.Storage
- refreshInterval time.Duration
- }
- // NewCollector initializes a new metric collector.
- func NewCollector(store *storage.Storage, refreshInterval time.Duration) *collector {
- prometheus.MustRegister(BackgroundFeedRefreshDuration)
- prometheus.MustRegister(ScraperRequestDuration)
- prometheus.MustRegister(ArchiveEntriesDuration)
- prometheus.MustRegister(usersGauge)
- prometheus.MustRegister(feedsGauge)
- prometheus.MustRegister(brokenFeedsGauge)
- prometheus.MustRegister(entriesGauge)
- prometheus.MustRegister(dbOpenConnectionsGauge)
- prometheus.MustRegister(dbConnectionsInUseGauge)
- prometheus.MustRegister(dbConnectionsIdleGauge)
- prometheus.MustRegister(dbConnectionsWaitCountGauge)
- prometheus.MustRegister(dbConnectionsMaxIdleClosedGauge)
- prometheus.MustRegister(dbConnectionsMaxIdleTimeClosedGauge)
- prometheus.MustRegister(dbConnectionsMaxLifetimeClosedGauge)
- return &collector{store, refreshInterval}
- }
- // GatherStorageMetrics polls the database to fetch metrics.
- func (c *collector) GatherStorageMetrics() {
- for range time.Tick(c.refreshInterval) {
- slog.Debug("Collecting metrics from the database")
- usersGauge.Set(float64(c.store.CountUsers()))
- brokenFeedsGauge.Set(float64(c.store.CountAllFeedsWithErrors()))
- feedsCount := c.store.CountAllFeeds()
- for status, count := range feedsCount {
- feedsGauge.WithLabelValues(status).Set(float64(count))
- }
- entriesCount := c.store.CountAllEntries()
- for status, count := range entriesCount {
- entriesGauge.WithLabelValues(status).Set(float64(count))
- }
- dbStats := c.store.DBStats()
- dbOpenConnectionsGauge.Set(float64(dbStats.OpenConnections))
- dbConnectionsInUseGauge.Set(float64(dbStats.InUse))
- dbConnectionsIdleGauge.Set(float64(dbStats.Idle))
- dbConnectionsWaitCountGauge.Set(float64(dbStats.WaitCount))
- dbConnectionsMaxIdleClosedGauge.Set(float64(dbStats.MaxIdleClosed))
- dbConnectionsMaxIdleTimeClosedGauge.Set(float64(dbStats.MaxIdleTimeClosed))
- dbConnectionsMaxLifetimeClosedGauge.Set(float64(dbStats.MaxLifetimeClosed))
- }
- }
|