diff --git a/main.go b/main.go index c3f1337..21773e6 100644 --- a/main.go +++ b/main.go @@ -26,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 @@ -103,7 +90,7 @@ 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() @@ -163,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) } }() diff --git a/prometheus.go b/prometheus.go index 2673c4c..01f3feb 100644 --- a/prometheus.go +++ b/prometheus.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "slices" "strconv" "strings" "sync" @@ -13,496 +14,288 @@ import ( "github.com/spf13/viper" ) -type MetricName string - -func (mn MetricName) String() string { - return string(mn) +type Metric struct { + Name string + Help string + Labels []string + Type string + collector prometheus.Collector } -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 { - _, exists := ms[mn] - return exists +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 (ms MetricsSet) Add(mn MetricName) { - ms[mn] = struct{}{} +func MustRegister(m Metric) { + 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)) + } } -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 Metrics = map[string]Metric{ + "zoneRequestsTotal": { + 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 + "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 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 Metrics { + if !slices.Contains(deniedMetrics, metric.Name) { + MustRegister(metric) } - 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 +323,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)) + Metrics["cloudflare_pool_origin_health_status"].RecordValueWithLabels(healthy, account.Name, pool.Name, o.Name, o.Address) } } } @@ -556,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") } } } @@ -587,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), + ) } } } @@ -608,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() @@ -639,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() @@ -657,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() @@ -693,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() @@ -737,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 @@ -745,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) } } @@ -768,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, + ) } } } @@ -852,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() @@ -926,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, + ) } } } @@ -967,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 @@ -991,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, + ) } } } 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