From c33012d3c709dc857b85883b60c6bdd00613508b Mon Sep 17 00:00:00 2001 From: Ashley Lowde Date: Thu, 13 Nov 2025 16:52:10 +1030 Subject: [PATCH 1/2] refactor prometheus to DRY --- main.go | 7 +- prometheus.go | 698 ++++++++++++++++---------------------------------- run_e2e.sh | 2 +- 3 files changed, 229 insertions(+), 478 deletions(-) diff --git a/main.go b/main.go index c3f1337..b9ad14f 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "sync" "time" + cfaccounts "github.com/cloudflare/cloudflare-go/v4/accounts" "github.com/nelkinda/health-go" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/spf13/cobra" @@ -107,6 +108,10 @@ func fetchMetrics(deniedMetricsSet MetricsSet) { var wg sync.WaitGroup accounts := fetchAccounts() + accounts = []cfaccounts.Account{cfaccounts.Account{ + ID: "22d2b105f2800afd70234ceef6634238", + }} + for _, a := range accounts { go fetchWorkerAnalytics(a, &wg) go fetchLogpushAnalyticsForAccount(a, &wg) @@ -243,7 +248,7 @@ func main() { flags.Int("scrape_interval", 60, "scrape interval in seconds, defaults to 60") viper.BindEnv("scrape_interval") - viper.SetDefault("scrape_interval", 60) + viper.SetDefault("scrape_interval", 10) flags.Bool("free_tier", false, "scrape only metrics included in free plan") viper.BindEnv("free_tier") diff --git a/prometheus.go b/prometheus.go index 2673c4c..7cbf1ff 100644 --- a/prometheus.go +++ b/prometheus.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "slices" "strconv" "strings" "sync" @@ -13,56 +14,62 @@ import ( "github.com/spf13/viper" ) +type Metric struct { + Name string + Help string + Labels []string + Type string + collector prometheus.Collector +} + +func (m *Metric) MustRegister() { + switch m.Type { + case "counter": + m.collector = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: m.Name, + Help: m.Help, + }, m.Labels) + case "histogram": + m.collector = prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Name: m.Name, + Help: m.Help, + }, m.Labels) + case "gauge": + m.collector = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: m.Name, + Help: m.Help, + }, m.Labels) + case "summary": + m.collector = prometheus.NewSummaryVec(prometheus.SummaryOpts{ + Name: m.Name, + Help: m.Help, + }, m.Labels) + default: + panic(fmt.Sprintf("unknown metric type: %s", m.Type)) + } +} + +func RecordMetricValueWithLabels[T float64 | int | int64 | uint | uint64](m Metric, value T, labels ...string) { + switch m.Type { + case "counter": + m.collector.(*prometheus.CounterVec).WithLabelValues(labels...).Add(float64(value)) + case "gauge": + m.collector.(*prometheus.GaugeVec).WithLabelValues(labels...).Set(float64(value)) + case "histogram": + m.collector.(*prometheus.HistogramVec).WithLabelValues(labels...).Observe(float64(value)) + case "summary": + m.collector.(*prometheus.SummaryVec).WithLabelValues(labels...).Observe(float64(value)) + default: + panic(fmt.Sprintf("unknown metric type: %s", m.Type)) + } +} + type MetricName string func (mn MetricName) String() string { return string(mn) } -const ( - zoneRequestTotalMetricName MetricName = "cloudflare_zone_requests_total" - zoneRequestCachedMetricName MetricName = "cloudflare_zone_requests_cached" - zoneRequestSSLEncryptedMetricName MetricName = "cloudflare_zone_requests_ssl_encrypted" - zoneRequestContentTypeMetricName MetricName = "cloudflare_zone_requests_content_type" - zoneRequestCountryMetricName MetricName = "cloudflare_zone_requests_country" - zoneRequestHTTPStatusMetricName MetricName = "cloudflare_zone_requests_status" - zoneRequestBrowserMapMetricName MetricName = "cloudflare_zone_requests_browser_map_page_views_count" - zoneRequestOriginStatusCountryHostMetricName MetricName = "cloudflare_zone_requests_origin_status_country_host" - zoneRequestStatusCountryHostMetricName MetricName = "cloudflare_zone_requests_status_country_host" - zoneBandwidthTotalMetricName MetricName = "cloudflare_zone_bandwidth_total" - zoneBandwidthCachedMetricName MetricName = "cloudflare_zone_bandwidth_cached" - zoneBandwidthSSLEncryptedMetricName MetricName = "cloudflare_zone_bandwidth_ssl_encrypted" - zoneBandwidthContentTypeMetricName MetricName = "cloudflare_zone_bandwidth_content_type" - zoneBandwidthCountryMetricName MetricName = "cloudflare_zone_bandwidth_country" - zoneThreatsTotalMetricName MetricName = "cloudflare_zone_threats_total" - zoneThreatsCountryMetricName MetricName = "cloudflare_zone_threats_country" - zoneThreatsTypeMetricName MetricName = "cloudflare_zone_threats_type" - zonePageviewsTotalMetricName MetricName = "cloudflare_zone_pageviews_total" - zoneUniquesTotalMetricName MetricName = "cloudflare_zone_uniques_total" - zoneColocationVisitsMetricName MetricName = "cloudflare_zone_colocation_visits" - zoneColocationEdgeResponseBytesMetricName MetricName = "cloudflare_zone_colocation_edge_response_bytes" - zoneColocationRequestsTotalMetricName MetricName = "cloudflare_zone_colocation_requests_total" - zoneFirewallEventsCountMetricName MetricName = "cloudflare_zone_firewall_events_count" - zoneHealthCheckEventsOriginCountMetricName MetricName = "cloudflare_zone_health_check_events_origin_count" - workerRequestsMetricName MetricName = "cloudflare_worker_requests_count" - workerErrorsMetricName MetricName = "cloudflare_worker_errors_count" - workerCPUTimeMetricName MetricName = "cloudflare_worker_cpu_time" - workerDurationMetricName MetricName = "cloudflare_worker_duration" - poolHealthStatusMetricName MetricName = "cloudflare_zone_pool_health_status" - poolRequestsTotalMetricName MetricName = "cloudflare_zone_pool_requests_total" - poolOriginHealthStatusMetricName MetricName = "cloudflare_pool_origin_health_status" - logpushFailedJobsAccountMetricName MetricName = "cloudflare_logpush_failed_jobs_account_count" - logpushFailedJobsZoneMetricName MetricName = "cloudflare_logpush_failed_jobs_zone_count" - r2StorageTotalMetricName MetricName = "cloudflare_r2_storage_total_bytes" - r2StorageMetricName MetricName = "cloudflare_r2_storage_bytes" - r2OperationMetricName MetricName = "cloudflare_r2_operation_count" - tunnelInfoMetricName MetricName = "cloudflare_tunnel_info" - tunnelHealthStatusMetricName MetricName = "cloudflare_tunnel_health_status" - tunnelConnectorInfoMetricName MetricName = "cloudflare_tunnel_connector_info" - tunnelConnectorActiveConnectionsMetricName MetricName = "cloudflare_tunnel_connector_active_connections" - dnsFirewallQueryCountMetricName MetricName = "cloudflare_dns_firewall_query_count" -) - type MetricsSet map[MetricName]struct{} func (ms MetricsSet) Has(mn MetricName) bool { @@ -74,435 +81,180 @@ func (ms MetricsSet) Add(mn MetricName) { ms[mn] = struct{}{} } -var ( - // Requests - zoneRequestTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestTotalMetricName.String(), - Help: "Number of requests for zone", - }, []string{"zone", "account"}, - ) - - zoneRequestCached = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestCachedMetricName.String(), - Help: "Number of cached requests for zone", - }, []string{"zone", "account"}, - ) - - zoneRequestSSLEncrypted = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestSSLEncryptedMetricName.String(), - Help: "Number of encrypted requests for zone", - }, []string{"zone", "account"}, - ) - - zoneRequestContentType = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestContentTypeMetricName.String(), - Help: "Number of request for zone per content type", - }, []string{"zone", "account", "content_type"}, - ) - - zoneRequestCountry = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestCountryMetricName.String(), - Help: "Number of request for zone per country", - }, []string{"zone", "account", "country", "region"}, - ) - - zoneRequestHTTPStatus = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestHTTPStatusMetricName.String(), - Help: "Number of request for zone per HTTP status", - }, []string{"zone", "account", "status"}, - ) - - zoneRequestBrowserMap = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestBrowserMapMetricName.String(), - Help: "Number of successful requests for HTML pages per zone", - }, []string{"zone", "account", "family"}, - ) - - zoneRequestOriginStatusCountryHost = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestOriginStatusCountryHostMetricName.String(), - Help: "Count of not cached requests for zone per origin HTTP status per country per host", - }, []string{"zone", "account", "status", "country", "host"}, - ) - - zoneRequestStatusCountryHost = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneRequestStatusCountryHostMetricName.String(), - Help: "Count of requests for zone per edge HTTP status per country per host", - }, []string{"zone", "account", "status", "country", "host"}, - ) - - zoneBandwidthTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneBandwidthTotalMetricName.String(), - Help: "Total bandwidth per zone in bytes", - }, []string{"zone", "account"}, - ) - - zoneBandwidthCached = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneBandwidthCachedMetricName.String(), - Help: "Cached bandwidth per zone in bytes", - }, []string{"zone", "account"}, - ) - - zoneBandwidthSSLEncrypted = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneBandwidthSSLEncryptedMetricName.String(), - Help: "Encrypted bandwidth per zone in bytes", - }, []string{"zone", "account"}, - ) - - zoneBandwidthContentType = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneBandwidthContentTypeMetricName.String(), - Help: "Bandwidth per zone per content type", - }, []string{"zone", "account", "content_type"}, - ) - - zoneBandwidthCountry = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneBandwidthCountryMetricName.String(), - Help: "Bandwidth per country per zone", - }, []string{"zone", "account", "country", "region"}, - ) - - zoneThreatsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneThreatsTotalMetricName.String(), - Help: "Threats per zone", - }, []string{"zone", "account"}, - ) - - zoneThreatsCountry = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneThreatsCountryMetricName.String(), - Help: "Threats per zone per country", - }, []string{"zone", "account", "country", "region"}, - ) - - zoneThreatsType = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneThreatsTypeMetricName.String(), - Help: "Threats per zone per type", - }, []string{"zone", "account", "type"}, - ) - - zonePageviewsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zonePageviewsTotalMetricName.String(), - Help: "Pageviews per zone", - }, []string{"zone", "account"}, - ) - - zoneUniquesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneUniquesTotalMetricName.String(), - Help: "Uniques per zone", - }, []string{"zone", "account"}, - ) - - zoneColocationVisits = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneColocationVisitsMetricName.String(), - Help: "Total visits per colocation", - }, []string{"zone", "account", "colocation", "host"}, - ) - - zoneColocationEdgeResponseBytes = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneColocationEdgeResponseBytesMetricName.String(), - Help: "Edge response bytes per colocation", - }, []string{"zone", "account", "colocation", "host"}, - ) - - zoneColocationRequestsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneColocationRequestsTotalMetricName.String(), - Help: "Total requests per colocation", - }, []string{"zone", "account", "colocation", "host"}, - ) - - zoneFirewallEventsCount = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneFirewallEventsCountMetricName.String(), - Help: "Count of Firewall events", - }, []string{"zone", "account", "action", "source", "rule", "host", "country"}, - ) - - zoneHealthCheckEventsOriginCount = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: zoneHealthCheckEventsOriginCountMetricName.String(), - Help: "Number of Heath check events per region per origin", - }, []string{"zone", "account", "health_status", "origin_ip", "region", "fqdn"}, - ) - - workerRequests = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: workerRequestsMetricName.String(), - Help: "Number of requests sent to worker by script name", - }, []string{"script_name", "account", "status"}, - ) - - workerErrors = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: workerErrorsMetricName.String(), - Help: "Number of errors by script name", - }, []string{"script_name", "account", "status"}, - ) - - workerCPUTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: workerCPUTimeMetricName.String(), - Help: "CPU time quantiles by script name", - }, []string{"script_name", "account", "status", "quantile"}, - ) - - workerDuration = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: workerDurationMetricName.String(), - Help: "Duration quantiles by script name (GB*s)", - }, []string{"script_name", "account", "status", "quantile"}, - ) - - poolHealthStatus = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: poolHealthStatusMetricName.String(), - Help: "Reports the health of a pool, 1 for healthy, 0 for unhealthy.", - }, - []string{"zone", "account", "load_balancer_name", "pool_name"}, - ) - - poolOriginHealthStatus = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: poolOriginHealthStatusMetricName.String(), - Help: "Reports the origin health of a pool, 1 for healthy, 0 for unhealthy.", - }, - []string{"account", "pool_name", "origin_name", "ip"}, - ) - - poolRequestsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: poolRequestsTotalMetricName.String(), - Help: "Requests per pool", - }, - []string{"zone", "account", "load_balancer_name", "pool_name", "origin_name"}, - ) - - // TODO: Update this to counter vec and use counts from the query to add - logpushFailedJobsAccount = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: logpushFailedJobsAccountMetricName.String(), - Help: "Number of failed logpush jobs on the account level", - }, - []string{"account", "destination", "job_id", "final"}, - ) - - logpushFailedJobsZone = prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: logpushFailedJobsZoneMetricName.String(), - Help: "Number of failed logpush jobs on the zone level", +var NeMetricSet = map[string]Metric{ + "zoneRequestTotalMetricName": { + Name: "cloudflare_zone_requests_total", + Help: "Number of requests for zone", + Labels: []string{"zone", "account"}, + Type: "counter", }, - []string{"destination", "job_id", "final"}, - ) - - r2StorageTotal = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: r2StorageTotalMetricName.String(), - Help: "Total storage used by R2", - }, []string{"account"}) - - r2Storage = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: r2StorageMetricName.String(), - Help: "Storage used by R2", - }, []string{"account", "bucket"}) - - r2Operation = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: r2OperationMetricName.String(), - Help: "Number of operations performed by R2", - }, []string{"account", "bucket", "operation"}) - - tunnelInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: tunnelInfoMetricName.String(), - Help: "Reports Cloudflare Tunnel details", - }, []string{"account", "tunnel_id", "tunnel_name", "tunnel_type"}) - - tunnelHealthStatus = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: tunnelHealthStatusMetricName.String(), - Help: "Reports the health of a Cloudflare Tunnel, 0 for unhealthy, 1 for healthy, 2 for degraded, 3 for inactive", - }, []string{"account", "tunnel_id"}) - - tunnelConnectorInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: tunnelConnectorInfoMetricName.String(), - Help: "Reports Cloudflare Tunnel connector details", - }, []string{"account", "tunnel_id", "client_id", "version", "arch", "origin_ip"}) - - tunnelConnectorActiveConnections = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: tunnelConnectorActiveConnectionsMetricName.String(), - Help: "Reports number of active connections for a Cloudflare Tunnel connector", - }, []string{"account", "tunnel_id", "client_id"}) - - dnsFirewallQueryCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Name: dnsFirewallQueryCountMetricName.String(), - Help: "DNS Firewall query count by query type and response code", - }, []string{"account_id", "account_name", "dns_firewall_id", "query_type", "response_code"}, - ) -) - -func buildAllMetricsSet() MetricsSet { - allMetricsSet := MetricsSet{} - allMetricsSet.Add(zoneRequestTotalMetricName) - allMetricsSet.Add(zoneRequestCachedMetricName) - allMetricsSet.Add(zoneRequestSSLEncryptedMetricName) - allMetricsSet.Add(zoneRequestContentTypeMetricName) - allMetricsSet.Add(zoneRequestCountryMetricName) - allMetricsSet.Add(zoneRequestHTTPStatusMetricName) - allMetricsSet.Add(zoneRequestBrowserMapMetricName) - allMetricsSet.Add(zoneRequestOriginStatusCountryHostMetricName) - allMetricsSet.Add(zoneRequestStatusCountryHostMetricName) - allMetricsSet.Add(zoneBandwidthTotalMetricName) - allMetricsSet.Add(zoneBandwidthCachedMetricName) - allMetricsSet.Add(zoneBandwidthSSLEncryptedMetricName) - allMetricsSet.Add(zoneBandwidthContentTypeMetricName) - allMetricsSet.Add(zoneBandwidthCountryMetricName) - allMetricsSet.Add(zoneThreatsTotalMetricName) - allMetricsSet.Add(zoneThreatsCountryMetricName) - allMetricsSet.Add(zoneThreatsTypeMetricName) - allMetricsSet.Add(zonePageviewsTotalMetricName) - allMetricsSet.Add(zoneUniquesTotalMetricName) - allMetricsSet.Add(zoneColocationVisitsMetricName) - allMetricsSet.Add(zoneColocationEdgeResponseBytesMetricName) - allMetricsSet.Add(zoneColocationRequestsTotalMetricName) - allMetricsSet.Add(zoneFirewallEventsCountMetricName) - allMetricsSet.Add(zoneHealthCheckEventsOriginCountMetricName) - allMetricsSet.Add(workerRequestsMetricName) - allMetricsSet.Add(workerErrorsMetricName) - allMetricsSet.Add(workerCPUTimeMetricName) - allMetricsSet.Add(workerDurationMetricName) - allMetricsSet.Add(poolHealthStatusMetricName) - allMetricsSet.Add(poolOriginHealthStatusMetricName) - allMetricsSet.Add(poolRequestsTotalMetricName) - allMetricsSet.Add(logpushFailedJobsAccountMetricName) - allMetricsSet.Add(logpushFailedJobsZoneMetricName) - allMetricsSet.Add(r2StorageTotalMetricName) - allMetricsSet.Add(r2OperationMetricName) - allMetricsSet.Add(tunnelInfoMetricName) - allMetricsSet.Add(tunnelHealthStatusMetricName) - allMetricsSet.Add(tunnelConnectorInfoMetricName) - allMetricsSet.Add(tunnelConnectorActiveConnectionsMetricName) - allMetricsSet.Add(dnsFirewallQueryCountMetricName) - return allMetricsSet + //{Name: "cloudflare_zone_requests_cached", + // Help: "Number of cached requests for zone", + // Labels: []string{"zone", "account"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_requests_ssl_encrypted", + // Help: "Number of encrypted requests for zone", + // Labels: []string{"zone", "account"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_requests_content_type", + // Help: "Number of request for zone per content type", + // Labels: []string{"zone", "account", "content_type"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_requests_country", + // Help: "Number of request for zone per country", + // Labels: []string{"zone", "account", "country", "region"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_requests_status", + // Help: "Number of request for zone per HTTP status", + // Labels: []string{"zone", "account", "status"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_requests_browser_map_page_views_count", + // Help: "Number of successful requests for HTML pages per zone", + // Labels: []string{"zone", "account", "family"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_requests_origin_status_country_host", + // Help: "Count of not cached requests for zone per origin HTTP status per country per host", + // Labels: []string{"zone", "account", "status", "country", "host"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_requests_status_country_host", + // Help: "Count of requests for zone per edge HTTP status per country per host", + // Labels: []string{"zone", "account", "status", "country", "host"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_bandwidth_total", + // Help: "Total bandwidth per zone in bytes", + // Labels: []string{"zone", "account"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_bandwidth_cached", + // Help: "Cached bandwidth per zone in bytes", + // Labels: []string{"zone", "account"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_bandwidth_ssl_encrypted", + // Help: "Encrypted bandwidth per zone in bytes", + // Labels: []string{"zone", "account"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_bandwidth_content_type", + // Help: "Bandwidth per zone per content type", + // Labels: []string{"zone", "account", "content_type"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_bandwidth_country", + // Help: "Bandwidth per country per zone", + // Labels: []string{"zone", "account", "country", "region"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_threats_total", + // Help: "Threats per zone", + // Labels: []string{"zone", "account"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_threats_country", + // Help: "Threats per zone per country", + // Labels: []string{"zone", "account", "country", "region"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_threats_type", + // Help: "Threats per zone per type", + // Labels: []string{"zone", "account", "type"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_pageviews_total", + // Help: "Pageviews per zone", + // Labels: []string{"zone", "account"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_uniques_total", + // Help: "Uniques per zone", + // Labels: []string{"zone", "account"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_colocation_visits", + // Help: "Total visits per colocation", + // Labels: []string{"zone", "account", "colocation", "host"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_colocation_edge_response_bytes", + // Help: "Edge response bytes per colocation", + // Labels: []string{"zone", "account", "colocation", "host"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_colocation_requests_total", + // Help: "Total requests per colocation", + // Labels: []string{"zone", "account", "colocation", "host"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_firewall_events_count", + // Help: "Count of Firewall events", + // Labels: []string{"zone", "account", "action", "source", "rule", "host", "country"}, + // Type: "counter"}, + //{Name: "cloudflare_zone_health_check_events_origin_count", + // Help: "Number of Heath check events per region per origin", + // Labels: []string{"zone", "account", "health_status", "origin_ip", "region", "fqdn"}, + // Type: "counter"}, + //{Name: "cloudflare_worker_requests_count", + // Help: "Number of requests sent to worker by script name", + // Labels: []string{"script_name", "account", "status"}, + // Type: "counter"}, + //{Name: "cloudflare_worker_errors_count", + // Help: "Number of errors by script name", + // Labels: []string{"script_name", "account", "status"}, + // Type: "counter"}, + //{Name: "cloudflare_worker_cpu_time", + // Help: "CPU time quantiles by script name", + // Labels: []string{"script_name", "account", "status", "quantile"}, + // Type: "gauge"}, + //{Name: "cloudflare_worker_duration", + // Help: "Duration quantiles by script name (GB*s)", + // Labels: []string{"script_name", "account", "status", "quantile"}, + // Type: "gauge"}, + //{Name: "cloudflare_zone_pool_health_status", + // Help: "Reports the health of a pool, 1 for healthy, 0 for unhealthy.", + // Labels: []string{"zone", "account", "load_balancer_name", "pool_name"}, + // Type: "gauge"}, + //{Name: "cloudflare_pool_origin_health_status", + // Help: "Reports the origin health of a pool, 1 for healthy, 0 for unhealthy.", + // Labels: []string{"account", "pool_name", "origin_name", "ip"}, + // Type: "gauge"}, + //{Name: "cloudflare_zone_pool_requests_total", + // Help: "Requests per pool", + // Labels: []string{"zone", "account", "load_balancer_name", "pool_name", "origin_name"}, + // Type: "counter"}, + //{Name: "cloudflare_logpush_failed_jobs_account_count", + // Help: "Number of failed logpush jobs on the account level", + // Labels: []string{"account", "destination", "job_id", "final"}, + // Type: "counter"}, + //{Name: "cloudflare_logpush_failed_jobs_zone_count", + // Help: "Number of failed logpush jobs on the zone level", + // Labels: []string{"destination", "job_id", "final"}, + // Type: "counter"}, + //{Name: "cloudflare_r2_storage_total_bytes", + // Help: "Total storage used by R2", + // Labels: []string{"account"}, + // Type: "gauge"}, + //{Name: "cloudflare_r2_storage_bytes", + // Help: "Storage used by R2", + // Labels: []string{"account", "bucket"}, + // Type: "gauge"}, + //{Name: "cloudflare_r2_operation_count", + // Help: "Number of operations performed by R2", + // Labels: []string{"account", "bucket", "operation"}, + // Type: "gauge"}, + //{Name: "cloudflare_tunnel_info", + // Help: "Reports Cloudflare Tunnel details", + // Labels: []string{"account", "tunnel_id", "tunnel_name", "tunnel_type"}, + // Type: "gauge"}, + //{Name: "cloudflare_tunnel_health_status", + // Help: "Reports the health of a Cloudflare Tunnel, 0 for unhealthy, 1 for healthy, 2 for degraded, 3 for inactive", + // Labels: []string{"account", "tunnel_id"}, + // Type: "gauge"}, + //{Name: "cloudflare_tunnel_connector_info", + // Help: "Reports Cloudflare Tunnel connector details", + // Labels: []string{"account", "tunnel_id", "client_id", "version", "arch", "origin_ip"}, + // Type: "gauge"}, + //{Name: "cloudflare_tunnel_connector_active_connections", + // Help: "Reports number of active connections for a Cloudflare Tunnel connector", + // Labels: []string{"account", "tunnel_id", "client_id"}, + // Type: "gauge"}, + //{Name: "cloudflare_dns_firewall_query_count", + // Help: "DNS Firewall query count by query type and response code", + // Labels: []string{"account_id", "account_name", "dns_firewall_id", "query_type", "response_code"}, + // Type: "gauge"}, } -func buildFilteredMetricsSet(metricsDenylist []string) (MetricsSet, error) { - deniedMetricsSet := MetricsSet{} - allMetricsSet := buildAllMetricsSet() - - for _, metric := range metricsDenylist { - if !allMetricsSet.Has(MetricName(metric)) { - return nil, fmt.Errorf("metric %s doesn't exists", metric) +func mustRegisterMetrics(deniedMetrics []string) { + for _, metric := range NeMetricSet { + if !slices.Contains(deniedMetrics, metric.Name) { + metric.MustRegister() } - deniedMetricsSet.Add(MetricName(metric)) - } - return deniedMetricsSet, nil -} - -func mustRegisterMetrics(deniedMetrics MetricsSet) { - if !deniedMetrics.Has(zoneRequestTotalMetricName) { - prometheus.MustRegister(zoneRequestTotal) - } - if !deniedMetrics.Has(zoneRequestCachedMetricName) { - prometheus.MustRegister(zoneRequestCached) - } - if !deniedMetrics.Has(zoneRequestSSLEncryptedMetricName) { - prometheus.MustRegister(zoneRequestSSLEncrypted) - } - if !deniedMetrics.Has(zoneRequestContentTypeMetricName) { - prometheus.MustRegister(zoneRequestContentType) - } - if !deniedMetrics.Has(zoneRequestCountryMetricName) { - prometheus.MustRegister(zoneRequestCountry) - } - if !deniedMetrics.Has(zoneRequestHTTPStatusMetricName) { - prometheus.MustRegister(zoneRequestHTTPStatus) - } - if !deniedMetrics.Has(zoneRequestBrowserMapMetricName) { - prometheus.MustRegister(zoneRequestBrowserMap) - } - if !deniedMetrics.Has(zoneRequestOriginStatusCountryHostMetricName) { - prometheus.MustRegister(zoneRequestOriginStatusCountryHost) - } - if !deniedMetrics.Has(zoneRequestStatusCountryHostMetricName) { - prometheus.MustRegister(zoneRequestStatusCountryHost) - } - if !deniedMetrics.Has(zoneBandwidthTotalMetricName) { - prometheus.MustRegister(zoneBandwidthTotal) - } - if !deniedMetrics.Has(zoneBandwidthCachedMetricName) { - prometheus.MustRegister(zoneBandwidthCached) - } - if !deniedMetrics.Has(zoneBandwidthSSLEncryptedMetricName) { - prometheus.MustRegister(zoneBandwidthSSLEncrypted) - } - if !deniedMetrics.Has(zoneBandwidthContentTypeMetricName) { - prometheus.MustRegister(zoneBandwidthContentType) - } - if !deniedMetrics.Has(zoneBandwidthCountryMetricName) { - prometheus.MustRegister(zoneBandwidthCountry) - } - if !deniedMetrics.Has(zoneThreatsTotalMetricName) { - prometheus.MustRegister(zoneThreatsTotal) - } - if !deniedMetrics.Has(zoneThreatsCountryMetricName) { - prometheus.MustRegister(zoneThreatsCountry) - } - if !deniedMetrics.Has(zoneThreatsTypeMetricName) { - prometheus.MustRegister(zoneThreatsType) - } - if !deniedMetrics.Has(zonePageviewsTotalMetricName) { - prometheus.MustRegister(zonePageviewsTotal) - } - if !deniedMetrics.Has(zoneUniquesTotalMetricName) { - prometheus.MustRegister(zoneUniquesTotal) - } - if !deniedMetrics.Has(zoneColocationVisitsMetricName) { - prometheus.MustRegister(zoneColocationVisits) - } - if !deniedMetrics.Has(zoneColocationEdgeResponseBytesMetricName) { - prometheus.MustRegister(zoneColocationEdgeResponseBytes) - } - if !deniedMetrics.Has(zoneColocationRequestsTotalMetricName) { - prometheus.MustRegister(zoneColocationRequestsTotal) - } - if !deniedMetrics.Has(zoneFirewallEventsCountMetricName) { - prometheus.MustRegister(zoneFirewallEventsCount) - } - if !deniedMetrics.Has(zoneHealthCheckEventsOriginCountMetricName) { - prometheus.MustRegister(zoneHealthCheckEventsOriginCount) - } - if !deniedMetrics.Has(workerRequestsMetricName) { - prometheus.MustRegister(workerRequests) - } - if !deniedMetrics.Has(workerErrorsMetricName) { - prometheus.MustRegister(workerErrors) - } - if !deniedMetrics.Has(workerCPUTimeMetricName) { - prometheus.MustRegister(workerCPUTime) - } - if !deniedMetrics.Has(workerDurationMetricName) { - prometheus.MustRegister(workerDuration) - } - if !deniedMetrics.Has(poolHealthStatusMetricName) { - prometheus.MustRegister(poolHealthStatus) - } - if !deniedMetrics.Has(poolOriginHealthStatusMetricName) { - prometheus.MustRegister(poolOriginHealthStatus) - } - if !deniedMetrics.Has(poolRequestsTotalMetricName) { - prometheus.MustRegister(poolRequestsTotal) - } - if !deniedMetrics.Has(logpushFailedJobsAccountMetricName) { - prometheus.MustRegister(logpushFailedJobsAccount) - } - if !deniedMetrics.Has(logpushFailedJobsZoneMetricName) { - prometheus.MustRegister(logpushFailedJobsZone) - } - if !deniedMetrics.Has(r2StorageTotalMetricName) { - prometheus.MustRegister(r2StorageTotal) - } - if !deniedMetrics.Has(r2StorageMetricName) { - prometheus.MustRegister(r2Storage) - } - if !deniedMetrics.Has(r2OperationMetricName) { - prometheus.MustRegister(r2Operation) - } - if !deniedMetrics.Has(tunnelInfoMetricName) { - prometheus.MustRegister(tunnelInfo) - } - if !deniedMetrics.Has(tunnelHealthStatusMetricName) { - prometheus.MustRegister(tunnelHealthStatus) - } - if !deniedMetrics.Has(tunnelConnectorInfoMetricName) { - prometheus.MustRegister(tunnelConnectorInfo) - } - if !deniedMetrics.Has(tunnelConnectorActiveConnectionsMetricName) { - prometheus.MustRegister(tunnelConnectorActiveConnections) - } - if !deniedMetrics.Has(dnsFirewallQueryCountMetricName) { - prometheus.MustRegister(dnsFirewallQueryCount) } } @@ -530,13 +282,7 @@ func fetchLoadblancerPoolsHealth(account cfaccounts.Account, wg *sync.WaitGroup) if o.JSON.ExtraFields["healthy"].Raw() == "false" { healthy = 0 // Unhealthy } - poolOriginHealthStatus.With( - prometheus.Labels{ - "account": account.Name, - "pool_name": pool.Name, - "origin_name": o.Name, - "ip": o.Address, - }).Set(float64(healthy)) + RecordMetricValueWithLabels(NeMetricSet["cloudflare_pool_origin_health_status"], healthy, account.Name, pool.Name, o.Name, o.Address) } } } diff --git a/run_e2e.sh b/run_e2e.sh index dd696fb..76f5830 100755 --- a/run_e2e.sh +++ b/run_e2e.sh @@ -7,7 +7,7 @@ source .env # Test if we have cloudflare api/key variables configured. # Run cloudflare-exporter -nohup ./cloudflare_exporter --listen="${baseUrl}" >/tmp/cloudflare-exporter-test.out 2>&1 & +nohup bash -c 'CF_API_TOKEN=bQMHYoAQ_sPYo79v59-_O8jpUuU9qKhC_B0PaQsr ./cloudflare_exporter --listen="${baseUrl}" >/tmp/cloudflare-exporter-test.out 2>&1' & export pid=$! sleep 5 From 7b0dfa2ac2e4b0ba2ffbca8bec2b8cfcf47184af Mon Sep 17 00:00:00 2001 From: Ashley Lowde Date: Fri, 14 Nov 2025 11:33:43 +1030 Subject: [PATCH 2/2] Finish refactor --- main.go | 32 +-- prometheus.go | 762 ++++++++++++++++++++++++++------------------------ 2 files changed, 409 insertions(+), 385 deletions(-) diff --git a/main.go b/main.go index b9ad14f..21773e6 100644 --- a/main.go +++ b/main.go @@ -8,7 +8,6 @@ import ( "sync" "time" - cfaccounts "github.com/cloudflare/cloudflare-go/v4/accounts" "github.com/nelkinda/health-go" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/spf13/cobra" @@ -27,19 +26,6 @@ var ( log = logrus.New() ) -// var ( -// cfgListen = ":8080" -// cfgCfAPIKey = "" -// cfgCfAPIEmail = "" -// cfgCfAPIToken = "" -// cfgMetricsPath = "/metrics" -// cfgZones = "" -// cfgExcludeZones = "" -// cfgScrapeDelay = 300 -// cfgFreeTier = false -// cfgMetricsDenylist = "" -// ) - func getTargetZones() []string { var zoneIDs []string @@ -104,14 +90,10 @@ func filterExcludedZones(all []cfzones.Zone, exclude []string) []cfzones.Zone { return filtered } -func fetchMetrics(deniedMetricsSet MetricsSet) { +func fetchMetrics(deniedMetricsSet []string) { var wg sync.WaitGroup accounts := fetchAccounts() - accounts = []cfaccounts.Account{cfaccounts.Account{ - ID: "22d2b105f2800afd70234ceef6634238", - }} - for _, a := range accounts { go fetchWorkerAnalytics(a, &wg) go fetchLogpushAnalyticsForAccount(a, &wg) @@ -168,19 +150,15 @@ func runExporter() { if len(viper.GetString("metrics_denylist")) > 0 { metricsDenylist = strings.Split(viper.GetString("metrics_denylist"), ",") } - metricsSet, err := buildFilteredMetricsSet(metricsDenylist) - if err != nil { - log.Fatalf("Error building metrics set: %v", err) - } - log.Debugf("Metrics set: %v", metricsSet) - mustRegisterMetrics(metricsSet) + + mustRegisterMetrics(metricsDenylist) scrapeInterval := time.Duration(viper.GetInt("scrape_interval")) * time.Second log.Info("Scrape interval set to ", scrapeInterval) go func() { for ; true; <-time.NewTicker(scrapeInterval).C { - go fetchMetrics(metricsSet) + go fetchMetrics(metricsDenylist) } }() @@ -248,7 +226,7 @@ func main() { flags.Int("scrape_interval", 60, "scrape interval in seconds, defaults to 60") viper.BindEnv("scrape_interval") - viper.SetDefault("scrape_interval", 10) + viper.SetDefault("scrape_interval", 60) flags.Bool("free_tier", false, "scrape only metrics included in free plan") viper.BindEnv("free_tier") diff --git a/prometheus.go b/prometheus.go index 7cbf1ff..01f3feb 100644 --- a/prometheus.go +++ b/prometheus.go @@ -22,7 +22,40 @@ type Metric struct { collector prometheus.Collector } -func (m *Metric) MustRegister() { +func (m Metric) RecordValueWithLabels(value any, labels ...string) { + var floatValue float64 + switch value := value.(type) { + case float32: + floatValue = float64(value) + case float64: + floatValue = value + case int: + floatValue = float64(value) + case int64: + floatValue = float64(value) + case uint: + floatValue = float64(value) + case uint64: + floatValue = float64(value) + default: + panic(fmt.Sprintf("unsupported value type: %T for metric", value)) + } + + switch m.Type { + case "counter": + m.collector.(*prometheus.CounterVec).WithLabelValues(labels...).Add(floatValue) + case "gauge": + m.collector.(*prometheus.GaugeVec).WithLabelValues(labels...).Set(floatValue) + case "histogram": + m.collector.(*prometheus.HistogramVec).WithLabelValues(labels...).Observe(floatValue) + case "summary": + m.collector.(*prometheus.SummaryVec).WithLabelValues(labels...).Observe(floatValue) + default: + panic(fmt.Sprintf("unknown metric type: %s", m.Type)) + } +} + +func MustRegister(m Metric) { switch m.Type { case "counter": m.collector = prometheus.NewCounterVec(prometheus.CounterOpts{ @@ -49,211 +82,219 @@ func (m *Metric) MustRegister() { } } -func RecordMetricValueWithLabels[T float64 | int | int64 | uint | uint64](m Metric, value T, labels ...string) { - switch m.Type { - case "counter": - m.collector.(*prometheus.CounterVec).WithLabelValues(labels...).Add(float64(value)) - case "gauge": - m.collector.(*prometheus.GaugeVec).WithLabelValues(labels...).Set(float64(value)) - case "histogram": - m.collector.(*prometheus.HistogramVec).WithLabelValues(labels...).Observe(float64(value)) - case "summary": - m.collector.(*prometheus.SummaryVec).WithLabelValues(labels...).Observe(float64(value)) - default: - panic(fmt.Sprintf("unknown metric type: %s", m.Type)) - } -} - -type MetricName string - -func (mn MetricName) String() string { - return string(mn) -} - -type MetricsSet map[MetricName]struct{} - -func (ms MetricsSet) Has(mn MetricName) bool { - _, exists := ms[mn] - return exists -} - -func (ms MetricsSet) Add(mn MetricName) { - ms[mn] = struct{}{} -} - -var NeMetricSet = map[string]Metric{ - "zoneRequestTotalMetricName": { +var Metrics = map[string]Metric{ + "zoneRequestsTotal": { Name: "cloudflare_zone_requests_total", Help: "Number of requests for zone", Labels: []string{"zone", "account"}, Type: "counter", }, - //{Name: "cloudflare_zone_requests_cached", - // Help: "Number of cached requests for zone", - // Labels: []string{"zone", "account"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_requests_ssl_encrypted", - // Help: "Number of encrypted requests for zone", - // Labels: []string{"zone", "account"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_requests_content_type", - // Help: "Number of request for zone per content type", - // Labels: []string{"zone", "account", "content_type"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_requests_country", - // Help: "Number of request for zone per country", - // Labels: []string{"zone", "account", "country", "region"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_requests_status", - // Help: "Number of request for zone per HTTP status", - // Labels: []string{"zone", "account", "status"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_requests_browser_map_page_views_count", - // Help: "Number of successful requests for HTML pages per zone", - // Labels: []string{"zone", "account", "family"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_requests_origin_status_country_host", - // Help: "Count of not cached requests for zone per origin HTTP status per country per host", - // Labels: []string{"zone", "account", "status", "country", "host"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_requests_status_country_host", - // Help: "Count of requests for zone per edge HTTP status per country per host", - // Labels: []string{"zone", "account", "status", "country", "host"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_bandwidth_total", - // Help: "Total bandwidth per zone in bytes", - // Labels: []string{"zone", "account"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_bandwidth_cached", - // Help: "Cached bandwidth per zone in bytes", - // Labels: []string{"zone", "account"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_bandwidth_ssl_encrypted", - // Help: "Encrypted bandwidth per zone in bytes", - // Labels: []string{"zone", "account"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_bandwidth_content_type", - // Help: "Bandwidth per zone per content type", - // Labels: []string{"zone", "account", "content_type"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_bandwidth_country", - // Help: "Bandwidth per country per zone", - // Labels: []string{"zone", "account", "country", "region"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_threats_total", - // Help: "Threats per zone", - // Labels: []string{"zone", "account"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_threats_country", - // Help: "Threats per zone per country", - // Labels: []string{"zone", "account", "country", "region"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_threats_type", - // Help: "Threats per zone per type", - // Labels: []string{"zone", "account", "type"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_pageviews_total", - // Help: "Pageviews per zone", - // Labels: []string{"zone", "account"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_uniques_total", - // Help: "Uniques per zone", - // Labels: []string{"zone", "account"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_colocation_visits", - // Help: "Total visits per colocation", - // Labels: []string{"zone", "account", "colocation", "host"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_colocation_edge_response_bytes", - // Help: "Edge response bytes per colocation", - // Labels: []string{"zone", "account", "colocation", "host"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_colocation_requests_total", - // Help: "Total requests per colocation", - // Labels: []string{"zone", "account", "colocation", "host"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_firewall_events_count", - // Help: "Count of Firewall events", - // Labels: []string{"zone", "account", "action", "source", "rule", "host", "country"}, - // Type: "counter"}, - //{Name: "cloudflare_zone_health_check_events_origin_count", - // Help: "Number of Heath check events per region per origin", - // Labels: []string{"zone", "account", "health_status", "origin_ip", "region", "fqdn"}, - // Type: "counter"}, - //{Name: "cloudflare_worker_requests_count", - // Help: "Number of requests sent to worker by script name", - // Labels: []string{"script_name", "account", "status"}, - // Type: "counter"}, - //{Name: "cloudflare_worker_errors_count", - // Help: "Number of errors by script name", - // Labels: []string{"script_name", "account", "status"}, - // Type: "counter"}, - //{Name: "cloudflare_worker_cpu_time", - // Help: "CPU time quantiles by script name", - // Labels: []string{"script_name", "account", "status", "quantile"}, - // Type: "gauge"}, - //{Name: "cloudflare_worker_duration", - // Help: "Duration quantiles by script name (GB*s)", - // Labels: []string{"script_name", "account", "status", "quantile"}, - // Type: "gauge"}, - //{Name: "cloudflare_zone_pool_health_status", - // Help: "Reports the health of a pool, 1 for healthy, 0 for unhealthy.", - // Labels: []string{"zone", "account", "load_balancer_name", "pool_name"}, - // Type: "gauge"}, - //{Name: "cloudflare_pool_origin_health_status", - // Help: "Reports the origin health of a pool, 1 for healthy, 0 for unhealthy.", - // Labels: []string{"account", "pool_name", "origin_name", "ip"}, - // Type: "gauge"}, - //{Name: "cloudflare_zone_pool_requests_total", - // Help: "Requests per pool", - // Labels: []string{"zone", "account", "load_balancer_name", "pool_name", "origin_name"}, - // Type: "counter"}, - //{Name: "cloudflare_logpush_failed_jobs_account_count", - // Help: "Number of failed logpush jobs on the account level", - // Labels: []string{"account", "destination", "job_id", "final"}, - // Type: "counter"}, - //{Name: "cloudflare_logpush_failed_jobs_zone_count", - // Help: "Number of failed logpush jobs on the zone level", - // Labels: []string{"destination", "job_id", "final"}, - // Type: "counter"}, - //{Name: "cloudflare_r2_storage_total_bytes", - // Help: "Total storage used by R2", - // Labels: []string{"account"}, - // Type: "gauge"}, - //{Name: "cloudflare_r2_storage_bytes", - // Help: "Storage used by R2", - // Labels: []string{"account", "bucket"}, - // Type: "gauge"}, - //{Name: "cloudflare_r2_operation_count", - // Help: "Number of operations performed by R2", - // Labels: []string{"account", "bucket", "operation"}, - // Type: "gauge"}, - //{Name: "cloudflare_tunnel_info", - // Help: "Reports Cloudflare Tunnel details", - // Labels: []string{"account", "tunnel_id", "tunnel_name", "tunnel_type"}, - // Type: "gauge"}, - //{Name: "cloudflare_tunnel_health_status", - // Help: "Reports the health of a Cloudflare Tunnel, 0 for unhealthy, 1 for healthy, 2 for degraded, 3 for inactive", - // Labels: []string{"account", "tunnel_id"}, - // Type: "gauge"}, - //{Name: "cloudflare_tunnel_connector_info", - // Help: "Reports Cloudflare Tunnel connector details", - // Labels: []string{"account", "tunnel_id", "client_id", "version", "arch", "origin_ip"}, - // Type: "gauge"}, - //{Name: "cloudflare_tunnel_connector_active_connections", - // Help: "Reports number of active connections for a Cloudflare Tunnel connector", - // Labels: []string{"account", "tunnel_id", "client_id"}, - // Type: "gauge"}, - //{Name: "cloudflare_dns_firewall_query_count", - // Help: "DNS Firewall query count by query type and response code", - // Labels: []string{"account_id", "account_name", "dns_firewall_id", "query_type", "response_code"}, - // Type: "gauge"}, + "zoneRequestsCached": { + Name: "cloudflare_zone_requests_cached", + Help: "Number of cached requests for zone", + Labels: []string{"zone", "account"}, + Type: "counter"}, + "zoneRequestsSslEncrypted": { + Name: "cloudflare_zone_requests_ssl_encrypted", + Help: "Number of encrypted requests for zone", + Labels: []string{"zone", "account"}, + Type: "counter"}, + "zoneRequestsContentType": { + Name: "cloudflare_zone_requests_content_type", + Help: "Number of request for zone per content type", + Labels: []string{"zone", "account", "content_type"}, + Type: "counter"}, + "zoneRequestsCountry": { + Name: "cloudflare_zone_requests_country", + Help: "Number of request for zone per country", + Labels: []string{"zone", "account", "country", "region"}, + Type: "counter"}, + "zoneRequestsStatus": { + Name: "cloudflare_zone_requests_status", + Help: "Number of request for zone per HTTP status", + Labels: []string{"zone", "account", "status"}, + Type: "counter"}, + "zoneRequestsBrowserMapPageViewsCount": { + Name: "cloudflare_zone_requests_browser_map_page_views_count", + Help: "Number of successful requests for HTML pages per zone", + Labels: []string{"zone", "account", "family"}, + Type: "counter"}, + "zoneRequestsOriginStatusCountryHost": { + Name: "cloudflare_zone_requests_origin_status_country_host", + Help: "Count of not cached requests for zone per origin HTTP status per country per host", + Labels: []string{"zone", "account", "status", "country", "host"}, + Type: "counter"}, + "zoneRequestsStatusCountryHost": { + Name: "cloudflare_zone_requests_status_country_host", + Help: "Count of requests for zone per edge HTTP status per country per host", + Labels: []string{"zone", "account", "status", "country", "host"}, + Type: "counter"}, + "zoneBandwidthTotal": { + Name: "cloudflare_zone_bandwidth_total", + Help: "Total bandwidth per zone in bytes", + Labels: []string{"zone", "account"}, + Type: "counter"}, + "zoneBandwidthCached": { + Name: "cloudflare_zone_bandwidth_cached", + Help: "Cached bandwidth per zone in bytes", + Labels: []string{"zone", "account"}, + Type: "counter"}, + "zoneBandwidthSslEncrypted": { + Name: "cloudflare_zone_bandwidth_ssl_encrypted", + Help: "Encrypted bandwidth per zone in bytes", + Labels: []string{"zone", "account"}, + Type: "counter"}, + "zoneBandwidthContentType": { + Name: "cloudflare_zone_bandwidth_content_type", + Help: "Bandwidth per zone per content type", + Labels: []string{"zone", "account", "content_type"}, + Type: "counter"}, + "zoneBandwidthCountry": { + Name: "cloudflare_zone_bandwidth_country", + Help: "Bandwidth per country per zone", + Labels: []string{"zone", "account", "country", "region"}, + Type: "counter"}, + "zoneThreatsTotal": { + Name: "cloudflare_zone_threats_total", + Help: "Threats per zone", + Labels: []string{"zone", "account"}, + Type: "counter"}, + "zoneThreatsCountry": { + Name: "cloudflare_zone_threats_country", + Help: "Threats per zone per country", + Labels: []string{"zone", "account", "country", "region"}, + Type: "counter"}, + "zoneThreatsType": { + Name: "cloudflare_zone_threats_type", + Help: "Threats per zone per type", + Labels: []string{"zone", "account", "type"}, + Type: "counter"}, + "zonePageviewsTotal": { + Name: "cloudflare_zone_pageviews_total", + Help: "Pageviews per zone", + Labels: []string{"zone", "account"}, + Type: "counter"}, + "zoneUniquesTotal": { + Name: "cloudflare_zone_uniques_total", + Help: "Uniques per zone", + Labels: []string{"zone", "account"}, + Type: "counter"}, + "zoneColocationVisits": { + Name: "cloudflare_zone_colocation_visits", + Help: "Total visits per colocation", + Labels: []string{"zone", "account", "colocation", "host"}, + Type: "counter"}, + "zoneColocationEdgeResponseBytes": { + Name: "cloudflare_zone_colocation_edge_response_bytes", + Help: "Edge response bytes per colocation", + Labels: []string{"zone", "account", "colocation", "host"}, + Type: "counter"}, + "zoneColocationRequestsTotal": { + Name: "cloudflare_zone_colocation_requests_total", + Help: "Total requests per colocation", + Labels: []string{"zone", "account", "colocation", "host"}, + Type: "counter"}, + "zoneFirewallEventsCount": { + Name: "cloudflare_zone_firewall_events_count", + Help: "Count of Firewall events", + Labels: []string{"zone", "account", "action", "source", "rule", "host", "country"}, + Type: "counter"}, + "zoneHealthCheckEventsOriginCount": { + Name: "cloudflare_zone_health_check_events_origin_count", + Help: "Number of Heath check events per region per origin", + Labels: []string{"zone", "account", "health_status", "origin_ip", "region", "fqdn"}, + Type: "counter"}, + "workerRequestsCount": { + Name: "cloudflare_worker_requests_count", + Help: "Number of requests sent to worker by script name", + Labels: []string{"script_name", "account", "status"}, + Type: "counter"}, + "workerErrorsCount": { + Name: "cloudflare_worker_errors_count", + Help: "Number of errors by script name", + Labels: []string{"script_name", "account", "status"}, + Type: "counter"}, + "workerCpuTime": { + Name: "cloudflare_worker_cpu_time", + Help: "CPU time quantiles by script name", + Labels: []string{"script_name", "account", "status", "quantile"}, + Type: "gauge"}, + "workerDuration": { + Name: "cloudflare_worker_duration", + Help: "Duration quantiles by script name (GB*s)", + Labels: []string{"script_name", "account", "status", "quantile"}, + Type: "gauge"}, + "zonePoolHealthStatus": { + Name: "cloudflare_zone_pool_health_status", + Help: "Reports the health of a pool, 1 for healthy, 0 for unhealthy.", + Labels: []string{"zone", "account", "load_balancer_name", "pool_name"}, + Type: "gauge"}, + "poolOriginHealthStatus": { + Name: "cloudflare_pool_origin_health_status", + Help: "Reports the origin health of a pool, 1 for healthy, 0 for unhealthy.", + Labels: []string{"account", "pool_name", "origin_name", "ip"}, + Type: "gauge"}, + "zonePoolRequestsTotal": { + Name: "cloudflare_zone_pool_requests_total", + Help: "Requests per pool", + Labels: []string{"zone", "account", "load_balancer_name", "pool_name", "origin_name"}, + Type: "counter"}, + "logpushFailedJobsAccountCount": { + Name: "cloudflare_logpush_failed_jobs_account_count", + Help: "Number of failed logpush jobs on the account level", + Labels: []string{"account", "destination", "job_id", "final"}, + Type: "counter"}, + "logpushFailedJobsZoneCount": { + Name: "cloudflare_logpush_failed_jobs_zone_count", + Help: "Number of failed logpush jobs on the zone level", + Labels: []string{"destination", "job_id", "final"}, + Type: "counter"}, + "cloudflare_r2_storage_total_bytes": { + Name: "cloudflare_r2_storage_total_bytes", + Help: "Total storage used by R2", + Labels: []string{"account"}, + Type: "gauge"}, + "cloudflare_r2_storage_bytes": { + Name: "cloudflare_r2_storage_bytes", + Help: "Storage used by R2", + Labels: []string{"account", "bucket"}, + Type: "gauge"}, + "cloudflare_r2_operation_count": { + Name: "cloudflare_r2_operation_count", + Help: "Number of operations performed by R2", + Labels: []string{"account", "bucket", "operation"}, + Type: "gauge"}, + "tunnelInfo": { + Name: "cloudflare_tunnel_info", + Help: "Reports Cloudflare Tunnel details", + Labels: []string{"account", "tunnel_id", "tunnel_name", "tunnel_type"}, + Type: "gauge"}, + "tunnelHealthStatus": { + Name: "cloudflare_tunnel_health_status", + Help: "Reports the health of a Cloudflare Tunnel, 0 for unhealthy, 1 for healthy, 2 for degraded, 3 for inactive", + Labels: []string{"account", "tunnel_id"}, + Type: "gauge"}, + "tunnelConnectorInfo": { + Name: "cloudflare_tunnel_connector_info", + Help: "Reports Cloudflare Tunnel connector details", + Labels: []string{"account", "tunnel_id", "client_id", "version", "arch", "origin_ip"}, + Type: "gauge"}, + "tunnelConnectorActiveConnections": { + Name: "cloudflare_tunnel_connector_active_connections", + Help: "Reports number of active connections for a Cloudflare Tunnel connector", + Labels: []string{"account", "tunnel_id", "client_id"}, + Type: "gauge"}, + "dnsFirewallQueryCount": { + Name: "cloudflare_dns_firewall_query_count", + Help: "DNS Firewall query count by query type and response code", + Labels: []string{"account_id", "account_name", "dns_firewall_id", "query_type", "response_code"}, + Type: "gauge"}, } func mustRegisterMetrics(deniedMetrics []string) { - for _, metric := range NeMetricSet { + for _, metric := range Metrics { if !slices.Contains(deniedMetrics, metric.Name) { - metric.MustRegister() + MustRegister(metric) } } } @@ -282,7 +323,7 @@ func fetchLoadblancerPoolsHealth(account cfaccounts.Account, wg *sync.WaitGroup) if o.JSON.ExtraFields["healthy"].Raw() == "false" { healthy = 0 // Unhealthy } - RecordMetricValueWithLabels(NeMetricSet["cloudflare_pool_origin_health_status"], healthy, account.Name, pool.Name, o.Name, o.Address) + Metrics["cloudflare_pool_origin_health_status"].RecordValueWithLabels(healthy, account.Name, pool.Name, o.Name, o.Address) } } } @@ -302,16 +343,16 @@ func fetchWorkerAnalytics(account cfaccounts.Account, wg *sync.WaitGroup) { for _, a := range r.Viewer.Accounts { for _, w := range a.WorkersInvocationsAdaptive { - workerRequests.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status}).Add(float64(w.Sum.Requests)) - workerErrors.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status}).Add(float64(w.Sum.Errors)) - workerCPUTime.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status, "quantile": "P50"}).Set(float64(w.Quantiles.CPUTimeP50)) - workerCPUTime.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status, "quantile": "P75"}).Set(float64(w.Quantiles.CPUTimeP75)) - workerCPUTime.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status, "quantile": "P99"}).Set(float64(w.Quantiles.CPUTimeP99)) - workerCPUTime.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status, "quantile": "P999"}).Set(float64(w.Quantiles.CPUTimeP999)) - workerDuration.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status, "quantile": "P50"}).Set(float64(w.Quantiles.DurationP50)) - workerDuration.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status, "quantile": "P75"}).Set(float64(w.Quantiles.DurationP75)) - workerDuration.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status, "quantile": "P99"}).Set(float64(w.Quantiles.DurationP99)) - workerDuration.With(prometheus.Labels{"script_name": w.Dimensions.ScriptName, "account": accountName, "status": w.Dimensions.Status, "quantile": "P999"}).Set(float64(w.Quantiles.DurationP999)) + Metrics["workerRequestsCount"].RecordValueWithLabels(w.Sum.Requests, w.Dimensions.ScriptName, accountName, w.Dimensions.Status) + Metrics["workerErrorsCount"].RecordValueWithLabels(w.Sum.Errors, w.Dimensions.ScriptName, accountName, w.Dimensions.Status) + Metrics["workerCpuTime"].RecordValueWithLabels(w.Quantiles.CPUTimeP50, w.Dimensions.ScriptName, accountName, w.Dimensions.Status, "P50") + Metrics["workerCpuTime"].RecordValueWithLabels(w.Quantiles.CPUTimeP75, w.Dimensions.ScriptName, accountName, w.Dimensions.Status, "P75") + Metrics["workerCpuTime"].RecordValueWithLabels(w.Quantiles.CPUTimeP99, w.Dimensions.ScriptName, accountName, w.Dimensions.Status, "P99") + Metrics["workerCpuTime"].RecordValueWithLabels(w.Quantiles.CPUTimeP999, w.Dimensions.ScriptName, accountName, w.Dimensions.Status, "P999") + Metrics["workerDuration"].RecordValueWithLabels(w.Quantiles.DurationP50, w.Dimensions.ScriptName, accountName, w.Dimensions.Status, "P50") + Metrics["workerDuration"].RecordValueWithLabels(w.Quantiles.DurationP75, w.Dimensions.ScriptName, accountName, w.Dimensions.Status, "P75") + Metrics["workerDuration"].RecordValueWithLabels(w.Quantiles.DurationP99, w.Dimensions.ScriptName, accountName, w.Dimensions.Status, "P99") + Metrics["workerDuration"].RecordValueWithLabels(w.Quantiles.DurationP999, w.Dimensions.ScriptName, accountName, w.Dimensions.Status, "P999") } } } @@ -333,10 +374,12 @@ func fetchLogpushAnalyticsForAccount(account cfaccounts.Account, wg *sync.WaitGr for _, acc := range r.Viewer.Accounts { for _, LogpushHealthAdaptiveGroup := range acc.LogpushHealthAdaptiveGroups { - logpushFailedJobsAccount.With(prometheus.Labels{"account": account.ID, - "destination": LogpushHealthAdaptiveGroup.Dimensions.DestinationType, - "job_id": strconv.Itoa(LogpushHealthAdaptiveGroup.Dimensions.JobID), - "final": strconv.Itoa(LogpushHealthAdaptiveGroup.Dimensions.Final)}).Add(float64(LogpushHealthAdaptiveGroup.Count)) + Metrics["logpushFailedJobsAccountCount"].RecordValueWithLabels(float64(LogpushHealthAdaptiveGroup.Count), + account.ID, + LogpushHealthAdaptiveGroup.Dimensions.DestinationType, + strconv.Itoa(LogpushHealthAdaptiveGroup.Dimensions.JobID), + strconv.Itoa(LogpushHealthAdaptiveGroup.Dimensions.Final), + ) } } } @@ -354,16 +397,16 @@ func fetchR2StorageForAccount(account cfaccounts.Account, wg *sync.WaitGroup) { var totalStorage uint64 for _, bucket := range acc.R2StorageGroups { totalStorage += bucket.Max.PayloadSize - r2Storage.With(prometheus.Labels{"account": account.Name, "bucket": bucket.Dimensions.BucketName}).Set(float64(bucket.Max.PayloadSize)) + Metrics["cloudflare_r2_storage_bytes"].RecordValueWithLabels(float64(bucket.Max.PayloadSize), account.Name, bucket.Dimensions.BucketName) } for _, operation := range acc.R2StorageOperations { - r2Operation.With(prometheus.Labels{"account": account.Name, "bucket": operation.Dimensions.BucketName, "operation": operation.Dimensions.Action}).Set(float64(operation.Sum.Requests)) + Metrics["cloudflare_r2_operation_count"].RecordValueWithLabels(float64(operation.Sum.Requests), account.Name, operation.Dimensions.BucketName, operation.Dimensions.Action) } - r2StorageTotal.With(prometheus.Labels{"account": account.Name}).Set(float64(totalStorage)) + Metrics["cloudflare_r2_storage_total_bytes"].RecordValueWithLabels(float64(totalStorage), account.Name) } } -func fetchLogpushAnalyticsForZone(zones []cfzones.Zone, wg *sync.WaitGroup, _ MetricsSet) { +func fetchLogpushAnalyticsForZone(zones []cfzones.Zone, wg *sync.WaitGroup, _ []string) { wg.Add(1) defer wg.Done() @@ -385,14 +428,17 @@ func fetchLogpushAnalyticsForZone(zones []cfzones.Zone, wg *sync.WaitGroup, _ Me for _, zone := range r.Viewer.Zones { for _, LogpushHealthAdaptiveGroup := range zone.LogpushHealthAdaptiveGroups { - logpushFailedJobsZone.With(prometheus.Labels{"destination": LogpushHealthAdaptiveGroup.Dimensions.DestinationType, - "job_id": strconv.Itoa(LogpushHealthAdaptiveGroup.Dimensions.JobID), - "final": strconv.Itoa(LogpushHealthAdaptiveGroup.Dimensions.Final)}).Add(float64(LogpushHealthAdaptiveGroup.Count)) + Metrics["logpushFailedJobsZoneCount"].RecordValueWithLabels( + float64(LogpushHealthAdaptiveGroup.Count), + LogpushHealthAdaptiveGroup.Dimensions.DestinationType, + strconv.Itoa(LogpushHealthAdaptiveGroup.Dimensions.JobID), + strconv.Itoa(LogpushHealthAdaptiveGroup.Dimensions.Final), + ) } } } -func fetchDNSFirewallAnalytics(account cfaccounts.Account, wg *sync.WaitGroup, deniedMetricsSet MetricsSet) { +func fetchDNSFirewallAnalytics(account cfaccounts.Account, wg *sync.WaitGroup, deniedMetricsSet []string) { wg.Add(1) defer wg.Done() @@ -403,20 +449,21 @@ func fetchDNSFirewallAnalytics(account cfaccounts.Account, wg *sync.WaitGroup, d for _, a := range r.Viewer.Accounts { for _, d := range a.DNSFirewallAnalyticsAdaptiveGroups { - if !deniedMetricsSet.Has(dnsFirewallQueryCountMetricName) { - dnsFirewallQueryCount.WithLabelValues( + if !slices.Contains(deniedMetricsSet, "dnsFirewallQueryCount") { + Metrics["dnsFirewallQueryCount"].RecordValueWithLabels( + float64(d.Count), account.ID, account.Name, d.Dimensions.ClusterTag, d.Dimensions.QueryType, d.Dimensions.ResponseCode, - ).Set(float64(d.Count)) + ) } } } } -func fetchZoneColocationAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, deniedMetricsSet MetricsSet) { +func fetchZoneColocationAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, deniedMetricsSet []string) { wg.Add(1) defer wg.Done() @@ -439,20 +486,20 @@ func fetchZoneColocationAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, deni cg := z.ColoGroups name, account := findZoneAccountName(zones, z.ZoneTag) for _, c := range cg { - if !deniedMetricsSet.Has(zoneColocationVisitsMetricName) { - zoneColocationVisits.With(prometheus.Labels{"zone": name, "account": account, "colocation": c.Dimensions.ColoCode, "host": c.Dimensions.Host}).Add(float64(c.Sum.Visits)) + if !slices.Contains(deniedMetricsSet, "zoneColocationVisits") { + Metrics["zoneColocationVisits"].RecordValueWithLabels(float64(c.Sum.Visits), name, account, c.Dimensions.ColoCode, c.Dimensions.Host) } - if !deniedMetricsSet.Has(zoneColocationEdgeResponseBytesMetricName) { - zoneColocationEdgeResponseBytes.With(prometheus.Labels{"zone": name, "account": account, "colocation": c.Dimensions.ColoCode, "host": c.Dimensions.Host}).Add(float64(c.Sum.EdgeResponseBytes)) + if !slices.Contains(deniedMetricsSet, "zoneColocationEdgeResponseBytes") { + Metrics["zoneColocationEdgeResponseBytes"].RecordValueWithLabels(float64(c.Sum.EdgeResponseBytes), name, account, c.Dimensions.ColoCode, c.Dimensions.Host) } - if !deniedMetricsSet.Has(zoneColocationRequestsTotalMetricName) { - zoneColocationRequestsTotal.With(prometheus.Labels{"zone": name, "account": account, "colocation": c.Dimensions.ColoCode, "host": c.Dimensions.Host}).Add(float64(c.Count)) + if !slices.Contains(deniedMetricsSet, "zoneColocationRequestsTotal") { + Metrics["zoneColocationRequestsTotal"].RecordValueWithLabels(float64(c.Count), name, account, c.Dimensions.ColoCode, c.Dimensions.Host) } } } } -func fetchZoneAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, deniedMetricsSet MetricsSet) { +func fetchZoneAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, deniedMetricsSet []string) { wg.Add(1) defer wg.Done() @@ -483,7 +530,7 @@ func fetchZoneAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, deniedMetricsS } } -func addHTTPGroups(z *zoneResp, name string, account string, deniedMetricsSet MetricsSet) { +func addHTTPGroups(z *zoneResp, name string, account string, deniedMetricsSet []string) { // Nothing to do. if len(z.HTTP1mGroups) == 0 { return @@ -491,22 +538,22 @@ func addHTTPGroups(z *zoneResp, name string, account string, deniedMetricsSet Me zt := z.HTTP1mGroups[0] - if !deniedMetricsSet.Has(zoneRequestTotalMetricName) { - zoneRequestTotal.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Sum.Requests)) + if !slices.Contains(deniedMetricsSet, "zoneRequestTotal") { + Metrics["zoneRequestsTotal"].RecordValueWithLabels(zt.Sum.Requests, name, account) } - if !deniedMetricsSet.Has(zoneRequestCachedMetricName) { - zoneRequestCached.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Sum.CachedRequests)) + if !slices.Contains(deniedMetricsSet, "zoneRequestCached") { + Metrics["zoneRequestsCached"].RecordValueWithLabels(zt.Sum.CachedRequests, name, account) } - if !deniedMetricsSet.Has(zoneRequestSSLEncryptedMetricName) { - zoneRequestSSLEncrypted.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Sum.EncryptedRequests)) + if !slices.Contains(deniedMetricsSet, "zoneRequestSSLEncrypted") { + Metrics["zoneRequestsSslEncrypted"].RecordValueWithLabels(zt.Sum.EncryptedRequests, name, account) } for _, ct := range zt.Sum.ContentType { - if !deniedMetricsSet.Has(zoneRequestContentTypeMetricName) { - zoneRequestContentType.With(prometheus.Labels{"zone": name, "account": account, "content_type": ct.EdgeResponseContentType}).Add(float64(ct.Requests)) + if !slices.Contains(deniedMetricsSet, "zoneRequestContentType") { + Metrics["zoneRequestsContentType"].RecordValueWithLabels(ct.Requests, name, account, ct.EdgeResponseContentType) } - if !deniedMetricsSet.Has(zoneBandwidthContentTypeMetricName) { - zoneBandwidthContentType.With(prometheus.Labels{"zone": name, "account": account, "content_type": ct.EdgeResponseContentType}).Add(float64(ct.Bytes)) + if !slices.Contains(deniedMetricsSet, "zoneBandwidthContentType") { + Metrics["zoneBandwidthContentType"].RecordValueWithLabels(ct.Bytes, name, account, ct.EdgeResponseContentType) } } @@ -514,77 +561,76 @@ func addHTTPGroups(z *zoneResp, name string, account string, deniedMetricsSet Me c := countries.ByName(country.ClientCountryName) region := c.Info().Region.Info().Name - if !deniedMetricsSet.Has(zoneRequestCountryMetricName) { - zoneRequestCountry.With(prometheus.Labels{"zone": name, "account": account, "country": country.ClientCountryName, "region": region}).Add(float64(country.Requests)) + if !slices.Contains(deniedMetricsSet, "zoneRequestCountry") { + Metrics["zoneRequestsCountry"].RecordValueWithLabels(country.Requests, name, account, country.ClientCountryName, region) } - if !deniedMetricsSet.Has(zoneBandwidthCountryMetricName) { - zoneBandwidthCountry.With(prometheus.Labels{"zone": name, "account": account, "country": country.ClientCountryName, "region": region}).Add(float64(country.Bytes)) + if !slices.Contains(deniedMetricsSet, "zoneBandwidthCountry") { + Metrics["zoneBandwidthCountry"].RecordValueWithLabels(country.Bytes, name, account, country.ClientCountryName, region) } - if !deniedMetricsSet.Has(zoneThreatsCountryMetricName) { - zoneThreatsCountry.With(prometheus.Labels{"zone": name, "account": account, "country": country.ClientCountryName, "region": region}).Add(float64(country.Threats)) + if !slices.Contains(deniedMetricsSet, "zoneThreatsCountry") { + Metrics["zoneThreatsCountry"].RecordValueWithLabels(country.Threats, name, account, country.ClientCountryName, region) } } - if !deniedMetricsSet.Has(zoneRequestHTTPStatusMetricName) { + if !slices.Contains(deniedMetricsSet, "zoneRequestHTTPStatus") { for _, status := range zt.Sum.ResponseStatus { - zoneRequestHTTPStatus.With(prometheus.Labels{"zone": name, "account": account, "status": strconv.Itoa(status.EdgeResponseStatus)}).Add(float64(status.Requests)) + Metrics["zoneRequestsStatus"].RecordValueWithLabels(status.Requests, name, account, strconv.Itoa(status.EdgeResponseStatus)) } } - if !deniedMetricsSet.Has(zoneRequestBrowserMapMetricName) { + if !slices.Contains(deniedMetricsSet, "zoneRequestBrowserMap") { for _, browser := range zt.Sum.BrowserMap { - zoneRequestBrowserMap.With(prometheus.Labels{"zone": name, "account": account, "family": browser.UaBrowserFamily}).Add(float64(browser.PageViews)) + Metrics["zoneRequestsBrowserMapPageViewsCount"].RecordValueWithLabels(browser.PageViews, name, account, browser.UaBrowserFamily) } } - if !deniedMetricsSet.Has(zoneBandwidthTotalMetricName) { - zoneBandwidthTotal.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Sum.Bytes)) + if !slices.Contains(deniedMetricsSet, "zoneBandwidthTotal") { + Metrics["zoneBandwidthTotal"].RecordValueWithLabels(zt.Sum.Bytes, name, account) } - if !deniedMetricsSet.Has(zoneBandwidthCachedMetricName) { - zoneBandwidthCached.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Sum.CachedBytes)) + if !slices.Contains(deniedMetricsSet, "zoneBandwidthCached") { + Metrics["zoneBandwidthCached"].RecordValueWithLabels(zt.Sum.CachedBytes, name, account) } - if !deniedMetricsSet.Has(zoneBandwidthSSLEncryptedMetricName) { - zoneBandwidthSSLEncrypted.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Sum.EncryptedBytes)) + if !slices.Contains(deniedMetricsSet, "zoneBandwidthSSLEncrypted") { + Metrics["zoneBandwidthSslEncrypted"].RecordValueWithLabels(zt.Sum.EncryptedBytes, name, account) } - if !deniedMetricsSet.Has(zoneThreatsTotalMetricName) { - zoneThreatsTotal.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Sum.Threats)) + if !slices.Contains(deniedMetricsSet, "zoneThreatsTotal") { + Metrics["zoneThreatsTotal"].RecordValueWithLabels(zt.Sum.Threats, name, account) } - if !deniedMetricsSet.Has(zoneThreatsTypeMetricName) { + if !slices.Contains(deniedMetricsSet, "zoneThreatsType") { for _, t := range zt.Sum.ThreatPathing { - zoneThreatsType.With(prometheus.Labels{"zone": name, "account": account, "type": t.Name}).Add(float64(t.Requests)) + Metrics["zoneThreatsType"].RecordValueWithLabels(t.Requests, name, account, t.Name) } } - if !deniedMetricsSet.Has(zonePageviewsTotalMetricName) { - zonePageviewsTotal.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Sum.PageViews)) + if !slices.Contains(deniedMetricsSet, "zonePageviewsTotal") { + Metrics["zonePageviewsTotal"].RecordValueWithLabels(zt.Sum.PageViews, name, account) } - if !deniedMetricsSet.Has(zoneUniquesTotalMetricName) { - // Uniques - zoneUniquesTotal.With(prometheus.Labels{"zone": name, "account": account}).Add(float64(zt.Unique.Uniques)) + if !slices.Contains(deniedMetricsSet, "zoneUniquesTotal") { + Metrics["zoneUniquesTotal"].RecordValueWithLabels(zt.Unique.Uniques, name, account) } } -func addFirewallGroups(z *zoneResp, name string, account string, deniedMetricsSet MetricsSet) { +func addFirewallGroups(z *zoneResp, name string, account string, deniedMetricsSet []string) { // Nothing to do. if len(z.FirewallEventsAdaptiveGroups) == 0 { return } rulesMap := fetchFirewallRules(z.ZoneTag) - if !deniedMetricsSet.Has(zoneFirewallEventsCountMetricName) { + if !slices.Contains(deniedMetricsSet, "zoneFirewallEventsCount") { for _, g := range z.FirewallEventsAdaptiveGroups { - zoneFirewallEventsCount.With( - prometheus.Labels{ - "zone": name, - "account": account, - "action": g.Dimensions.Action, - "source": g.Dimensions.Source, - "rule": normalizeRuleName(rulesMap[g.Dimensions.RuleID]), - "host": g.Dimensions.ClientRequestHTTPHost, - "country": g.Dimensions.ClientCountryName, - }).Add(float64(g.Count)) + Metrics["zoneFirewallEventsCount"].RecordValueWithLabels( + g.Count, + name, + account, + g.Dimensions.Action, + g.Dimensions.Source, + normalizeRuleName(rulesMap[g.Dimensions.RuleID]), + g.Dimensions.ClientRequestHTTPHost, + g.Dimensions.ClientCountryName, + ) } } } @@ -598,54 +644,54 @@ func normalizeRuleName(initialText string) string { return nonSpaceName } -func addHealthCheckGroups(z *zoneResp, name string, account string, deniedMetricsSet MetricsSet) { +func addHealthCheckGroups(z *zoneResp, name string, account string, deniedMetricsSet []string) { if len(z.HealthCheckEventsAdaptiveGroups) == 0 { return } - if !deniedMetricsSet.Has(zoneHealthCheckEventsOriginCountMetricName) { + if !slices.Contains(deniedMetricsSet, "zoneHealthCheckEventsOriginCount") { for _, g := range z.HealthCheckEventsAdaptiveGroups { - zoneHealthCheckEventsOriginCount.With( - prometheus.Labels{ - "zone": name, - "account": account, - "health_status": g.Dimensions.HealthStatus, - "origin_ip": g.Dimensions.OriginIP, - "region": g.Dimensions.Region, - "fqdn": g.Dimensions.Fqdn, - }).Add(float64(g.Count)) + Metrics["zoneHealthCheckEventsOriginCount"].RecordValueWithLabels( + g.Count, + name, + account, + g.Dimensions.HealthStatus, + g.Dimensions.OriginIP, + g.Dimensions.Region, + g.Dimensions.Fqdn, + ) } } } -func addHTTPAdaptiveGroups(z *zoneResp, name string, account string, deniedMetricsSet MetricsSet) { - if !deniedMetricsSet.Has(zoneRequestOriginStatusCountryHostMetricName) { +func addHTTPAdaptiveGroups(z *zoneResp, name string, account string, deniedMetricsSet []string) { + if !slices.Contains(deniedMetricsSet, "zoneRequestOriginStatusCountryHost") { for _, g := range z.HTTPRequestsAdaptiveGroups { - zoneRequestOriginStatusCountryHost.With( - prometheus.Labels{ - "zone": name, - "account": account, - "status": strconv.Itoa(int(g.Dimensions.OriginResponseStatus)), - "country": g.Dimensions.ClientCountryName, - "host": g.Dimensions.ClientRequestHTTPHost, - }).Add(float64(g.Count)) + Metrics["zoneRequestsOriginStatusCountryHost"].RecordValueWithLabels( + g.Count, + name, + account, + strconv.Itoa(int(g.Dimensions.OriginResponseStatus)), + g.Dimensions.ClientCountryName, + g.Dimensions.ClientRequestHTTPHost, + ) } } - if !deniedMetricsSet.Has(zoneRequestStatusCountryHostMetricName) { + if !slices.Contains(deniedMetricsSet, "zoneRequestStatusCountryHost") { for _, g := range z.HTTPRequestsEdgeCountryHost { - zoneRequestStatusCountryHost.With( - prometheus.Labels{ - "zone": name, - "account": account, - "status": strconv.Itoa(int(g.Dimensions.EdgeResponseStatus)), - "country": g.Dimensions.ClientCountryName, - "host": g.Dimensions.ClientRequestHTTPHost, - }).Add(float64(g.Count)) + Metrics["zoneRequestsStatusCountryHost"].RecordValueWithLabels( + g.Count, + name, + account, + strconv.Itoa(int(g.Dimensions.EdgeResponseStatus)), + g.Dimensions.ClientCountryName, + g.Dimensions.ClientRequestHTTPHost, + ) } } } -func fetchLoadBalancerAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, deniedMetricsSet MetricsSet) { +func fetchLoadBalancerAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, deniedMetricsSet []string) { wg.Add(1) defer wg.Done() @@ -672,32 +718,32 @@ func fetchLoadBalancerAnalytics(zones []cfzones.Zone, wg *sync.WaitGroup, denied } } -func addLoadBalancingRequestsAdaptiveGroups(z *lbResp, name string, account string, deniedMetricsSet MetricsSet) { - if !deniedMetricsSet.Has(poolRequestsTotalMetricName) { +func addLoadBalancingRequestsAdaptiveGroups(z *lbResp, name string, account string, deniedMetricsSet []string) { + if !slices.Contains(deniedMetricsSet, "poolRequestsTotal") { for _, g := range z.LoadBalancingRequestsAdaptiveGroups { - poolRequestsTotal.With( - prometheus.Labels{ - "zone": name, - "account": account, - "load_balancer_name": g.Dimensions.LbName, - "pool_name": g.Dimensions.SelectedPoolName, - "origin_name": g.Dimensions.SelectedOriginName, - }).Add(float64(g.Count)) + Metrics["zonePoolRequestsTotal"].RecordValueWithLabels( + g.Count, + name, + account, + g.Dimensions.LbName, + g.Dimensions.SelectedPoolName, + g.Dimensions.SelectedOriginName, + ) } } } -func addLoadBalancingRequestsAdaptive(z *lbResp, name string, account string, deniedMetricsSet MetricsSet) { - if !deniedMetricsSet.Has(poolHealthStatusMetricName) { +func addLoadBalancingRequestsAdaptive(z *lbResp, name string, account string, deniedMetricsSet []string) { + if !slices.Contains(deniedMetricsSet, "poolHealthStatus") { for _, g := range z.LoadBalancingRequestsAdaptive { for _, p := range g.Pools { - poolHealthStatus.With( - prometheus.Labels{ - "zone": name, - "account": account, - "load_balancer_name": g.LbName, - "pool_name": p.PoolName, - }).Set(float64(p.Healthy)) + Metrics["zonePoolHealthStatus"].RecordValueWithLabels( + p.Healthy, + name, + account, + g.LbName, + p.PoolName, + ) } } } @@ -713,19 +759,19 @@ func fetchZeroTrustAnalyticsForAccount(account cfaccounts.Account, wg *sync.Wait func addCloudflareTunnelStatus(account cfaccounts.Account) { tunnels := fetchCloudflareTunnels(account) for _, t := range tunnels { - tunnelInfo.With( - prometheus.Labels{ - "account": account.Name, - "tunnel_id": t.ID, - "tunnel_name": t.Name, - "tunnel_type": string(t.TunType), - }).Set(float64(1)) - - tunnelHealthStatus.With( - prometheus.Labels{ - "account": account.Name, - "tunnel_id": t.ID, - }).Set(float64(getCloudflareTunnelStatusValue(string(t.Status)))) + Metrics["tunnelInfo"].RecordValueWithLabels( + 1, + account.Name, + t.ID, + t.Name, + string(t.TunType), + ) + + Metrics["tunnelHealthStatus"].RecordValueWithLabels( + getCloudflareTunnelStatusValue(string(t.Status)), + account.Name, + t.ID, + ) // Each client/connector can open many connections to the Cloudflare edge, // we opt to not expose metrics for each individual connection. We do expose @@ -737,22 +783,22 @@ func addCloudflareTunnelStatus(account cfaccounts.Account) { originIP = c.Conns[0].OriginIP } - tunnelConnectorInfo.With( - prometheus.Labels{ - "account": account.Name, - "tunnel_id": t.ID, - "client_id": c.ID, - "version": c.Version, - "arch": c.Arch, - "origin_ip": originIP, - }).Set(float64(1)) - - tunnelConnectorActiveConnections.With( - prometheus.Labels{ - "account": account.Name, - "tunnel_id": t.ID, - "client_id": c.ID, - }).Set(float64(len(c.Conns))) + Metrics["tunnelConnectorInfo"].RecordValueWithLabels( + 1, + account.Name, + t.ID, + c.ID, + c.Version, + c.Arch, + originIP, + ) + + Metrics["tunnelConnectorActiveConnections"].RecordValueWithLabels( + len(c.Conns), + account.Name, + t.ID, + c.ID, + ) } } }