diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 177bd69..df22b6e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - go-version: [1.13.x] + go-version: [1.15.x] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/cmd/fastly-exporter/main.go b/cmd/fastly-exporter/main.go index c8ee788..65a9620 100644 --- a/cmd/fastly-exporter/main.go +++ b/cmd/fastly-exporter/main.go @@ -19,7 +19,7 @@ import ( "github.com/oklog/run" "github.com/peterbourgon/fastly-exporter/pkg/api" "github.com/peterbourgon/fastly-exporter/pkg/filter" - "github.com/peterbourgon/fastly-exporter/pkg/prom" + "github.com/peterbourgon/fastly-exporter/pkg/gen" "github.com/peterbourgon/fastly-exporter/pkg/rt" "github.com/peterbourgon/ff/v3" "github.com/prometheus/client_golang/prometheus" @@ -210,10 +210,10 @@ func main() { registry = prometheus.NewRegistry() } - var metrics *prom.Metrics + var metrics *gen.Metrics { var err error - metrics, err = prom.NewMetrics(namespace, subsystem, metricNameFilter, registry) + metrics, err = gen.NewMetrics(namespace, subsystem, metricNameFilter, registry) if err != nil { level.Error(logger).Log("err", err) os.Exit(1) diff --git a/cmd/fieldgen/api_fields.json b/cmd/fieldgen/api_fields.json new file mode 100644 index 0000000..fd50e01 --- /dev/null +++ b/cmd/fieldgen/api_fields.json @@ -0,0 +1,155 @@ +[ + {"field_name": "AttackBlockedReqHeaderBytes", "type": "uint64", "key": "attack_blocked_req_header_bytes"}, + {"field_name": "AttackBlockedReqBodyBytes", "type": "uint64", "key": "attack_blocked_req_body_bytes"}, + {"field_name": "AttackLoggedReqBodyBytes", "type": "uint64", "key": "attack_logged_req_body_bytes"}, + {"field_name": "AttackLoggedReqHeaderBytes", "type": "uint64", "key": "attack_logged_req_header_bytes"}, + {"field_name": "AttackPassedReqBodyBytes", "type": "uint64", "key": "attack_passed_req_body_bytes"}, + {"field_name": "AttackPassedReqHeaderBytes", "type": "uint64", "key": "attack_passed_req_header_bytes"}, + {"field_name": "AttackReqBodyBytes", "type": "uint64", "key": "attack_req_body_bytes"}, + {"field_name": "AttackReqHeaderBytes", "type": "uint64", "key": "attack_req_header_bytes"}, + {"field_name": "AttackRespSynthBytes", "type": "uint64", "key": "attack_resp_synth_bytes"}, + {"field_name": "BackendReqBodyBytes", "type": "uint64", "key": "bereq_body_bytes"}, + {"field_name": "BackendReqHeaderBytes", "type": "uint64", "key": "bereq_header_bytes"}, + {"field_name": "Billed", "type": "uint64", "key": "billed"}, + {"field_name": "BilledBodyBytes", "type": "uint64", "key": "billed_body_bytes"}, + {"field_name": "BilledHeaderBytes", "type": "uint64", "key": "billed_header_bytes"}, + {"field_name": "Blacklisted", "type": "uint64", "key": "blacklist"}, + {"field_name": "BodySize", "type": "uint64", "key": "body_size"}, + {"field_name": "DeliverSubCount", "type": "uint64", "key": "deliver_sub_count"}, + {"field_name": "DeliverSubTime", "type": "uint64", "key": "deliver_sub_time"}, + {"field_name": "Edge", "type": "uint64", "key": "edge"}, + {"field_name": "EdgeRespBodyBytes", "type": "uint64", "key": "edge_resp_body_bytes"}, + {"field_name": "EdgeRespHeaderBytes", "type": "uint64", "key": "edge_resp_header_bytes"}, + {"field_name": "Errors", "type": "uint64", "key": "errors"}, + {"field_name": "ErrorSubCount", "type": "uint64", "key": "error_sub_count"}, + {"field_name": "ErrorSubTime", "type": "uint64", "key": "error_sub_time"}, + {"field_name": "FetchSubCount", "type": "uint64", "key": "fetch_sub_count"}, + {"field_name": "FetchSubTime", "type": "uint64", "key": "fetch_sub_time"}, + {"field_name": "HashSubCount", "type": "uint64", "key": "hash_sub_count"}, + {"field_name": "HashSubTime", "type": "uint64", "key": "hash_sub_time"}, + {"field_name": "HeaderSize", "type": "uint64", "key": "header_size"}, + {"field_name": "HitRespBodyBytes", "type": "uint64", "key": "hit_resp_body_bytes"}, + {"field_name": "Hits", "type": "uint64", "key": "hits"}, + {"field_name": "HitsTime", "type": "float64", "key": "hits_time"}, + {"field_name": "HitSubCount", "type": "uint64", "key": "hit_sub_count"}, + {"field_name": "HitSubTime", "type": "uint64", "key": "hit_sub_time"}, + {"field_name": "HTTP2", "type": "uint64", "key": "http2"}, + {"field_name": "ImgOpto", "type": "uint64", "key": "imgopto"}, + {"field_name": "ImgOptoRespBodyBytes", "type": "uint64", "key": "imgopto_resp_body_bytes"}, + {"field_name": "ImgOptoRespHeaderBytes", "type": "uint64", "key": "imgopto_resp_header_bytes"}, + {"field_name": "ImgOptoShield", "type": "uint64", "key": "imgopto_shield"}, + {"field_name": "ImgOptoShieldRespBodyBytes", "type": "uint64", "key": "imgopto_shield_resp_body_bytes"}, + {"field_name": "ImgOptoShieldRespHeaderBytes", "type": "uint64", "key": "imgopto_shield_resp_header_bytes"}, + {"field_name": "ImgOptoTransform", "type": "uint64", "key": "imgopto_transforms"}, + {"field_name": "ImgOptoTransformRespBodyBytes", "type": "uint64", "key": "imgopto_transform_resp_body_bytes"}, + {"field_name": "ImgOptoTransformRespHeaderBytes", "type": "uint64", "key": "imgopto_transform_resp_header_bytes"}, + {"field_name": "ImgVideo", "type": "uint64", "key": "imgvideo"}, + {"field_name": "ImgVideoFrames", "type": "uint64", "key": "imgvideo_frames"}, + {"field_name": "ImgVideoRespBodyBytes", "type": "uint64", "key": "imgvideo_resp_body_bytes"}, + {"field_name": "ImgVideoRespHeaderBytes", "type": "uint64", "key": "imgvideo_resp_header_bytes"}, + {"field_name": "ImgVideoShield", "type": "uint64", "key": "imgvideo_shield"}, + {"field_name": "ImgVideoShieldFrames", "type": "uint64", "key": "imgvideo_shield_frames"}, + {"field_name": "ImgVideoShieldRespBodyBytes", "type": "uint64", "key": "imgvideo_shield_resp_body_bytes"}, + {"field_name": "ImgVideoShieldRespHeaderBytes", "type": "uint64", "key": "imgvideo_shield_resp_header_bytes"}, + {"field_name": "IPv6", "type": "uint64", "key": "ipv6"}, + {"field_name": "LogBytes", "type": "uint64", "key": "log_bytes"}, + {"field_name": "Logging", "type": "uint64", "key": "logging"}, + {"field_name": "Misses", "type": "uint64", "key": "miss"}, + {"field_name": "MissHistogram", "type": "map[string]uint64", "key": "miss_histogram"}, + {"field_name": "MissRespBodyBytes", "type": "uint64", "key": "miss_resp_body_bytes"}, + {"field_name": "MissSubCount", "type": "uint64", "key": "miss_sub_count"}, + {"field_name": "MissSubTime", "type": "uint64", "key": "miss_sub_time"}, + {"field_name": "MissTime", "type": "float64", "key": "miss_time"}, + {"field_name": "ObjectSize100k", "type": "uint64", "key": "object_size_100k"}, + {"field_name": "ObjectSize100m", "type": "uint64", "key": "object_size_100m"}, + {"field_name": "ObjectSize10k", "type": "uint64", "key": "object_size_10k"}, + {"field_name": "ObjectSize10m", "type": "uint64", "key": "object_size_10m"}, + {"field_name": "ObjectSize1g", "type": "uint64", "key": "object_size_1g"}, + {"field_name": "ObjectSize1k", "type": "uint64", "key": "object_size_1k"}, + {"field_name": "ObjectSize1m", "type": "uint64", "key": "object_size_1m"}, + {"field_name": "ObjectSizeOther", "type": "uint64", "key": "object_size_other"}, + {"field_name": "OriginFetchBodyBytes", "type": "uint64", "key": "origin_fetch_body_bytes"}, + {"field_name": "OriginFetches", "type": "uint64", "key": "origin_fetches"}, + {"field_name": "OriginFetchHeaderBytes", "type": "uint64", "key": "origin_fetch_header_bytes"}, + {"field_name": "OriginFetchRespBodyBytes", "type": "uint64", "key": "origin_fetch_resp_body_bytes"}, + {"field_name": "OriginFetchRespHeaderBytes", "type": "uint64", "key": "origin_fetch_resp_header_bytes"}, + {"field_name": "OriginRevalidations", "type": "uint64", "key": "origin_revalidations"}, + {"field_name": "OTFP", "type": "uint64", "key": "otfp"}, + {"field_name": "OTFPDeliverTime", "type": "uint64", "key": "otfp_deliver_time"}, + {"field_name": "OTFPManifest", "type": "uint64", "key": "otfp_manifests"}, + {"field_name": "OTFPRespBodyBytes", "type": "uint64", "key": "otfp_resp_body_bytes"}, + {"field_name": "OTFPRespHeaderBytes", "type": "uint64", "key": "otfp_resp_header_bytes"}, + {"field_name": "OTFPShield", "type": "uint64", "key": "otfp_shield"}, + {"field_name": "OTFPShieldRespBodyBytes", "type": "uint64", "key": "otfp_shield_resp_body_bytes"}, + {"field_name": "OTFPShieldRespHeaderBytes", "type": "uint64", "key": "otfp_shield_resp_header_bytes"}, + {"field_name": "OTFPShieldTime", "type": "uint64", "key": "otfp_shield_time"}, + {"field_name": "OTFPTransform", "type": "uint64", "key": "otfp_transforms"}, + {"field_name": "OTFPTransformRespBodyBytes", "type": "uint64", "key": "otfp_transform_resp_body_bytes"}, + {"field_name": "OTFPTransformRespHeaderBytes", "type": "uint64", "key": "otfp_transform_resp_header_bytes"}, + {"field_name": "OTFPTransformTime", "type": "uint64", "key": "otfp_transform_time"}, + {"field_name": "Passes", "type": "uint64", "key": "pass"}, + {"field_name": "PassRespBodyBytes", "type": "uint64", "key": "pass_resp_body_bytes"}, + {"field_name": "PassSubCount", "type": "uint64", "key": "pass_sub_count"}, + {"field_name": "PassSubTime", "type": "uint64", "key": "pass_sub_time"}, + {"field_name": "PassTime", "type": "float64", "key": "pass_time"}, + {"field_name": "PCI", "type": "uint64", "key": "pci"}, + {"field_name": "PipeSubCount", "type": "uint64", "key": "pipe_sub_count"}, + {"field_name": "PipeSubTime", "type": "uint64", "key": "pipe_sub_time"}, + {"field_name": "PredeliverSubCount", "type": "uint64", "key": "predeliver_sub_count"}, + {"field_name": "PredeliverSubTime", "type": "uint64", "key": "predeliver_sub_time"}, + {"field_name": "PrehashSubCount", "type": "uint64", "key": "prehash_sub_count"}, + {"field_name": "PrehashSubTime", "type": "uint64", "key": "prehash_sub_time"}, + {"field_name": "RecvSubCount", "type": "uint64", "key": "recv_sub_count"}, + {"field_name": "RecvSubTime", "type": "uint64", "key": "recv_sub_time"}, + {"field_name": "ReqBodyBytes", "type": "uint64", "key": "req_body_bytes"}, + {"field_name": "ReqHeaderBytes", "type": "uint64", "key": "req_header_bytes"}, + {"field_name": "Requests", "type": "uint64", "key": "requests"}, + {"field_name": "RespBodyBytes", "type": "uint64", "key": "resp_body_bytes"}, + {"field_name": "RespHeaderBytes", "type": "uint64", "key": "resp_header_bytes"}, + {"field_name": "Restart", "type": "uint64", "key": "restarts"}, + {"field_name": "SegBlockOriginFetches", "type": "uint64", "key": "segblock_origin_fetches"}, + {"field_name": "SegBlockShieldFetches", "type": "uint64", "key": "segblock_shield_fetches"}, + {"field_name": "ShieldFetchBodyBytes", "type": "uint64", "key": "shield_fetch_body_bytes"}, + {"field_name": "Shield", "type": "uint64", "key": "shield"}, + {"field_name": "ShieldFetches", "type": "uint64", "key": "shield_fetches"}, + {"field_name": "ShieldFetchHeaderBytes", "type": "uint64", "key": "shield_fetch_header_bytes"}, + {"field_name": "ShieldFetchRespBodyBytes", "type": "uint64", "key": "shield_fetch_resp_body_bytes"}, + {"field_name": "ShieldFetchRespHeaderBytes", "type": "uint64", "key": "shield_fetch_resp_header_bytes"}, + {"field_name": "ShieldRespBodyBytes", "type": "uint64", "key": "shield_resp_body_bytes"}, + {"field_name": "ShieldRespHeaderBytes", "type": "uint64", "key": "shield_resp_header_bytes"}, + {"field_name": "ShieldRevalidations", "type": "uint64", "key": "shield_revalidations"}, + {"field_name": "Status1xx", "type": "uint64", "key": "status_1xx"}, + {"field_name": "Status200", "type": "uint64", "key": "status_200"}, + {"field_name": "Status204", "type": "uint64", "key": "status_204"}, + {"field_name": "Status206", "type": "uint64", "key": "status_206"}, + {"field_name": "Status2xx", "type": "uint64", "key": "status_2xx"}, + {"field_name": "Status301", "type": "uint64", "key": "status_301"}, + {"field_name": "Status302", "type": "uint64", "key": "status_302"}, + {"field_name": "Status304", "type": "uint64", "key": "status_304"}, + {"field_name": "Status3xx", "type": "uint64", "key": "status_3xx"}, + {"field_name": "Status400", "type": "uint64", "key": "status_400"}, + {"field_name": "Status401", "type": "uint64", "key": "status_401"}, + {"field_name": "Status403", "type": "uint64", "key": "status_403"}, + {"field_name": "Status404", "type": "uint64", "key": "status_404"}, + {"field_name": "Status416", "type": "uint64", "key": "status_416"}, + {"field_name": "Status429", "type": "uint64", "key": "status_429"}, + {"field_name": "Status4xx", "type": "uint64", "key": "status_4xx"}, + {"field_name": "Status500", "type": "uint64", "key": "status_500"}, + {"field_name": "Status501", "type": "uint64", "key": "status_501"}, + {"field_name": "Status502", "type": "uint64", "key": "status_502"}, + {"field_name": "Status503", "type": "uint64", "key": "status_503"}, + {"field_name": "Status504", "type": "uint64", "key": "status_504"}, + {"field_name": "Status505", "type": "uint64", "key": "status_505"}, + {"field_name": "Status5xx", "type": "uint64", "key": "status_5xx"}, + {"field_name": "Synths", "type": "uint64", "key": "synth"}, + {"field_name": "TLS", "type": "uint64", "key": "tls"}, + {"field_name": "TLSv10", "type": "uint64", "key": "tls_v10"}, + {"field_name": "TLSv11", "type": "uint64", "key": "tls_v11"}, + {"field_name": "TLSv12", "type": "uint64", "key": "tls_v12"}, + {"field_name": "TLSv13", "type": "uint64", "key": "tls_v13"}, + {"field_name": "Uncacheable", "type": "uint64", "key": "uncacheable"}, + {"field_name": "Video", "type": "uint64", "key": "video"}, + {"field_name": "WAFBlocked", "type": "uint64", "key": "waf_blocked"}, + {"field_name": "WAFLogged", "type": "uint64", "key": "waf_logged"}, + {"field_name": "WAFPassed", "type": "uint64", "key": "waf_passed"} +] \ No newline at end of file diff --git a/cmd/fieldgen/exporter_metrics.json b/cmd/fieldgen/exporter_metrics.json new file mode 100644 index 0000000..396e42d --- /dev/null +++ b/cmd/fieldgen/exporter_metrics.json @@ -0,0 +1,123 @@ +[ + {"field_name": "AttackBlockedReqBodyBytesTotal", "type": "Counter", "metric_name": "attack_blocked_req_body_bytes_total", "extra_labels": [], "help": "Total body bytes received from requests that triggered a WAF rule that was blocked."}, + {"field_name": "AttackBlockedReqHeaderBytesTotal", "type": "Counter", "metric_name": "attack_blocked_req_header_bytes_total", "extra_labels": [], "help": "Total header bytes received from requests that triggered a WAF rule that was blocked."}, + {"field_name": "AttackLoggedReqBodyBytesTotal", "type": "Counter", "metric_name": "attack_logged_req_body_bytes_total", "extra_labels": [], "help": "Total body bytes received from requests that triggered a WAF rule that was logged."}, + {"field_name": "AttackLoggedReqHeaderBytesTotal", "type": "Counter", "metric_name": "attack_logged_req_header_bytes_total", "extra_labels": [], "help": "Total header bytes received from requests that triggered a WAF rule that was logged."}, + {"field_name": "AttackPassedReqBodyBytesTotal", "type": "Counter", "metric_name": "attack_passed_req_body_bytes_total", "extra_labels": [], "help": "Total body bytes received from requests that triggered a WAF rule that was passed."}, + {"field_name": "AttackPassedReqHeaderBytesTotal", "type": "Counter", "metric_name": "attack_passed_req_header_bytes_total", "extra_labels": [], "help": "Total header bytes received from requests that triggered a WAF rule that was passed."}, + {"field_name": "AttackReqBodyBytesTotal", "type": "Counter", "metric_name": "attack_req_body_bytes_total", "extra_labels": [], "help": "Total body bytes received from requests that triggered a WAF rule."}, + {"field_name": "AttackReqHeaderBytesTotal", "type": "Counter", "metric_name": "attack_req_header_bytes_total", "extra_labels": [], "help": "Total header bytes received from requests that triggered a WAF rule."}, + {"field_name": "AttackRespSynthBytesTotal", "type": "Counter", "metric_name": "attack_resp_synth_bytes_total", "extra_labels": [], "help": "Total bytes delivered for requests that triggered a WAF rule and returned a synthetic response."}, + {"field_name": "BackendReqBodyBytesTotal", "type": "Counter", "metric_name": "bereq_body_bytes_total", "extra_labels": [], "help": "Total body bytes sent to origin."}, + {"field_name": "BackendReqHeaderBytesTotal", "type": "Counter", "metric_name": "bereq_header_bytes_total", "extra_labels": [], "help": "Total header bytes sent to origin."}, + {"field_name": "BilledBodyBytesTotal", "type": "Counter", "metric_name": "billed_body_bytes_total", "extra_labels": [], "help": "TODO"}, + {"field_name": "BilledHeaderBytesTotal", "type": "Counter", "metric_name": "billed_header_bytes_total", "extra_labels": [], "help": "TODO"}, + {"field_name": "BilledTotal", "type": "Counter", "metric_name": "billed_total", "extra_labels": [], "help": "TODO"}, + {"field_name": "BlacklistedTotal", "type": "Counter", "metric_name": "blacklist_total", "extra_labels": [], "help": "TODO"}, + {"field_name": "BodySizeTotal", "type": "Counter", "metric_name": "body_size_total", "extra_labels": [], "help": "Total body bytes delivered (alias for resp_body_bytes)."}, + {"field_name": "DeliverSubCountTotal", "type": "Counter", "metric_name": "deliver_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'deliver' Varnish subroutine."}, + {"field_name": "DeliverSubTimeTotal", "type": "Counter", "metric_name": "deliver_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'deliver' Varnish subroutine (in seconds)."}, + {"field_name": "EdgeRespBodyBytesTotal", "type": "Counter", "metric_name": "edge_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered from Fastly to the end user."}, + {"field_name": "EdgeRespHeaderBytesTotal", "type": "Counter", "metric_name": "edge_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes delivered from Fastly to the end user."}, + {"field_name": "EdgeTotal", "type": "Counter", "metric_name": "edge_total", "extra_labels": [], "help": "Number of requests sent by end users to Fastly."}, + {"field_name": "ErrorSubCountTotal", "type": "Counter", "metric_name": "error_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'error' Varnish subroutine."}, + {"field_name": "ErrorSubTimeTotal", "type": "Counter", "metric_name": "error_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'error' Varnish subroutine (in seconds)."}, + {"field_name": "ErrorsTotal", "type": "Counter", "metric_name": "errors_total", "extra_labels": [], "help": "Number of cache errors."}, + {"field_name": "FetchSubCountTotal", "type": "Counter", "metric_name": "fetch_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'fetch' Varnish subroutine."}, + {"field_name": "FetchSubTimeTotal", "type": "Counter", "metric_name": "fetch_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'fetch' Varnish subroutine (in seconds)."}, + {"field_name": "HTTP2Total", "type": "Counter", "metric_name": "http2_total", "extra_labels": [], "help": "Number of requests received over HTTP2."}, + {"field_name": "HashSubCountTotal", "type": "Counter", "metric_name": "hash_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'hash' Varnish subroutine."}, + {"field_name": "HashSubTimeTotal", "type": "Counter", "metric_name": "hash_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'hash' Varnish subroutine (in seconds)."}, + {"field_name": "HeaderSizeTotal", "type": "Counter", "metric_name": "header_size_total", "extra_labels": [], "help": "Total header bytes delivered (alias for resp_header_bytes)."}, + {"field_name": "HitRespBodyBytesTotal", "type": "Counter", "metric_name": "hit_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered for cache hits."}, + {"field_name": "HitSubCountTotal", "type": "Counter", "metric_name": "hit_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'hit' Varnish subroutine."}, + {"field_name": "HitSubTimeTotal", "type": "Counter", "metric_name": "hit_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'hit' Varnish subroutine (in seconds)."}, + {"field_name": "HitsTimeTotal", "type": "Counter", "metric_name": "hits_time_total", "extra_labels": [], "help": "Total amount of time spent processing cache hits (in seconds)."}, + {"field_name": "HitsTotal", "type": "Counter", "metric_name": "hits_total", "extra_labels": [], "help": "Number of cache hits."}, + {"field_name": "IPv6Total", "type": "Counter", "metric_name": "ipv6_total", "extra_labels": [], "help": "Number of requests that were received over IPv6."}, + {"field_name": "ImgOptoRespBodyBytesTotal", "type": "Counter", "metric_name": "imgopto_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered from the Fastly Image Optimizer service."}, + {"field_name": "ImgOptoRespHeaderBytesTotal", "type": "Counter", "metric_name": "imgopto_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes delivered from the Fastly Image Optimizer service."}, + {"field_name": "ImgOptoShieldRespBodyBytesTotal", "type": "Counter", "metric_name": "imgopto_shield_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered via a shield from the Fastly Image Optimizer service."}, + {"field_name": "ImgOptoShieldRespHeaderBytesTotal", "type": "Counter", "metric_name": "imgopto_shield_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes delivered via a shield from the Fastly Image Optimizer service."}, + {"field_name": "ImgOptoShieldTotal", "type": "Counter", "metric_name": "imgopto_shield_total", "extra_labels": [], "help": "Number of responses delivered via a shield from the Fastly Image Optimizer service."}, + {"field_name": "ImgOptoTotal", "type": "Counter", "metric_name": "imgopto_total", "extra_labels": [], "help": "Number of responses that came from the Fastly Image Optimizer service."}, + {"field_name": "ImgOptoTransformRespBodyBytesTotal", "type": "Counter", "metric_name": "imgopto_transform_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes of transforms delivered from the Fastly Image Optimizer service."}, + {"field_name": "ImgOptoTransformRespHeaderBytesTotal", "type": "Counter", "metric_name": "imgopto_transform_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes of transforms delivered from the Fastly Image Optimizer service."}, + {"field_name": "ImgOptoTransformTotal", "type": "Counter", "metric_name": "imgopto_transforms_total", "extra_labels": [], "help": "Total transforms performed by the Fastly Image Optimizer service."}, + {"field_name": "ImgVideoFramesTotal", "type": "Counter", "metric_name": "imgvideo_frames_total", "extra_labels": [], "help": "Number of video frames that came from the Fastly Image Optimizer service."}, + {"field_name": "ImgVideoRespBodyBytesTotal", "type": "Counter", "metric_name": "imgvideo_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes of video delivered from the Fastly Image Optimizer service."}, + {"field_name": "ImgVideoRespHeaderBytesTotal", "type": "Counter", "metric_name": "imgvideo_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes of video delivered from the Fastly Image Optimizer service."}, + {"field_name": "ImgVideoShieldFramesTotal", "type": "Counter", "metric_name": "imgvideo_shield_frames_total", "extra_labels": [], "help": "Number of video frames delivered via a shield from the Fastly Image Optimizer service."}, + {"field_name": "ImgVideoShieldRespBodyBytesTotal", "type": "Counter", "metric_name": "imgvideo_shield_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes of video delivered via a shield from the Fastly Image Optimizer service."}, + {"field_name": "ImgVideoShieldRespHeaderBytesTotal", "type": "Counter", "metric_name": "imgvideo_shield_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes of video delivered via a shield from the Fastly Image Optimizer service."}, + {"field_name": "ImgVideoShieldTotal", "type": "Counter", "metric_name": "imgvideo_shield_total", "extra_labels": [], "help": "Number of video responses that came via a shield from the Fastly Image Optimizer service."}, + {"field_name": "ImgVideoTotal", "type": "Counter", "metric_name": "imgvideo_total", "extra_labels": [], "help": "Number of video responses that came via a shield from the Fastly Image Optimizer service."}, + {"field_name": "LogBytesTotal", "type": "Counter", "metric_name": "log_bytes_total", "extra_labels": [], "help": "Total log bytes sent."}, + {"field_name": "LoggingTotal", "type": "Counter", "metric_name": "logging_total", "extra_labels": [], "help": "Number of log lines sent."}, + {"field_name": "MissDurationSeconds", "type": "Histogram", "metric_name": "miss_duration_seconds", "extra_labels": [], "help": "Histogram of time spent processing cache misses (in seconds)."}, + {"field_name": "MissRespBodyBytesTotal", "type": "Counter", "metric_name": "miss_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered for cache misses."}, + {"field_name": "MissSubCountTotal", "type": "Counter", "metric_name": "miss_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'miss' Varnish subroutine."}, + {"field_name": "MissSubTimeTotal", "type": "Counter", "metric_name": "miss_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'miss' Varnish subroutine (in seconds)."}, + {"field_name": "MissTimeTotal", "type": "Counter", "metric_name": "miss_time_total", "extra_labels": [], "help": "Total amount of time spent processing cache misses (in seconds)."}, + {"field_name": "MissesTotal", "type": "Counter", "metric_name": "miss_total", "extra_labels": [], "help": "Number of cache misses."}, + {"field_name": "OTFPDeliverTimeTotal", "type": "Counter", "metric_name": "otfp_total", "extra_labels": [], "help": "Number of responses that came from the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPManifestTotal", "type": "Counter", "metric_name": "otfp_deliver_time_total", "extra_labels": [], "help": "Total amount of time spent delivering a response from the Fastly On-the-Fly Packager (in seconds)."}, + {"field_name": "OTFPRespBodyBytesTotal", "type": "Counter", "metric_name": "otfp_manifests_total", "extra_labels": [], "help": "Number of responses that were manifest files from the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPRespHeaderBytesTotal", "type": "Counter", "metric_name": "otfp_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered from the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPShieldRespBodyBytesTotal", "type": "Counter", "metric_name": "otfp_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes delivered from the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPShieldRespHeaderBytesTotal", "type": "Counter", "metric_name": "otfp_shield_total", "extra_labels": [], "help": "Number of responses delivered from the Fastly On-the-Fly Packager"}, + {"field_name": "OTFPShieldTimeTotal", "type": "Counter", "metric_name": "otfp_shield_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered via a shield for the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPShieldTotal", "type": "Counter", "metric_name": "otfp_shield_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes delivered via a shield for the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPTotal", "type": "Counter", "metric_name": "otfp_shield_time_total", "extra_labels": [], "help": "Total amount of time spent delivering a response via a shield from the Fastly On-the-Fly Packager (in seconds)."}, + {"field_name": "OTFPTransformRespBodyBytesTotal", "type": "Counter", "metric_name": "otfp_transforms_total", "extra_labels": [], "help": "Number of transforms performed by the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPTransformRespHeaderBytesTotal", "type": "Counter", "metric_name": "otfp_transform_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes of transforms delivered from the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPTransformTimeTotal", "type": "Counter", "metric_name": "otfp_transform_resp_header_bytes_total", "extra_labels": [], "help": "Total body bytes of transforms delivered from the Fastly On-the-Fly Packager."}, + {"field_name": "OTFPTransformTotal", "type": "Counter", "metric_name": "otfp_transform_time_total", "extra_labels": [], "help": "Total amount of time spent performing transforms from the Fastly On-the-Fly Packager."}, + {"field_name": "ObjectSizeBytes", "type": "Histogram", "metric_name": "object_size_bytes", "extra_labels": [], "help": "Histogram of count of objects served, bucketed by object size range."}, + {"field_name": "OriginFetchBodyBytesTotal", "type": "Counter", "metric_name": "origin_fetch_body_bytes_total", "extra_labels": [], "help": "Total request body bytes sent to origin."}, + {"field_name": "OriginFetchHeaderBytesTotal", "type": "Counter", "metric_name": "origin_fetch_header_bytes_total", "extra_labels": [], "help": "Total request header bytes sent to origin."}, + {"field_name": "OriginFetchRespBodyBytesTotal", "type": "Counter", "metric_name": "origin_fetch_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes received from origin."}, + {"field_name": "OriginFetchRespHeaderBytesTotal", "type": "Counter", "metric_name": "origin_fetch_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes received from origin."}, + {"field_name": "OriginFetchesTotal", "type": "Counter", "metric_name": "origin_fetches_total", "extra_labels": [], "help": "Number of requests sent to origin."}, + {"field_name": "OriginRevalidationsTotal", "type": "Counter", "metric_name": "origin_revalidations_total", "extra_labels": [], "help": "Number of responses received from origin with a 304 status code in response to an If-Modified-Since or If-None-Match request. Under regular scenarios, a revalidation will imply a cache hit. However, if using Fastly Image Optimizer or segmented caching this may result in a cache miss."}, + {"field_name": "PCITotal", "type": "Counter", "metric_name": "pci_total", "extra_labels": [], "help": "Number of responses with the PCI flag turned on."}, + {"field_name": "PassRespBodyBytesTotal", "type": "Counter", "metric_name": "pass_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered for cache passes."}, + {"field_name": "PassSubCountTotal", "type": "Counter", "metric_name": "pass_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'pass' Varnish subroutine."}, + {"field_name": "PassSubTimeTotal", "type": "Counter", "metric_name": "pass_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'pass' Varnish subroutine (in seconds)."}, + {"field_name": "PassTimeTotal", "type": "Counter", "metric_name": "pass_time_total", "extra_labels": [], "help": "Total amount of time spent processing cache passes (in seconds)."}, + {"field_name": "PassesTotal", "type": "Counter", "metric_name": "pass_total", "extra_labels": [], "help": "Number of requests that passed through the CDN without being cached."}, + {"field_name": "PipeSubCountTotal", "type": "Counter", "metric_name": "pipe_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'pipe' Varnish subroutine."}, + {"field_name": "PipeSubTimeTotal", "type": "Counter", "metric_name": "pipe_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'pipe' Varnish subroutine (in seconds)."}, + {"field_name": "PredeliverSubCountTotal", "type": "Counter", "metric_name": "predeliver_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'predeliver' Varnish subroutine."}, + {"field_name": "PredeliverSubTimeTotal", "type": "Counter", "metric_name": "predeliver_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'predeliver' Varnish subroutine (in seconds)."}, + {"field_name": "PrehashSubCountTotal", "type": "Counter", "metric_name": "prehash_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'prehash' Varnish subroutine."}, + {"field_name": "PrehashSubTimeTotal", "type": "Counter", "metric_name": "prehash_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'prehash' Varnish subroutine (in seconds)."}, + {"field_name": "RecvSubCountTotal", "type": "Counter", "metric_name": "recv_sub_count_total", "extra_labels": [], "help": "Number of executions of the 'recv' Varnish subroutine."}, + {"field_name": "RecvSubTimeTotal", "type": "Counter", "metric_name": "recv_sub_time_total", "extra_labels": [], "help": "Time spent inside the 'recv' Varnish subroutine (in seconds)."}, + {"field_name": "ReqBodyBytesTotal", "type": "Counter", "metric_name": "req_body_bytes_total", "extra_labels": [], "help": "Total body bytes received."}, + {"field_name": "ReqHeaderBytesTotal", "type": "Counter", "metric_name": "req_header_bytes_total", "extra_labels": [], "help": "Total header bytes received."}, + {"field_name": "RequestsTotal", "type": "Counter", "metric_name": "requests_total", "extra_labels": [], "help": "Number of requests processed."}, + {"field_name": "RespBodyBytesTotal", "type": "Counter", "metric_name": "resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered."}, + {"field_name": "RespHeaderBytesTotal", "type": "Counter", "metric_name": "resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes delivered."}, + {"field_name": "RestartTotal", "type": "Counter", "metric_name": "restarts_total", "extra_labels": [], "help": "Number of restarts performed."}, + {"field_name": "SegBlockOriginFetchesTotal", "type": "Counter", "metric_name": "segblock_origin_fetches_total", "extra_labels": [], "help": "Number of Range requests to origin for segments of resources when using segmented caching."}, + {"field_name": "SegBlockShieldFetchesTotal", "type": "Counter", "metric_name": "segblock_shield_fetches_total", "extra_labels": [], "help": "Number of Range requests to a shield for segments of resources when using segmented caching."}, + {"field_name": "ShieldFetchBodyBytesTotal", "type": "Counter", "metric_name": "shield_fetch_body_bytes_total", "extra_labels": [], "help": "Total request body bytes sent to a shield."}, + {"field_name": "ShieldFetchHeaderBytesTotal", "type": "Counter", "metric_name": "shield_fetch_header_bytes_total", "extra_labels": [], "help": "Total request header bytes sent to a shield."}, + {"field_name": "ShieldFetchRespBodyBytesTotal", "type": "Counter", "metric_name": "shield_fetch_resp_body_bytes_total", "extra_labels": [], "help": "Total response body bytes sent from a shield to the edge."}, + {"field_name": "ShieldFetchRespHeaderBytesTotal", "type": "Counter", "metric_name": "shield_fetch_resp_header_bytes_total", "extra_labels": [], "help": "Total response header bytes sent from a shield to the edge."}, + {"field_name": "ShieldFetchesTotal", "type": "Counter", "metric_name": "shield_fetches_total", "extra_labels": [], "help": "Number of requests made from one Fastly data center to another, as part of shielding."}, + {"field_name": "ShieldRespBodyBytesTotal", "type": "Counter", "metric_name": "shield_resp_body_bytes_total", "extra_labels": [], "help": "Total body bytes delivered via a shield."}, + {"field_name": "ShieldRespHeaderBytesTotal", "type": "Counter", "metric_name": "shield_resp_header_bytes_total", "extra_labels": [], "help": "Total header bytes delivered via a shield."}, + {"field_name": "ShieldRevalidationsTotal", "type": "Counter", "metric_name": "shield_revalidations_total", "extra_labels": [], "help": "Number of responses received from origin with a 304 status code, in response to an If-Modified-Since or If-None-Match request to a shield. Under regular scenarios, a revalidation will imply a cache hit. However, if using segmented caching this may result in a cache miss."}, + {"field_name": "ShieldTotal", "type": "Counter", "metric_name": "shield_total", "extra_labels": [], "help": "Number of requests from edge to the shield POP."}, + {"field_name": "StatusCodeTotal", "type": "Counter", "metric_name": "status_code_total", "extra_labels": ["status_code"], "help": "Number of responses sent with status code 500 (Internal Server Error)."}, + {"field_name": "StatusGroupTotal", "type": "Counter", "metric_name": "status_group_total", "extra_labels": ["status_group"], "help": "Number of 'Client Error' category status codes delivered."}, + {"field_name": "SynthsTotal", "type": "Counter", "metric_name": "synth_total", "extra_labels": [], "help": "TODO"}, + {"field_name": "TLSTotal", "type": "Counter", "metric_name": "tls_total", "extra_labels": ["tls_version"], "help": "Number of requests that were received over TLS."}, + {"field_name": "UncacheableTotal", "type": "Counter", "metric_name": "uncacheable_total", "extra_labels": [], "help": "Number of requests that were designated uncachable."}, + {"field_name": "VideoTotal", "type": "Counter", "metric_name": "video_total", "extra_labels": [], "help": "Number of responses with the video segment or video manifest MIME type (i.e., application/x-mpegurl, application/vnd.apple.mpegurl, application/f4m, application/dash+xml, application/vnd.ms-sstr+xml, ideo/mp2t, audio/aac, video/f4f, video/x-flv, video/mp4, audio/mp4)."}, + {"field_name": "WAFBlockedTotal", "type": "Counter", "metric_name": "waf_blocked_total", "extra_labels": [], "help": "Number of requests that triggered a WAF rule and were blocked."}, + {"field_name": "WAFLoggedTotal", "type": "Counter", "metric_name": "waf_logged_total", "extra_labels": [], "help": "Number of requests that triggered a WAF rule and were logged."}, + {"field_name": "WAFPassedTotal", "type": "Counter", "metric_name": "waf_passed_total", "extra_labels": [], "help": "Number of requests that triggered a WAF rule and were passed."} +] diff --git a/cmd/fieldgen/main.go b/cmd/fieldgen/main.go new file mode 100644 index 0000000..7068ef8 --- /dev/null +++ b/cmd/fieldgen/main.go @@ -0,0 +1,294 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "os" + "strings" +) + +func main() { + if err := exec(); err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } +} + +func exec() error { + fs := flag.NewFlagSet("fieldgen", flag.ExitOnError) + var ( + metricsFile = fs.String("metrics", "exporter_metrics.json", "JSON file containing metric definitions") + fieldsFile = fs.String("fields", "api_fields.json", "JSON file containing API field definitions") + mappingsFile = fs.String("mappings", "mappings.json", "JSON file containing metric-to-field mappings") + invalid = fs.Bool("invalid", false, "skip validations") + ) + fs.Parse(os.Args[1:]) + + var metrics []exporterMetric + if err := readJSON(*metricsFile, &metrics); err != nil { + return err + } + + if !*invalid { + var noHelp []string + for _, m := range metrics { + if m.Help == "" || strings.Contains(m.Help, "TODO") { + noHelp = append(noHelp, m.FieldName) + } + } + if len(noHelp) > 0 { + return fmt.Errorf("metrics with undefined Help strings: %s", strings.Join(noHelp, ", ")) + } + } + + var fields []apiField + if err := readJSON(*fieldsFile, &fields); err != nil { + return err + } + + var mappings []mapping + if err := readJSON(*mappingsFile, &mappings); err != nil { + return err + } + + if !*invalid { + unmappedAPIFields := map[string]bool{} + for _, f := range fields { + unmappedAPIFields[f.FieldName] = true + } + for _, m := range mappings { + delete(unmappedAPIFields, m.APIField) + for _, pair := range m.APIFieldLabels { + delete(unmappedAPIFields, pair[0]) + } + for _, f := range m.APIFieldSizes { + delete(unmappedAPIFields, f) + } + } + if len(unmappedAPIFields) > 0 { + var names []string + for f := range unmappedAPIFields { + names = append(names, f) + } + return fmt.Errorf("unmapped API fields: %s", strings.Join(names, ", ")) + } + } + + fmt.Printf("// Code generated by fieldgen; DO NOT EDIT.\n") + fmt.Printf("\n") + fmt.Printf("package gen\n") + fmt.Printf("\n") + fmt.Printf("%s\n", importBlock) + fmt.Printf("\n") + fmt.Printf("%s\n", apiResponseBlock) + fmt.Printf("\n") + fmt.Printf("// Datacenter models the per-datacenter portion of the rt.fastly.com response.\n") + fmt.Printf("type Datacenter struct {\n") + for _, f := range fields { + fmt.Printf("\t%s %s `json:\"%s\"`\n", f.FieldName, f.Type, f.Key) + } + fmt.Printf("}\n") + fmt.Printf("\n") + fmt.Printf("// Metrics collects all of the Prometheus metrics exported by this service.\n") + fmt.Printf("type Metrics struct {\n") + fmt.Printf("\tRealtimeAPIRequestsTotal *prometheus.CounterVec\n") + fmt.Printf("\tServiceInfo *prometheus.GaugeVec\n") + for _, m := range metrics { + fmt.Printf("\t%s *prometheus.%sVec\n", m.FieldName, m.Type) + } + fmt.Printf("}\n") + fmt.Printf("\n") + fmt.Printf("// NewMetrics returns a new set of metrics registered to the registerer.\n") + fmt.Printf("// Only metrics whose names pass the name filter are registered.\n") + fmt.Printf("func NewMetrics(namespace, subsystem string, nameFilter filter.Filter, r prometheus.Registerer) (*Metrics, error) {\n") + fmt.Printf("\tm := Metrics{\n") + fmt.Printf("\t\t" + `RealtimeAPIRequestsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "realtime_api_requests_total", Help: "Total requests made to the real-time stats API.", }, []string{"service_id", "service_name", "result"}),` + "\n") + fmt.Printf("\t\t" + `ServiceInfo: prometheus.NewGaugeVec(prometheus.GaugeOpts{Namespace: namespace, Subsystem: subsystem, Name: "service_info", Help: "Static gauge with service ID, name, and version information.", }, []string{"service_id", "service_name", "service_version"}),` + "\n") + for _, m := range metrics { + fmt.Printf("\t\t%s: %s,\n", m.FieldName, m.create()) + } + fmt.Printf("\t}\n") + fmt.Printf("\n") + fmt.Printf("%s\n", registerBlock) + fmt.Printf("\treturn &m, nil\n") + fmt.Printf("}\n\n") + fmt.Printf("%s\n", getNameBlock) + fmt.Printf("\n") + fmt.Printf("// Process updates the metrics with data from the API response.\n") + fmt.Printf("func Process(response *APIResponse, serviceID, serviceName, serviceVersion string, m *Metrics) {\n") + fmt.Printf("\tfor _, d := range response.Data {\n") + fmt.Printf("\t\tfor datacenter, stats := range d.Datacenter {\n") + fmt.Printf("\t\t\tm.ServiceInfo.WithLabelValues(serviceID, serviceName, serviceVersion).Set(1)\n") + fmt.Printf("\t\t\tm.RequestsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Requests))\n") + for _, m := range mappings { + switch m.Kind { + case "Counter": + fmt.Printf("\t\t\tm.%s.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.%s))\n", m.ExporterMetric, m.APIField) + case "CounterLabels": + for _, pair := range m.APIFieldLabels { + fmt.Printf("\t\t\tm.%s.WithLabelValues(serviceID, serviceName, datacenter, \"%s\").Add(float64(stats.%s))\n", m.ExporterMetric, pair[1], pair[0]) + } + case "Histogram": + fmt.Printf("\t\t\tprocessHistogram(stats.%s, m.%s.WithLabelValues(serviceID, serviceName, datacenter))\n", m.APIField, m.ExporterMetric) + case "ObjectSize": + fmt.Printf("\t\t\tprocessObjectSizes(stats.ObjectSize1k, stats.ObjectSize10k, stats.ObjectSize100k, stats.ObjectSize1m, stats.ObjectSize10m, stats.ObjectSize100m, stats.ObjectSize1g, m.%s.WithLabelValues(serviceID, serviceName, datacenter))\n", m.ExporterMetric) // hacky hack + case "Ignored": + // + default: + fmt.Printf("\t\t\t// %s: unknown mapping kind %q\n", m.ExporterMetric, m.Kind) + } + } + fmt.Printf("\t\t}\n") + fmt.Printf("\t}\n") + fmt.Printf("}\n") + fmt.Printf("\n") + fmt.Printf("%s\n", processBlock) + return nil +} + +func readJSON(filename string, data interface{}) error { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + + return json.NewDecoder(f).Decode(data) +} + +type exporterMetric struct { + FieldName string `json:"field_name"` + Type string `json:"type"` + MetricName string `json:"metric_name"` + ExtraLabels []string `json:"extra_labels"` + Help string `json:"help"` +} + +var standardLabels = []string{"service_id", "service_name", "datacenter"} + +func quoteList(a []string) string { + b := make([]string, len(a)) + for i, s := range a { + b[i] = `"` + s + `"` + } + return strings.Join(b, ", ") +} + +func (m exporterMetric) create() string { + var ( + constructor = fmt.Sprintf("prometheus.New%sVec", m.Type) + options = fmt.Sprintf("prometheus.%sOpts", m.Type) + constLabels = quoteList(append(standardLabels, m.ExtraLabels...)) + ) + return fmt.Sprintf( + `%s(%s{Namespace: namespace, Subsystem: subsystem, Name: "%s", Help: "%s"}, []string{%s})`, + constructor, options, m.MetricName, m.Help, constLabels, + ) +} + +type apiField struct { + FieldName string `json:"field_name"` + Type string `json:"type"` + Key string `json:"key"` +} + +type mapping struct { + ExporterMetric string `json:"exporter_metric"` + Kind string `json:"kind"` + APIField string `json:"api_field"` // kind=Counter, kind=Histogram + APIFieldLabels [][2]string `json:"api_field_labels"` // Kind=CounterLabels + APIFieldSizes []string `json:"api_field_sizes"` // kind=ObjectSize +} + +// +// +// + +const importBlock = ` +import ( + "fmt" + "reflect" + "regexp" + "strconv" + + "github.com/peterbourgon/fastly-exporter/pkg/filter" + "github.com/prometheus/client_golang/prometheus" +) +` + +var apiResponseBlock = strings.Replace(` +// APIResponse models the response from rt.fastly.com. It can get quite large; +// when there are lots of services being monitored, unmarshaling to this type is +// the CPU bottleneck of the program. +type APIResponse struct { + Timestamp uint64 ·json:"Timestamp"· + Data []struct { + Datacenter map[string]Datacenter ·json:"datacenter"· + Aggregated Datacenter ·json:"aggregated"· + Recorded uint64 ·json:"recorded"· + } ·json:"Data"· + Error string ·json:"error"· +} +`, "·", "`", -1) + +const getNameBlock = ` +var descNameRegex = regexp.MustCompile("fqName: \"([^\"]+)\"") + +func getName(c prometheus.Collector) string { + d := make(chan *prometheus.Desc, 1) + c.Describe(d) + desc := (<-d).String() + matches := descNameRegex.FindAllStringSubmatch(desc, -1) + if len(matches) == 1 && len(matches[0]) == 2 { + return matches[0][1] + } + return "" +} +` + +const processBlock = ` +func processHistogram(src map[string]uint64, obs prometheus.Observer) { + for str, count := range src { + ms, err := strconv.Atoi(str) + if err != nil { + continue + } + s := float64(ms) / 1e3 + for i := 0; i < int(count); i++ { + obs.Observe(s) + } + } +} + +func processObjectSizes(n1k, n10k, n100k, n1m, n10m, n100m, n1g uint64, obs prometheus.Observer) { + for v, n := range map[uint64]uint64{ + 1 * 1024: n1k, + 10 * 1024: n10k, + 100 * 1024: n100k, + 1 * 1000 * 1024: n1m, + 10 * 1000 * 1024: n10m, + 100 * 1000 * 1024: n100m, + 1000 * 1000 * 1024: n1g, + } { + for i := uint64(0); i < n; i++ { + obs.Observe(float64(v)) + } + } +} +` + +const registerBlock = ` +for i, v := 0, reflect.ValueOf(m); i < v.NumField(); i++ { + c, ok := v.Field(i).Interface().(prometheus.Collector) + if !ok { + panic(fmt.Sprintf("programmer error: field %d/%d in Metrics type isn't a prometheus.Collector", i+1, v.NumField())) + } + if name := getName(c); !nameFilter.Permit(name) { + continue + } + if err := r.Register(c); err != nil { + return nil, fmt.Errorf("error registering metric %d/%d: %w", i+1, v.NumField(), err) + } +} +` diff --git a/cmd/fieldgen/mappings.json b/cmd/fieldgen/mappings.json new file mode 100644 index 0000000..9510a75 --- /dev/null +++ b/cmd/fieldgen/mappings.json @@ -0,0 +1,124 @@ +[ + {"exporter_metric": "AttackBlockedReqBodyBytesTotal", "kind": "Counter", "api_field": "AttackBlockedReqBodyBytes"}, + {"exporter_metric": "AttackBlockedReqHeaderBytesTotal", "kind": "Counter", "api_field": "AttackBlockedReqHeaderBytes"}, + {"exporter_metric": "AttackLoggedReqBodyBytesTotal", "kind": "Counter", "api_field": "AttackLoggedReqBodyBytes"}, + {"exporter_metric": "AttackLoggedReqHeaderBytesTotal", "kind": "Counter", "api_field": "AttackLoggedReqHeaderBytes"}, + {"exporter_metric": "AttackPassedReqBodyBytesTotal", "kind": "Counter", "api_field": "AttackPassedReqBodyBytes"}, + {"exporter_metric": "AttackPassedReqHeaderBytesTotal", "kind": "Counter", "api_field": "AttackPassedReqHeaderBytes"}, + {"exporter_metric": "AttackReqBodyBytesTotal", "kind": "Counter", "api_field": "AttackReqBodyBytes"}, + {"exporter_metric": "AttackReqHeaderBytesTotal", "kind": "Counter", "api_field": "AttackReqHeaderBytes"}, + {"exporter_metric": "AttackRespSynthBytesTotal", "kind": "Counter", "api_field": "AttackRespSynthBytes"}, + {"exporter_metric": "BackendReqBodyBytesTotal", "kind": "Counter", "api_field": "BackendReqBodyBytes"}, + {"exporter_metric": "BackendReqHeaderBytesTotal", "kind": "Counter", "api_field": "BackendReqHeaderBytes"}, + {"exporter_metric": "BilledBodyBytesTotal", "kind": "Counter", "api_field": "BilledBodyBytes"}, + {"exporter_metric": "BilledHeaderBytesTotal", "kind": "Counter", "api_field": "BilledHeaderBytes"}, + {"exporter_metric": "BilledTotal", "kind": "Counter", "api_field": "Billed"}, + {"exporter_metric": "BlacklistedTotal", "kind": "Counter", "api_field": "Blacklisted"}, + {"exporter_metric": "BodySizeTotal", "kind": "Counter", "api_field": "BodySize"}, + {"exporter_metric": "DeliverSubCountTotal", "kind": "Counter", "api_field": "DeliverSubCount"}, + {"exporter_metric": "DeliverSubTimeTotal", "kind": "Counter", "api_field": "DeliverSubTime"}, + {"exporter_metric": "EdgeRespBodyBytesTotal", "kind": "Counter", "api_field": "EdgeRespBodyBytes"}, + {"exporter_metric": "EdgeRespHeaderBytesTotal", "kind": "Counter", "api_field": "EdgeRespHeaderBytes"}, + {"exporter_metric": "EdgeTotal", "kind": "Counter", "api_field": "Edge"}, + {"exporter_metric": "ErrorSubCountTotal", "kind": "Counter", "api_field": "ErrorSubCount"}, + {"exporter_metric": "ErrorSubTimeTotal", "kind": "Counter", "api_field": "ErrorSubTime"}, + {"exporter_metric": "ErrorsTotal", "kind": "Counter", "api_field": "Errors"}, + {"exporter_metric": "FetchSubCountTotal", "kind": "Counter", "api_field": "FetchSubCount"}, + {"exporter_metric": "FetchSubTimeTotal", "kind": "Counter", "api_field": "FetchSubTime"}, + {"exporter_metric": "HTTP2Total", "kind": "Counter", "api_field": "HTTP2"}, + {"exporter_metric": "HashSubCountTotal", "kind": "Counter", "api_field": "HashSubCount"}, + {"exporter_metric": "HashSubTimeTotal", "kind": "Counter", "api_field": "HashSubTime"}, + {"exporter_metric": "HeaderSizeTotal", "kind": "Counter", "api_field": "HeaderSize"}, + {"exporter_metric": "HitRespBodyBytesTotal", "kind": "Counter", "api_field": "HitRespBodyBytes"}, + {"exporter_metric": "HitSubCountTotal", "kind": "Counter", "api_field": "HitSubCount"}, + {"exporter_metric": "HitSubTimeTotal", "kind": "Counter", "api_field": "HitSubTime"}, + {"exporter_metric": "HitsTimeTotal", "kind": "Counter", "api_field": "HitsTime"}, + {"exporter_metric": "HitsTotal", "kind": "Counter", "api_field": "Hits"}, + {"exporter_metric": "IPv6Total", "kind": "Counter", "api_field": "IPv6"}, + {"exporter_metric": "ImgOptoRespBodyBytesTotal", "kind": "Counter", "api_field": "ImgOptoRespBodyBytes"}, + {"exporter_metric": "ImgOptoRespHeaderBytesTotal", "kind": "Counter", "api_field": "ImgOptoRespHeaderBytes"}, + {"exporter_metric": "ImgOptoShieldRespBodyBytesTotal", "kind": "Counter", "api_field": "ImgOptoShieldRespBodyBytes"}, + {"exporter_metric": "ImgOptoShieldRespHeaderBytesTotal", "kind": "Counter", "api_field": "ImgOptoShieldRespHeaderBytes"}, + {"exporter_metric": "ImgOptoShieldTotal", "kind": "Counter", "api_field": "ImgOptoShield"}, + {"exporter_metric": "ImgOptoTotal", "kind": "Counter", "api_field": "ImgOpto"}, + {"exporter_metric": "ImgOptoTransformRespBodyBytesTotal", "kind": "Counter", "api_field": "ImgOptoTransformRespBodyBytes"}, + {"exporter_metric": "ImgOptoTransformRespHeaderBytesTotal", "kind": "Counter", "api_field": "ImgOptoTransformRespHeaderBytes"}, + {"exporter_metric": "ImgOptoTransformTotal", "kind": "Counter", "api_field": "ImgOptoTransform"}, + {"exporter_metric": "ImgVideoFramesTotal", "kind": "Counter", "api_field": "ImgVideoFrames"}, + {"exporter_metric": "ImgVideoRespBodyBytesTotal", "kind": "Counter", "api_field": "ImgVideoRespBodyBytes"}, + {"exporter_metric": "ImgVideoRespHeaderBytesTotal", "kind": "Counter", "api_field": "ImgVideoRespHeaderBytes"}, + {"exporter_metric": "ImgVideoShieldFramesTotal", "kind": "Counter", "api_field": "ImgVideoShieldFrames"}, + {"exporter_metric": "ImgVideoShieldRespBodyBytesTotal", "kind": "Counter", "api_field": "ImgVideoShieldRespBodyBytes"}, + {"exporter_metric": "ImgVideoShieldRespHeaderBytesTotal", "kind": "Counter", "api_field": "ImgVideoShieldRespHeaderBytes"}, + {"exporter_metric": "ImgVideoShieldTotal", "kind": "Counter", "api_field": "ImgVideoShield"}, + {"exporter_metric": "ImgVideoTotal", "kind": "Counter", "api_field": "ImgVideo"}, + {"exporter_metric": "LogBytesTotal", "kind": "Counter", "api_field": "LogBytes"}, + {"exporter_metric": "LoggingTotal", "kind": "Counter", "api_field": "Logging"}, + {"exporter_metric": "MissDurationSeconds", "kind": "Histogram", "api_field": "MissHistogram"}, + {"exporter_metric": "MissRespBodyBytesTotal", "kind": "Counter", "api_field": "MissRespBodyBytes"}, + {"exporter_metric": "MissSubCountTotal", "kind": "Counter", "api_field": "MissSubCount"}, + {"exporter_metric": "MissSubTimeTotal", "kind": "Counter", "api_field": "MissSubTime"}, + {"exporter_metric": "MissTimeTotal", "kind": "Counter", "api_field": "MissTime"}, + {"exporter_metric": "MissesTotal", "kind": "Counter", "api_field": "Misses"}, + {"exporter_metric": "OTFPDeliverTimeTotal", "kind": "Counter", "api_field": "OTFPDeliverTime"}, + {"exporter_metric": "OTFPManifestTotal", "kind": "Counter", "api_field": "OTFPManifest"}, + {"exporter_metric": "OTFPRespBodyBytesTotal", "kind": "Counter", "api_field": "OTFPRespBodyBytes"}, + {"exporter_metric": "OTFPRespHeaderBytesTotal", "kind": "Counter", "api_field": "OTFPRespHeaderBytes"}, + {"exporter_metric": "OTFPShieldRespBodyBytesTotal", "kind": "Counter", "api_field": "OTFPShieldRespBodyBytes"}, + {"exporter_metric": "OTFPShieldRespHeaderBytesTotal", "kind": "Counter", "api_field": "OTFPShieldRespHeaderBytes"}, + {"exporter_metric": "OTFPShieldTimeTotal", "kind": "Counter", "api_field": "OTFPShieldTime"}, + {"exporter_metric": "OTFPShieldTotal", "kind": "Counter", "api_field": "OTFPShield"}, + {"exporter_metric": "OTFPTotal", "kind": "Counter", "api_field": "OTFP"}, + {"exporter_metric": "OTFPTransformRespBodyBytesTotal", "kind": "Counter", "api_field": "OTFPTransformRespBodyBytes"}, + {"exporter_metric": "OTFPTransformRespHeaderBytesTotal", "kind": "Counter", "api_field": "OTFPTransformRespHeaderBytes"}, + {"exporter_metric": "OTFPTransformTimeTotal", "kind": "Counter", "api_field": "OTFPTransformTime"}, + {"exporter_metric": "OTFPTransformTotal", "kind": "Counter", "api_field": "OTFPTransform"}, + {"exporter_metric": "ObjectSizeBytes", "kind": "ObjectSize", "api_field_sizes": ["ObjectSize100k", "ObjectSize100m", "ObjectSize10k", "ObjectSize10m", "ObjectSize1g", "ObjectSize1k", "ObjectSize1m"]}, + {"exporter_metric": "ObjectSizeOtherTotal", "kind": "Ignored", "api_field": "-"}, + {"exporter_metric": "OriginFetchBodyBytesTotal", "kind": "Counter", "api_field": "OriginFetchBodyBytes"}, + {"exporter_metric": "OriginFetchHeaderBytesTotal", "kind": "Counter", "api_field": "OriginFetchHeaderBytes"}, + {"exporter_metric": "OriginFetchRespBodyBytesTotal", "kind": "Counter", "api_field": "OriginFetchRespBodyBytes"}, + {"exporter_metric": "OriginFetchRespHeaderBytesTotal", "kind": "Counter", "api_field": "OriginFetchRespHeaderBytes"}, + {"exporter_metric": "OriginFetchesTotal", "kind": "Counter", "api_field": "OriginFetches"}, + {"exporter_metric": "OriginRevalidationsTotal", "kind": "Counter", "api_field": "OriginRevalidations"}, + {"exporter_metric": "PCITotal", "kind": "Counter", "api_field": "PCI"}, + {"exporter_metric": "PassRespBodyBytesTotal", "kind": "Counter", "api_field": "PassRespBodyBytes"}, + {"exporter_metric": "PassSubCountTotal", "kind": "Counter", "api_field": "PassSubCount"}, + {"exporter_metric": "PassSubTimeTotal", "kind": "Counter", "api_field": "PassSubTime"}, + {"exporter_metric": "PassTimeTotal", "kind": "Counter", "api_field": "PassTime"}, + {"exporter_metric": "PassesTotal", "kind": "Counter", "api_field": "Passes"}, + {"exporter_metric": "PipeSubCountTotal", "kind": "Counter", "api_field": "PipeSubCount"}, + {"exporter_metric": "PipeSubTimeTotal", "kind": "Counter", "api_field": "PipeSubTime"}, + {"exporter_metric": "PredeliverSubCountTotal", "kind": "Counter", "api_field": "PredeliverSubCount"}, + {"exporter_metric": "PredeliverSubTimeTotal", "kind": "Counter", "api_field": "PredeliverSubTime"}, + {"exporter_metric": "PrehashSubCountTotal", "kind": "Counter", "api_field": "PrehashSubCount"}, + {"exporter_metric": "PrehashSubTimeTotal", "kind": "Counter", "api_field": "PrehashSubTime"}, + {"exporter_metric": "RecvSubCountTotal", "kind": "Counter", "api_field": "RecvSubCount"}, + {"exporter_metric": "RecvSubTimeTotal", "kind": "Counter", "api_field": "RecvSubTime"}, + {"exporter_metric": "ReqBodyBytesTotal", "kind": "Counter", "api_field": "ReqBodyBytes"}, + {"exporter_metric": "ReqHeaderBytesTotal", "kind": "Counter", "api_field": "ReqHeaderBytes"}, + {"exporter_metric": "RequestsTotal", "kind": "Counter", "api_field": "Requests"}, + {"exporter_metric": "RespBodyBytesTotal", "kind": "Counter", "api_field": "RespBodyBytes"}, + {"exporter_metric": "RespHeaderBytesTotal", "kind": "Counter", "api_field": "RespHeaderBytes"}, + {"exporter_metric": "RestartTotal", "kind": "Counter", "api_field": "Restart"}, + {"exporter_metric": "SegBlockOriginFetchesTotal", "kind": "Counter", "api_field": "SegBlockOriginFetches"}, + {"exporter_metric": "SegBlockShieldFetchesTotal", "kind": "Counter", "api_field": "SegBlockShieldFetches"}, + {"exporter_metric": "ShieldFetchBodyBytesTotal", "kind": "Counter", "api_field": "ShieldFetchBodyBytes"}, + {"exporter_metric": "ShieldFetchHeaderBytesTotal", "kind": "Counter", "api_field": "ShieldFetchHeaderBytes"}, + {"exporter_metric": "ShieldFetchRespBodyBytesTotal", "kind": "Counter", "api_field": "ShieldFetchRespBodyBytes"}, + {"exporter_metric": "ShieldFetchRespHeaderBytesTotal", "kind": "Counter", "api_field": "ShieldFetchRespHeaderBytes"}, + {"exporter_metric": "ShieldFetchesTotal", "kind": "Counter", "api_field": "ShieldFetches"}, + {"exporter_metric": "ShieldRespBodyBytesTotal", "kind": "Counter", "api_field": "ShieldRespBodyBytes"}, + {"exporter_metric": "ShieldRespHeaderBytesTotal", "kind": "Counter", "api_field": "ShieldRespHeaderBytes"}, + {"exporter_metric": "ShieldRevalidationsTotal", "kind": "Counter", "api_field": "ShieldRevalidations"}, + {"exporter_metric": "ShieldTotal", "kind": "Counter", "api_field": "Shield"}, + {"exporter_metric": "StatusCodeTotal", "kind": "CounterLabels", "api_field_labels": [["Status200", "200"], ["Status204", "204"], ["Status206", "206"], ["Status301", "301"], ["Status302", "302"], ["Status304", "304"], ["Status400", "400"], ["Status401", "401"], ["Status403", "403"], ["Status404", "404"], ["Status416", "416"], ["Status429", "429"], ["Status500", "500"], ["Status501", "501"], ["Status502", "502"], ["Status503", "503"], ["Status504", "504"], ["Status505", "505"]]}, + {"exporter_metric": "StatusGroupTotal", "kind": "CounterLabels", "api_field_labels": [["Status1xx", "1xx"], ["Status2xx", "2xx"], ["Status3xx", "3xx"], ["Status4xx", "4xx"], ["Status5xx", "5xx"]]}, + {"exporter_metric": "SynthsTotal", "kind": "Counter", "api_field": "Synths"}, + {"exporter_metric": "TLSTotal", "kind": "CounterLabels", "api_field_labels": [["TLS", "any"], ["TLSv10", "v10"], ["TLSv11", "v11"], ["TLSv12", "v12"], ["TLSv13", "v13"]]}, + {"exporter_metric": "UncacheableTotal", "kind": "Counter", "api_field": "Uncacheable"}, + {"exporter_metric": "VideoTotal", "kind": "Counter", "api_field": "Video"}, + {"exporter_metric": "WAFBlockedTotal", "kind": "Counter", "api_field": "WAFBlocked"}, + {"exporter_metric": "WAFLoggedTotal", "kind": "Counter", "api_field": "WAFLogged"}, + {"exporter_metric": "WAFPassedTotal", "kind": "Counter", "api_field": "WAFPassed"} +] diff --git a/pkg/gen/doc.go b/pkg/gen/doc.go new file mode 100644 index 0000000..d4a9269 --- /dev/null +++ b/pkg/gen/doc.go @@ -0,0 +1,8 @@ +// Package gen contains generated code that defines the rt.fastly.com API +// response, the Prometheus metrics we export, and the mapping between them. +// +// cd cmd/fieldgen +// go run main.go > ../../pkg/gen/gen.go +// gofmt -w ../../pkg/gen/gen.go +// +package gen diff --git a/pkg/gen/gen.go b/pkg/gen/gen.go new file mode 100644 index 0000000..f73f294 --- /dev/null +++ b/pkg/gen/gen.go @@ -0,0 +1,653 @@ +// Code generated by fieldgen; DO NOT EDIT. + +package gen + +import ( + "fmt" + "reflect" + "regexp" + "strconv" + + "github.com/peterbourgon/fastly-exporter/pkg/filter" + "github.com/prometheus/client_golang/prometheus" +) + +// APIResponse models the response from rt.fastly.com. It can get quite large; +// when there are lots of services being monitored, unmarshaling to this type is +// the CPU bottleneck of the program. +type APIResponse struct { + Timestamp uint64 `json:"Timestamp"` + Data []struct { + Datacenter map[string]Datacenter `json:"datacenter"` + Aggregated Datacenter `json:"aggregated"` + Recorded uint64 `json:"recorded"` + } `json:"Data"` + Error string `json:"error"` +} + +// Datacenter models the per-datacenter portion of the rt.fastly.com response. +type Datacenter struct { + AttackBlockedReqHeaderBytes uint64 `json:"attack_blocked_req_header_bytes"` + AttackBlockedReqBodyBytes uint64 `json:"attack_blocked_req_body_bytes"` + AttackLoggedReqBodyBytes uint64 `json:"attack_logged_req_body_bytes"` + AttackLoggedReqHeaderBytes uint64 `json:"attack_logged_req_header_bytes"` + AttackPassedReqBodyBytes uint64 `json:"attack_passed_req_body_bytes"` + AttackPassedReqHeaderBytes uint64 `json:"attack_passed_req_header_bytes"` + AttackReqBodyBytes uint64 `json:"attack_req_body_bytes"` + AttackReqHeaderBytes uint64 `json:"attack_req_header_bytes"` + AttackRespSynthBytes uint64 `json:"attack_resp_synth_bytes"` + BackendReqBodyBytes uint64 `json:"bereq_body_bytes"` + BackendReqHeaderBytes uint64 `json:"bereq_header_bytes"` + Billed uint64 `json:"billed"` + BilledBodyBytes uint64 `json:"billed_body_bytes"` + BilledHeaderBytes uint64 `json:"billed_header_bytes"` + Blacklisted uint64 `json:"blacklist"` + BodySize uint64 `json:"body_size"` + DeliverSubCount uint64 `json:"deliver_sub_count"` + DeliverSubTime uint64 `json:"deliver_sub_time"` + Edge uint64 `json:"edge"` + EdgeRespBodyBytes uint64 `json:"edge_resp_body_bytes"` + EdgeRespHeaderBytes uint64 `json:"edge_resp_header_bytes"` + Errors uint64 `json:"errors"` + ErrorSubCount uint64 `json:"error_sub_count"` + ErrorSubTime uint64 `json:"error_sub_time"` + FetchSubCount uint64 `json:"fetch_sub_count"` + FetchSubTime uint64 `json:"fetch_sub_time"` + HashSubCount uint64 `json:"hash_sub_count"` + HashSubTime uint64 `json:"hash_sub_time"` + HeaderSize uint64 `json:"header_size"` + HitRespBodyBytes uint64 `json:"hit_resp_body_bytes"` + Hits uint64 `json:"hits"` + HitsTime float64 `json:"hits_time"` + HitSubCount uint64 `json:"hit_sub_count"` + HitSubTime uint64 `json:"hit_sub_time"` + HTTP2 uint64 `json:"http2"` + ImgOpto uint64 `json:"imgopto"` + ImgOptoRespBodyBytes uint64 `json:"imgopto_resp_body_bytes"` + ImgOptoRespHeaderBytes uint64 `json:"imgopto_resp_header_bytes"` + ImgOptoShield uint64 `json:"imgopto_shield"` + ImgOptoShieldRespBodyBytes uint64 `json:"imgopto_shield_resp_body_bytes"` + ImgOptoShieldRespHeaderBytes uint64 `json:"imgopto_shield_resp_header_bytes"` + ImgOptoTransform uint64 `json:"imgopto_transforms"` + ImgOptoTransformRespBodyBytes uint64 `json:"imgopto_transform_resp_body_bytes"` + ImgOptoTransformRespHeaderBytes uint64 `json:"imgopto_transform_resp_header_bytes"` + ImgVideo uint64 `json:"imgvideo"` + ImgVideoFrames uint64 `json:"imgvideo_frames"` + ImgVideoRespBodyBytes uint64 `json:"imgvideo_resp_body_bytes"` + ImgVideoRespHeaderBytes uint64 `json:"imgvideo_resp_header_bytes"` + ImgVideoShield uint64 `json:"imgvideo_shield"` + ImgVideoShieldFrames uint64 `json:"imgvideo_shield_frames"` + ImgVideoShieldRespBodyBytes uint64 `json:"imgvideo_shield_resp_body_bytes"` + ImgVideoShieldRespHeaderBytes uint64 `json:"imgvideo_shield_resp_header_bytes"` + IPv6 uint64 `json:"ipv6"` + LogBytes uint64 `json:"log_bytes"` + Logging uint64 `json:"logging"` + Misses uint64 `json:"miss"` + MissHistogram map[string]uint64 `json:"miss_histogram"` + MissRespBodyBytes uint64 `json:"miss_resp_body_bytes"` + MissSubCount uint64 `json:"miss_sub_count"` + MissSubTime uint64 `json:"miss_sub_time"` + MissTime float64 `json:"miss_time"` + ObjectSize100k uint64 `json:"object_size_100k"` + ObjectSize100m uint64 `json:"object_size_100m"` + ObjectSize10k uint64 `json:"object_size_10k"` + ObjectSize10m uint64 `json:"object_size_10m"` + ObjectSize1g uint64 `json:"object_size_1g"` + ObjectSize1k uint64 `json:"object_size_1k"` + ObjectSize1m uint64 `json:"object_size_1m"` + ObjectSizeOther uint64 `json:"object_size_other"` + OriginFetchBodyBytes uint64 `json:"origin_fetch_body_bytes"` + OriginFetches uint64 `json:"origin_fetches"` + OriginFetchHeaderBytes uint64 `json:"origin_fetch_header_bytes"` + OriginFetchRespBodyBytes uint64 `json:"origin_fetch_resp_body_bytes"` + OriginFetchRespHeaderBytes uint64 `json:"origin_fetch_resp_header_bytes"` + OriginRevalidations uint64 `json:"origin_revalidations"` + OTFP uint64 `json:"otfp"` + OTFPDeliverTime uint64 `json:"otfp_deliver_time"` + OTFPManifest uint64 `json:"otfp_manifests"` + OTFPRespBodyBytes uint64 `json:"otfp_resp_body_bytes"` + OTFPRespHeaderBytes uint64 `json:"otfp_resp_header_bytes"` + OTFPShield uint64 `json:"otfp_shield"` + OTFPShieldRespBodyBytes uint64 `json:"otfp_shield_resp_body_bytes"` + OTFPShieldRespHeaderBytes uint64 `json:"otfp_shield_resp_header_bytes"` + OTFPShieldTime uint64 `json:"otfp_shield_time"` + OTFPTransform uint64 `json:"otfp_transforms"` + OTFPTransformRespBodyBytes uint64 `json:"otfp_transform_resp_body_bytes"` + OTFPTransformRespHeaderBytes uint64 `json:"otfp_transform_resp_header_bytes"` + OTFPTransformTime uint64 `json:"otfp_transform_time"` + Passes uint64 `json:"pass"` + PassRespBodyBytes uint64 `json:"pass_resp_body_bytes"` + PassSubCount uint64 `json:"pass_sub_count"` + PassSubTime uint64 `json:"pass_sub_time"` + PassTime float64 `json:"pass_time"` + PCI uint64 `json:"pci"` + PipeSubCount uint64 `json:"pipe_sub_count"` + PipeSubTime uint64 `json:"pipe_sub_time"` + PredeliverSubCount uint64 `json:"predeliver_sub_count"` + PredeliverSubTime uint64 `json:"predeliver_sub_time"` + PrehashSubCount uint64 `json:"prehash_sub_count"` + PrehashSubTime uint64 `json:"prehash_sub_time"` + RecvSubCount uint64 `json:"recv_sub_count"` + RecvSubTime uint64 `json:"recv_sub_time"` + ReqBodyBytes uint64 `json:"req_body_bytes"` + ReqHeaderBytes uint64 `json:"req_header_bytes"` + Requests uint64 `json:"requests"` + RespBodyBytes uint64 `json:"resp_body_bytes"` + RespHeaderBytes uint64 `json:"resp_header_bytes"` + Restart uint64 `json:"restarts"` + SegBlockOriginFetches uint64 `json:"segblock_origin_fetches"` + SegBlockShieldFetches uint64 `json:"segblock_shield_fetches"` + ShieldFetchBodyBytes uint64 `json:"shield_fetch_body_bytes"` + Shield uint64 `json:"shield"` + ShieldFetches uint64 `json:"shield_fetches"` + ShieldFetchHeaderBytes uint64 `json:"shield_fetch_header_bytes"` + ShieldFetchRespBodyBytes uint64 `json:"shield_fetch_resp_body_bytes"` + ShieldFetchRespHeaderBytes uint64 `json:"shield_fetch_resp_header_bytes"` + ShieldRespBodyBytes uint64 `json:"shield_resp_body_bytes"` + ShieldRespHeaderBytes uint64 `json:"shield_resp_header_bytes"` + ShieldRevalidations uint64 `json:"shield_revalidations"` + Status1xx uint64 `json:"status_1xx"` + Status200 uint64 `json:"status_200"` + Status204 uint64 `json:"status_204"` + Status206 uint64 `json:"status_206"` + Status2xx uint64 `json:"status_2xx"` + Status301 uint64 `json:"status_301"` + Status302 uint64 `json:"status_302"` + Status304 uint64 `json:"status_304"` + Status3xx uint64 `json:"status_3xx"` + Status400 uint64 `json:"status_400"` + Status401 uint64 `json:"status_401"` + Status403 uint64 `json:"status_403"` + Status404 uint64 `json:"status_404"` + Status416 uint64 `json:"status_416"` + Status429 uint64 `json:"status_429"` + Status4xx uint64 `json:"status_4xx"` + Status500 uint64 `json:"status_500"` + Status501 uint64 `json:"status_501"` + Status502 uint64 `json:"status_502"` + Status503 uint64 `json:"status_503"` + Status504 uint64 `json:"status_504"` + Status505 uint64 `json:"status_505"` + Status5xx uint64 `json:"status_5xx"` + Synths uint64 `json:"synth"` + TLS uint64 `json:"tls"` + TLSv10 uint64 `json:"tls_v10"` + TLSv11 uint64 `json:"tls_v11"` + TLSv12 uint64 `json:"tls_v12"` + TLSv13 uint64 `json:"tls_v13"` + Uncacheable uint64 `json:"uncacheable"` + Video uint64 `json:"video"` + WAFBlocked uint64 `json:"waf_blocked"` + WAFLogged uint64 `json:"waf_logged"` + WAFPassed uint64 `json:"waf_passed"` +} + +// Metrics collects all of the Prometheus metrics exported by this service. +type Metrics struct { + RealtimeAPIRequestsTotal *prometheus.CounterVec + ServiceInfo *prometheus.GaugeVec + AttackBlockedReqBodyBytesTotal *prometheus.CounterVec + AttackBlockedReqHeaderBytesTotal *prometheus.CounterVec + AttackLoggedReqBodyBytesTotal *prometheus.CounterVec + AttackLoggedReqHeaderBytesTotal *prometheus.CounterVec + AttackPassedReqBodyBytesTotal *prometheus.CounterVec + AttackPassedReqHeaderBytesTotal *prometheus.CounterVec + AttackReqBodyBytesTotal *prometheus.CounterVec + AttackReqHeaderBytesTotal *prometheus.CounterVec + AttackRespSynthBytesTotal *prometheus.CounterVec + BackendReqBodyBytesTotal *prometheus.CounterVec + BackendReqHeaderBytesTotal *prometheus.CounterVec + BilledBodyBytesTotal *prometheus.CounterVec + BilledHeaderBytesTotal *prometheus.CounterVec + BilledTotal *prometheus.CounterVec + BlacklistedTotal *prometheus.CounterVec + BodySizeTotal *prometheus.CounterVec + DeliverSubCountTotal *prometheus.CounterVec + DeliverSubTimeTotal *prometheus.CounterVec + EdgeRespBodyBytesTotal *prometheus.CounterVec + EdgeRespHeaderBytesTotal *prometheus.CounterVec + EdgeTotal *prometheus.CounterVec + ErrorSubCountTotal *prometheus.CounterVec + ErrorSubTimeTotal *prometheus.CounterVec + ErrorsTotal *prometheus.CounterVec + FetchSubCountTotal *prometheus.CounterVec + FetchSubTimeTotal *prometheus.CounterVec + HTTP2Total *prometheus.CounterVec + HashSubCountTotal *prometheus.CounterVec + HashSubTimeTotal *prometheus.CounterVec + HeaderSizeTotal *prometheus.CounterVec + HitRespBodyBytesTotal *prometheus.CounterVec + HitSubCountTotal *prometheus.CounterVec + HitSubTimeTotal *prometheus.CounterVec + HitsTimeTotal *prometheus.CounterVec + HitsTotal *prometheus.CounterVec + IPv6Total *prometheus.CounterVec + ImgOptoRespBodyBytesTotal *prometheus.CounterVec + ImgOptoRespHeaderBytesTotal *prometheus.CounterVec + ImgOptoShieldRespBodyBytesTotal *prometheus.CounterVec + ImgOptoShieldRespHeaderBytesTotal *prometheus.CounterVec + ImgOptoShieldTotal *prometheus.CounterVec + ImgOptoTotal *prometheus.CounterVec + ImgOptoTransformRespBodyBytesTotal *prometheus.CounterVec + ImgOptoTransformRespHeaderBytesTotal *prometheus.CounterVec + ImgOptoTransformTotal *prometheus.CounterVec + ImgVideoFramesTotal *prometheus.CounterVec + ImgVideoRespBodyBytesTotal *prometheus.CounterVec + ImgVideoRespHeaderBytesTotal *prometheus.CounterVec + ImgVideoShieldFramesTotal *prometheus.CounterVec + ImgVideoShieldRespBodyBytesTotal *prometheus.CounterVec + ImgVideoShieldRespHeaderBytesTotal *prometheus.CounterVec + ImgVideoShieldTotal *prometheus.CounterVec + ImgVideoTotal *prometheus.CounterVec + LogBytesTotal *prometheus.CounterVec + LoggingTotal *prometheus.CounterVec + MissDurationSeconds *prometheus.HistogramVec + MissRespBodyBytesTotal *prometheus.CounterVec + MissSubCountTotal *prometheus.CounterVec + MissSubTimeTotal *prometheus.CounterVec + MissTimeTotal *prometheus.CounterVec + MissesTotal *prometheus.CounterVec + OTFPDeliverTimeTotal *prometheus.CounterVec + OTFPManifestTotal *prometheus.CounterVec + OTFPRespBodyBytesTotal *prometheus.CounterVec + OTFPRespHeaderBytesTotal *prometheus.CounterVec + OTFPShieldRespBodyBytesTotal *prometheus.CounterVec + OTFPShieldRespHeaderBytesTotal *prometheus.CounterVec + OTFPShieldTimeTotal *prometheus.CounterVec + OTFPShieldTotal *prometheus.CounterVec + OTFPTotal *prometheus.CounterVec + OTFPTransformRespBodyBytesTotal *prometheus.CounterVec + OTFPTransformRespHeaderBytesTotal *prometheus.CounterVec + OTFPTransformTimeTotal *prometheus.CounterVec + OTFPTransformTotal *prometheus.CounterVec + ObjectSizeBytes *prometheus.HistogramVec + OriginFetchBodyBytesTotal *prometheus.CounterVec + OriginFetchHeaderBytesTotal *prometheus.CounterVec + OriginFetchRespBodyBytesTotal *prometheus.CounterVec + OriginFetchRespHeaderBytesTotal *prometheus.CounterVec + OriginFetchesTotal *prometheus.CounterVec + OriginRevalidationsTotal *prometheus.CounterVec + PCITotal *prometheus.CounterVec + PassRespBodyBytesTotal *prometheus.CounterVec + PassSubCountTotal *prometheus.CounterVec + PassSubTimeTotal *prometheus.CounterVec + PassTimeTotal *prometheus.CounterVec + PassesTotal *prometheus.CounterVec + PipeSubCountTotal *prometheus.CounterVec + PipeSubTimeTotal *prometheus.CounterVec + PredeliverSubCountTotal *prometheus.CounterVec + PredeliverSubTimeTotal *prometheus.CounterVec + PrehashSubCountTotal *prometheus.CounterVec + PrehashSubTimeTotal *prometheus.CounterVec + RecvSubCountTotal *prometheus.CounterVec + RecvSubTimeTotal *prometheus.CounterVec + ReqBodyBytesTotal *prometheus.CounterVec + ReqHeaderBytesTotal *prometheus.CounterVec + RequestsTotal *prometheus.CounterVec + RespBodyBytesTotal *prometheus.CounterVec + RespHeaderBytesTotal *prometheus.CounterVec + RestartTotal *prometheus.CounterVec + SegBlockOriginFetchesTotal *prometheus.CounterVec + SegBlockShieldFetchesTotal *prometheus.CounterVec + ShieldFetchBodyBytesTotal *prometheus.CounterVec + ShieldFetchHeaderBytesTotal *prometheus.CounterVec + ShieldFetchRespBodyBytesTotal *prometheus.CounterVec + ShieldFetchRespHeaderBytesTotal *prometheus.CounterVec + ShieldFetchesTotal *prometheus.CounterVec + ShieldRespBodyBytesTotal *prometheus.CounterVec + ShieldRespHeaderBytesTotal *prometheus.CounterVec + ShieldRevalidationsTotal *prometheus.CounterVec + ShieldTotal *prometheus.CounterVec + StatusCodeTotal *prometheus.CounterVec + StatusGroupTotal *prometheus.CounterVec + SynthsTotal *prometheus.CounterVec + TLSTotal *prometheus.CounterVec + UncacheableTotal *prometheus.CounterVec + VideoTotal *prometheus.CounterVec + WAFBlockedTotal *prometheus.CounterVec + WAFLoggedTotal *prometheus.CounterVec + WAFPassedTotal *prometheus.CounterVec +} + +// NewMetrics returns a new set of metrics registered to the registerer. +// Only metrics whose names pass the name filter are registered. +func NewMetrics(namespace, subsystem string, nameFilter filter.Filter, r prometheus.Registerer) (*Metrics, error) { + m := Metrics{ + RealtimeAPIRequestsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "realtime_api_requests_total", Help: "Total requests made to the real-time stats API."}, []string{"service_id", "service_name", "result"}), + ServiceInfo: prometheus.NewGaugeVec(prometheus.GaugeOpts{Namespace: namespace, Subsystem: subsystem, Name: "service_info", Help: "Static gauge with service ID, name, and version information."}, []string{"service_id", "service_name", "service_version"}), + AttackBlockedReqBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_blocked_req_body_bytes_total", Help: "Total body bytes received from requests that triggered a WAF rule that was blocked."}, []string{"service_id", "service_name", "datacenter"}), + AttackBlockedReqHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_blocked_req_header_bytes_total", Help: "Total header bytes received from requests that triggered a WAF rule that was blocked."}, []string{"service_id", "service_name", "datacenter"}), + AttackLoggedReqBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_logged_req_body_bytes_total", Help: "Total body bytes received from requests that triggered a WAF rule that was logged."}, []string{"service_id", "service_name", "datacenter"}), + AttackLoggedReqHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_logged_req_header_bytes_total", Help: "Total header bytes received from requests that triggered a WAF rule that was logged."}, []string{"service_id", "service_name", "datacenter"}), + AttackPassedReqBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_passed_req_body_bytes_total", Help: "Total body bytes received from requests that triggered a WAF rule that was passed."}, []string{"service_id", "service_name", "datacenter"}), + AttackPassedReqHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_passed_req_header_bytes_total", Help: "Total header bytes received from requests that triggered a WAF rule that was passed."}, []string{"service_id", "service_name", "datacenter"}), + AttackReqBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_req_body_bytes_total", Help: "Total body bytes received from requests that triggered a WAF rule."}, []string{"service_id", "service_name", "datacenter"}), + AttackReqHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_req_header_bytes_total", Help: "Total header bytes received from requests that triggered a WAF rule."}, []string{"service_id", "service_name", "datacenter"}), + AttackRespSynthBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "attack_resp_synth_bytes_total", Help: "Total bytes delivered for requests that triggered a WAF rule and returned a synthetic response."}, []string{"service_id", "service_name", "datacenter"}), + BackendReqBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "bereq_body_bytes_total", Help: "Total body bytes sent to origin."}, []string{"service_id", "service_name", "datacenter"}), + BackendReqHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "bereq_header_bytes_total", Help: "Total header bytes sent to origin."}, []string{"service_id", "service_name", "datacenter"}), + BilledBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "billed_body_bytes_total", Help: "TODO"}, []string{"service_id", "service_name", "datacenter"}), + BilledHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "billed_header_bytes_total", Help: "TODO"}, []string{"service_id", "service_name", "datacenter"}), + BilledTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "billed_total", Help: "TODO"}, []string{"service_id", "service_name", "datacenter"}), + BlacklistedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "blacklist_total", Help: "TODO"}, []string{"service_id", "service_name", "datacenter"}), + BodySizeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "body_size_total", Help: "Total body bytes delivered (alias for resp_body_bytes)."}, []string{"service_id", "service_name", "datacenter"}), + DeliverSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "deliver_sub_count_total", Help: "Number of executions of the 'deliver' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + DeliverSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "deliver_sub_time_total", Help: "Time spent inside the 'deliver' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + EdgeRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "edge_resp_body_bytes_total", Help: "Total body bytes delivered from Fastly to the end user."}, []string{"service_id", "service_name", "datacenter"}), + EdgeRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "edge_resp_header_bytes_total", Help: "Total header bytes delivered from Fastly to the end user."}, []string{"service_id", "service_name", "datacenter"}), + EdgeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "edge_total", Help: "Number of requests sent by end users to Fastly."}, []string{"service_id", "service_name", "datacenter"}), + ErrorSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "error_sub_count_total", Help: "Number of executions of the 'error' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + ErrorSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "error_sub_time_total", Help: "Time spent inside the 'error' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + ErrorsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "errors_total", Help: "Number of cache errors."}, []string{"service_id", "service_name", "datacenter"}), + FetchSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "fetch_sub_count_total", Help: "Number of executions of the 'fetch' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + FetchSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "fetch_sub_time_total", Help: "Time spent inside the 'fetch' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + HTTP2Total: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "http2_total", Help: "Number of requests received over HTTP2."}, []string{"service_id", "service_name", "datacenter"}), + HashSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "hash_sub_count_total", Help: "Number of executions of the 'hash' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + HashSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "hash_sub_time_total", Help: "Time spent inside the 'hash' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + HeaderSizeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "header_size_total", Help: "Total header bytes delivered (alias for resp_header_bytes)."}, []string{"service_id", "service_name", "datacenter"}), + HitRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "hit_resp_body_bytes_total", Help: "Total body bytes delivered for cache hits."}, []string{"service_id", "service_name", "datacenter"}), + HitSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "hit_sub_count_total", Help: "Number of executions of the 'hit' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + HitSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "hit_sub_time_total", Help: "Time spent inside the 'hit' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + HitsTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "hits_time_total", Help: "Total amount of time spent processing cache hits (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + HitsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "hits_total", Help: "Number of cache hits."}, []string{"service_id", "service_name", "datacenter"}), + IPv6Total: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "ipv6_total", Help: "Number of requests that were received over IPv6."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_resp_body_bytes_total", Help: "Total body bytes delivered from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_resp_header_bytes_total", Help: "Total header bytes delivered from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoShieldRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_shield_resp_body_bytes_total", Help: "Total body bytes delivered via a shield from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoShieldRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_shield_resp_header_bytes_total", Help: "Total header bytes delivered via a shield from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoShieldTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_shield_total", Help: "Number of responses delivered via a shield from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_total", Help: "Number of responses that came from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoTransformRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_transform_resp_body_bytes_total", Help: "Total body bytes of transforms delivered from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoTransformRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_transform_resp_header_bytes_total", Help: "Total header bytes of transforms delivered from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgOptoTransformTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgopto_transforms_total", Help: "Total transforms performed by the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgVideoFramesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgvideo_frames_total", Help: "Number of video frames that came from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgVideoRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgvideo_resp_body_bytes_total", Help: "Total body bytes of video delivered from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgVideoRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgvideo_resp_header_bytes_total", Help: "Total header bytes of video delivered from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgVideoShieldFramesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgvideo_shield_frames_total", Help: "Number of video frames delivered via a shield from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgVideoShieldRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgvideo_shield_resp_body_bytes_total", Help: "Total body bytes of video delivered via a shield from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgVideoShieldRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgvideo_shield_resp_header_bytes_total", Help: "Total header bytes of video delivered via a shield from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgVideoShieldTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgvideo_shield_total", Help: "Number of video responses that came via a shield from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + ImgVideoTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "imgvideo_total", Help: "Number of video responses that came via a shield from the Fastly Image Optimizer service."}, []string{"service_id", "service_name", "datacenter"}), + LogBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "log_bytes_total", Help: "Total log bytes sent."}, []string{"service_id", "service_name", "datacenter"}), + LoggingTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "logging_total", Help: "Number of log lines sent."}, []string{"service_id", "service_name", "datacenter"}), + MissDurationSeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{Namespace: namespace, Subsystem: subsystem, Name: "miss_duration_seconds", Help: "Histogram of time spent processing cache misses (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + MissRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "miss_resp_body_bytes_total", Help: "Total body bytes delivered for cache misses."}, []string{"service_id", "service_name", "datacenter"}), + MissSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "miss_sub_count_total", Help: "Number of executions of the 'miss' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + MissSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "miss_sub_time_total", Help: "Time spent inside the 'miss' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + MissTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "miss_time_total", Help: "Total amount of time spent processing cache misses (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + MissesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "miss_total", Help: "Number of cache misses."}, []string{"service_id", "service_name", "datacenter"}), + OTFPDeliverTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_total", Help: "Number of responses that came from the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPManifestTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_deliver_time_total", Help: "Total amount of time spent delivering a response from the Fastly On-the-Fly Packager (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + OTFPRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_manifests_total", Help: "Number of responses that were manifest files from the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_resp_body_bytes_total", Help: "Total body bytes delivered from the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPShieldRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_resp_header_bytes_total", Help: "Total header bytes delivered from the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPShieldRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_shield_total", Help: "Number of responses delivered from the Fastly On-the-Fly Packager"}, []string{"service_id", "service_name", "datacenter"}), + OTFPShieldTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_shield_resp_body_bytes_total", Help: "Total body bytes delivered via a shield for the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPShieldTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_shield_resp_header_bytes_total", Help: "Total header bytes delivered via a shield for the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_shield_time_total", Help: "Total amount of time spent delivering a response via a shield from the Fastly On-the-Fly Packager (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + OTFPTransformRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_transforms_total", Help: "Number of transforms performed by the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPTransformRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_transform_resp_body_bytes_total", Help: "Total body bytes of transforms delivered from the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPTransformTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_transform_resp_header_bytes_total", Help: "Total body bytes of transforms delivered from the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + OTFPTransformTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "otfp_transform_time_total", Help: "Total amount of time spent performing transforms from the Fastly On-the-Fly Packager."}, []string{"service_id", "service_name", "datacenter"}), + ObjectSizeBytes: prometheus.NewHistogramVec(prometheus.HistogramOpts{Namespace: namespace, Subsystem: subsystem, Name: "object_size_bytes", Help: "Histogram of count of objects served, bucketed by object size range."}, []string{"service_id", "service_name", "datacenter"}), + OriginFetchBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "origin_fetch_body_bytes_total", Help: "Total request body bytes sent to origin."}, []string{"service_id", "service_name", "datacenter"}), + OriginFetchHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "origin_fetch_header_bytes_total", Help: "Total request header bytes sent to origin."}, []string{"service_id", "service_name", "datacenter"}), + OriginFetchRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "origin_fetch_resp_body_bytes_total", Help: "Total body bytes received from origin."}, []string{"service_id", "service_name", "datacenter"}), + OriginFetchRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "origin_fetch_resp_header_bytes_total", Help: "Total header bytes received from origin."}, []string{"service_id", "service_name", "datacenter"}), + OriginFetchesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "origin_fetches_total", Help: "Number of requests sent to origin."}, []string{"service_id", "service_name", "datacenter"}), + OriginRevalidationsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "origin_revalidations_total", Help: "Number of responses received from origin with a 304 status code in response to an If-Modified-Since or If-None-Match request. Under regular scenarios, a revalidation will imply a cache hit. However, if using Fastly Image Optimizer or segmented caching this may result in a cache miss."}, []string{"service_id", "service_name", "datacenter"}), + PCITotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "pci_total", Help: "Number of responses with the PCI flag turned on."}, []string{"service_id", "service_name", "datacenter"}), + PassRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "pass_resp_body_bytes_total", Help: "Total body bytes delivered for cache passes."}, []string{"service_id", "service_name", "datacenter"}), + PassSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "pass_sub_count_total", Help: "Number of executions of the 'pass' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + PassSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "pass_sub_time_total", Help: "Time spent inside the 'pass' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + PassTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "pass_time_total", Help: "Total amount of time spent processing cache passes (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + PassesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "pass_total", Help: "Number of requests that passed through the CDN without being cached."}, []string{"service_id", "service_name", "datacenter"}), + PipeSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "pipe_sub_count_total", Help: "Number of executions of the 'pipe' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + PipeSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "pipe_sub_time_total", Help: "Time spent inside the 'pipe' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + PredeliverSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "predeliver_sub_count_total", Help: "Number of executions of the 'predeliver' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + PredeliverSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "predeliver_sub_time_total", Help: "Time spent inside the 'predeliver' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + PrehashSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "prehash_sub_count_total", Help: "Number of executions of the 'prehash' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + PrehashSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "prehash_sub_time_total", Help: "Time spent inside the 'prehash' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + RecvSubCountTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "recv_sub_count_total", Help: "Number of executions of the 'recv' Varnish subroutine."}, []string{"service_id", "service_name", "datacenter"}), + RecvSubTimeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "recv_sub_time_total", Help: "Time spent inside the 'recv' Varnish subroutine (in seconds)."}, []string{"service_id", "service_name", "datacenter"}), + ReqBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "req_body_bytes_total", Help: "Total body bytes received."}, []string{"service_id", "service_name", "datacenter"}), + ReqHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "req_header_bytes_total", Help: "Total header bytes received."}, []string{"service_id", "service_name", "datacenter"}), + RequestsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "requests_total", Help: "Number of requests processed."}, []string{"service_id", "service_name", "datacenter"}), + RespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "resp_body_bytes_total", Help: "Total body bytes delivered."}, []string{"service_id", "service_name", "datacenter"}), + RespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "resp_header_bytes_total", Help: "Total header bytes delivered."}, []string{"service_id", "service_name", "datacenter"}), + RestartTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "restarts_total", Help: "Number of restarts performed."}, []string{"service_id", "service_name", "datacenter"}), + SegBlockOriginFetchesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "segblock_origin_fetches_total", Help: "Number of Range requests to origin for segments of resources when using segmented caching."}, []string{"service_id", "service_name", "datacenter"}), + SegBlockShieldFetchesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "segblock_shield_fetches_total", Help: "Number of Range requests to a shield for segments of resources when using segmented caching."}, []string{"service_id", "service_name", "datacenter"}), + ShieldFetchBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_fetch_body_bytes_total", Help: "Total request body bytes sent to a shield."}, []string{"service_id", "service_name", "datacenter"}), + ShieldFetchHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_fetch_header_bytes_total", Help: "Total request header bytes sent to a shield."}, []string{"service_id", "service_name", "datacenter"}), + ShieldFetchRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_fetch_resp_body_bytes_total", Help: "Total response body bytes sent from a shield to the edge."}, []string{"service_id", "service_name", "datacenter"}), + ShieldFetchRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_fetch_resp_header_bytes_total", Help: "Total response header bytes sent from a shield to the edge."}, []string{"service_id", "service_name", "datacenter"}), + ShieldFetchesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_fetches_total", Help: "Number of requests made from one Fastly data center to another, as part of shielding."}, []string{"service_id", "service_name", "datacenter"}), + ShieldRespBodyBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_resp_body_bytes_total", Help: "Total body bytes delivered via a shield."}, []string{"service_id", "service_name", "datacenter"}), + ShieldRespHeaderBytesTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_resp_header_bytes_total", Help: "Total header bytes delivered via a shield."}, []string{"service_id", "service_name", "datacenter"}), + ShieldRevalidationsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_revalidations_total", Help: "Number of responses received from origin with a 304 status code, in response to an If-Modified-Since or If-None-Match request to a shield. Under regular scenarios, a revalidation will imply a cache hit. However, if using segmented caching this may result in a cache miss."}, []string{"service_id", "service_name", "datacenter"}), + ShieldTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "shield_total", Help: "Number of requests from edge to the shield POP."}, []string{"service_id", "service_name", "datacenter"}), + StatusCodeTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "status_code_total", Help: "Number of responses sent with status code 500 (Internal Server Error)."}, []string{"service_id", "service_name", "datacenter", "status_code"}), + StatusGroupTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "status_group_total", Help: "Number of 'Client Error' category status codes delivered."}, []string{"service_id", "service_name", "datacenter", "status_group"}), + SynthsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "synth_total", Help: "TODO"}, []string{"service_id", "service_name", "datacenter"}), + TLSTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "tls_total", Help: "Number of requests that were received over TLS."}, []string{"service_id", "service_name", "datacenter", "tls_version"}), + UncacheableTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "uncacheable_total", Help: "Number of requests that were designated uncachable."}, []string{"service_id", "service_name", "datacenter"}), + VideoTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "video_total", Help: "Number of responses with the video segment or video manifest MIME type (i.e., application/x-mpegurl, application/vnd.apple.mpegurl, application/f4m, application/dash+xml, application/vnd.ms-sstr+xml, ideo/mp2t, audio/aac, video/f4f, video/x-flv, video/mp4, audio/mp4)."}, []string{"service_id", "service_name", "datacenter"}), + WAFBlockedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "waf_blocked_total", Help: "Number of requests that triggered a WAF rule and were blocked."}, []string{"service_id", "service_name", "datacenter"}), + WAFLoggedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "waf_logged_total", Help: "Number of requests that triggered a WAF rule and were logged."}, []string{"service_id", "service_name", "datacenter"}), + WAFPassedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, Name: "waf_passed_total", Help: "Number of requests that triggered a WAF rule and were passed."}, []string{"service_id", "service_name", "datacenter"}), + } + + for i, v := 0, reflect.ValueOf(m); i < v.NumField(); i++ { + c, ok := v.Field(i).Interface().(prometheus.Collector) + if !ok { + panic(fmt.Sprintf("programmer error: field %d/%d in Metrics type isn't a prometheus.Collector", i+1, v.NumField())) + } + if name := getName(c); !nameFilter.Permit(name) { + continue + } + if err := r.Register(c); err != nil { + return nil, fmt.Errorf("error registering metric %d/%d: %w", i+1, v.NumField(), err) + } + } + + return &m, nil +} + +var descNameRegex = regexp.MustCompile("fqName: \"([^\"]+)\"") + +func getName(c prometheus.Collector) string { + d := make(chan *prometheus.Desc, 1) + c.Describe(d) + desc := (<-d).String() + matches := descNameRegex.FindAllStringSubmatch(desc, -1) + if len(matches) == 1 && len(matches[0]) == 2 { + return matches[0][1] + } + return "" +} + +// Process updates the metrics with data from the API response. +func Process(response *APIResponse, serviceID, serviceName, serviceVersion string, m *Metrics) { + for _, d := range response.Data { + for datacenter, stats := range d.Datacenter { + m.ServiceInfo.WithLabelValues(serviceID, serviceName, serviceVersion).Set(1) + m.RequestsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Requests)) + m.AttackBlockedReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackBlockedReqBodyBytes)) + m.AttackBlockedReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackBlockedReqHeaderBytes)) + m.AttackLoggedReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackLoggedReqBodyBytes)) + m.AttackLoggedReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackLoggedReqHeaderBytes)) + m.AttackPassedReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackPassedReqBodyBytes)) + m.AttackPassedReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackPassedReqHeaderBytes)) + m.AttackReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackReqBodyBytes)) + m.AttackReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackReqHeaderBytes)) + m.AttackRespSynthBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackRespSynthBytes)) + m.BackendReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BackendReqBodyBytes)) + m.BackendReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BackendReqHeaderBytes)) + m.BilledBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BilledBodyBytes)) + m.BilledHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BilledHeaderBytes)) + m.BilledTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Billed)) + m.BlacklistedTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Blacklisted)) + m.BodySizeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BodySize)) + m.DeliverSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.DeliverSubCount)) + m.DeliverSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.DeliverSubTime)) + m.EdgeRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.EdgeRespBodyBytes)) + m.EdgeRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.EdgeRespHeaderBytes)) + m.EdgeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Edge)) + m.ErrorSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ErrorSubCount)) + m.ErrorSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ErrorSubTime)) + m.ErrorsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Errors)) + m.FetchSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.FetchSubCount)) + m.FetchSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.FetchSubTime)) + m.HTTP2Total.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HTTP2)) + m.HashSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HashSubCount)) + m.HashSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HashSubTime)) + m.HeaderSizeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HeaderSize)) + m.HitRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HitRespBodyBytes)) + m.HitSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HitSubCount)) + m.HitSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HitSubTime)) + m.HitsTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HitsTime)) + m.HitsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Hits)) + m.IPv6Total.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.IPv6)) + m.ImgOptoRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoRespBodyBytes)) + m.ImgOptoRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoRespHeaderBytes)) + m.ImgOptoShieldRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoShieldRespBodyBytes)) + m.ImgOptoShieldRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoShieldRespHeaderBytes)) + m.ImgOptoShieldTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoShield)) + m.ImgOptoTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOpto)) + m.ImgOptoTransformRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoTransformRespBodyBytes)) + m.ImgOptoTransformRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoTransformRespHeaderBytes)) + m.ImgOptoTransformTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoTransform)) + m.ImgVideoFramesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgVideoFrames)) + m.ImgVideoRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgVideoRespBodyBytes)) + m.ImgVideoRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgVideoRespHeaderBytes)) + m.ImgVideoShieldFramesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgVideoShieldFrames)) + m.ImgVideoShieldRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgVideoShieldRespBodyBytes)) + m.ImgVideoShieldRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgVideoShieldRespHeaderBytes)) + m.ImgVideoShieldTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgVideoShield)) + m.ImgVideoTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgVideo)) + m.LogBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.LogBytes)) + m.LoggingTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Logging)) + processHistogram(stats.MissHistogram, m.MissDurationSeconds.WithLabelValues(serviceID, serviceName, datacenter)) + m.MissRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.MissRespBodyBytes)) + m.MissSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.MissSubCount)) + m.MissSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.MissSubTime)) + m.MissTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.MissTime)) + m.MissesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Misses)) + m.OTFPDeliverTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPDeliverTime)) + m.OTFPManifestTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPManifest)) + m.OTFPRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPRespBodyBytes)) + m.OTFPRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPRespHeaderBytes)) + m.OTFPShieldRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPShieldRespBodyBytes)) + m.OTFPShieldRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPShieldRespHeaderBytes)) + m.OTFPShieldTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPShieldTime)) + m.OTFPShieldTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPShield)) + m.OTFPTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFP)) + m.OTFPTransformRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPTransformRespBodyBytes)) + m.OTFPTransformRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPTransformRespHeaderBytes)) + m.OTFPTransformTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPTransformTime)) + m.OTFPTransformTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPTransform)) + processObjectSizes(stats.ObjectSize1k, stats.ObjectSize10k, stats.ObjectSize100k, stats.ObjectSize1m, stats.ObjectSize10m, stats.ObjectSize100m, stats.ObjectSize1g, m.ObjectSizeBytes.WithLabelValues(serviceID, serviceName, datacenter)) + m.OriginFetchBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OriginFetchBodyBytes)) + m.OriginFetchHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OriginFetchHeaderBytes)) + m.OriginFetchRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OriginFetchRespBodyBytes)) + m.OriginFetchRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OriginFetchRespHeaderBytes)) + m.OriginFetchesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OriginFetches)) + m.OriginRevalidationsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OriginRevalidations)) + m.PCITotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PCI)) + m.PassRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PassRespBodyBytes)) + m.PassSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PassSubCount)) + m.PassSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PassSubTime)) + m.PassTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PassTime)) + m.PassesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Passes)) + m.PipeSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PipeSubCount)) + m.PipeSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PipeSubTime)) + m.PredeliverSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PredeliverSubCount)) + m.PredeliverSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PredeliverSubTime)) + m.PrehashSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PrehashSubCount)) + m.PrehashSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PrehashSubTime)) + m.RecvSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.RecvSubCount)) + m.RecvSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.RecvSubTime)) + m.ReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ReqBodyBytes)) + m.ReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ReqHeaderBytes)) + m.RequestsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Requests)) + m.RespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.RespBodyBytes)) + m.RespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.RespHeaderBytes)) + m.RestartTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Restart)) + m.SegBlockOriginFetchesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.SegBlockOriginFetches)) + m.SegBlockShieldFetchesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.SegBlockShieldFetches)) + m.ShieldFetchBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldFetchBodyBytes)) + m.ShieldFetchHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldFetchHeaderBytes)) + m.ShieldFetchRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldFetchRespBodyBytes)) + m.ShieldFetchRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldFetchRespHeaderBytes)) + m.ShieldFetchesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldFetches)) + m.ShieldRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldRespBodyBytes)) + m.ShieldRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldRespHeaderBytes)) + m.ShieldRevalidationsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldRevalidations)) + m.ShieldTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Shield)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "200").Add(float64(stats.Status200)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "204").Add(float64(stats.Status204)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "206").Add(float64(stats.Status206)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "301").Add(float64(stats.Status301)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "302").Add(float64(stats.Status302)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "304").Add(float64(stats.Status304)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "400").Add(float64(stats.Status400)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "401").Add(float64(stats.Status401)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "403").Add(float64(stats.Status403)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "404").Add(float64(stats.Status404)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "416").Add(float64(stats.Status416)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "429").Add(float64(stats.Status429)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "500").Add(float64(stats.Status500)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "501").Add(float64(stats.Status501)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "502").Add(float64(stats.Status502)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "503").Add(float64(stats.Status503)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "504").Add(float64(stats.Status504)) + m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "505").Add(float64(stats.Status505)) + m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "1xx").Add(float64(stats.Status1xx)) + m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "2xx").Add(float64(stats.Status2xx)) + m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "3xx").Add(float64(stats.Status3xx)) + m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "4xx").Add(float64(stats.Status4xx)) + m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "5xx").Add(float64(stats.Status5xx)) + m.SynthsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Synths)) + m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "any").Add(float64(stats.TLS)) + m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "v10").Add(float64(stats.TLSv10)) + m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "v11").Add(float64(stats.TLSv11)) + m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "v12").Add(float64(stats.TLSv12)) + m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "v13").Add(float64(stats.TLSv13)) + m.UncacheableTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Uncacheable)) + m.VideoTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Video)) + m.WAFBlockedTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.WAFBlocked)) + m.WAFLoggedTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.WAFLogged)) + m.WAFPassedTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.WAFPassed)) + } + } +} + +func processHistogram(src map[string]uint64, obs prometheus.Observer) { + for str, count := range src { + ms, err := strconv.Atoi(str) + if err != nil { + continue + } + s := float64(ms) / 1e3 + for i := 0; i < int(count); i++ { + obs.Observe(s) + } + } +} + +func processObjectSizes(n1k, n10k, n100k, n1m, n10m, n100m, n1g uint64, obs prometheus.Observer) { + for v, n := range map[uint64]uint64{ + 1 * 1024: n1k, + 10 * 1024: n10k, + 100 * 1024: n100k, + 1 * 1000 * 1024: n1m, + 10 * 1000 * 1024: n10m, + 100 * 1000 * 1024: n100m, + 1000 * 1000 * 1024: n1g, + } { + for i := uint64(0); i < n; i++ { + obs.Observe(float64(v)) + } + } +} diff --git a/pkg/prom/doc.go b/pkg/prom/doc.go deleted file mode 100644 index 32d9910..0000000 --- a/pkg/prom/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package prom defines the Prometheus metrics the exporter exposes. -package prom diff --git a/pkg/prom/metrics.go b/pkg/prom/metrics.go deleted file mode 100644 index 9300154..0000000 --- a/pkg/prom/metrics.go +++ /dev/null @@ -1,471 +0,0 @@ -package prom - -import ( - "fmt" - "reflect" - "regexp" - - "github.com/peterbourgon/fastly-exporter/pkg/filter" - "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" -) - -// Metrics are the concrete Prometheus metrics that get updated with data -// retrieved from the real-time stats API. The same set of metrics are updated -// for all service IDs, only the labels change. -type Metrics struct { - // These metrics concern the exporter itself. - RealtimeAPIRequestsTotal *prometheus.CounterVec - - // These metrics concern the Fastly service. - ServiceInfo *prometheus.GaugeVec - RequestsTotal *prometheus.CounterVec - TLSTotal *prometheus.CounterVec - ShieldTotal *prometheus.CounterVec - IPv6Total *prometheus.CounterVec - ImgOptoTotal *prometheus.CounterVec - ImgOptoShieldTotal *prometheus.CounterVec - ImgOptoTransformTotal *prometheus.CounterVec - OTFPTotal *prometheus.CounterVec - OTFPShieldTotal *prometheus.CounterVec - OTFPTransformTotal *prometheus.CounterVec - OTFPManifestTotal *prometheus.CounterVec - VideoTotal *prometheus.CounterVec - PCITotal *prometheus.CounterVec - LoggingTotal *prometheus.CounterVec - HTTP2Total *prometheus.CounterVec - RespHeaderBytesTotal *prometheus.CounterVec - HeaderSizeTotal *prometheus.CounterVec - RespBodyBytesTotal *prometheus.CounterVec - BodySizeTotal *prometheus.CounterVec - ReqHeaderBytesTotal *prometheus.CounterVec - BackendReqHeaderBytesTotal *prometheus.CounterVec - BilledHeaderBytesTotal *prometheus.CounterVec - BilledBodyBytesTotal *prometheus.CounterVec - WAFBlockedTotal *prometheus.CounterVec - WAFLoggedTotal *prometheus.CounterVec - WAFPassedTotal *prometheus.CounterVec - AttackReqHeaderBytesTotal *prometheus.CounterVec - AttackReqBodyBytesTotal *prometheus.CounterVec - AttackRespSynthBytesTotal *prometheus.CounterVec - AttackLoggedReqHeaderBytesTotal *prometheus.CounterVec - AttackLoggedReqBodyBytesTotal *prometheus.CounterVec - AttackBlockedReqHeaderBytesTotal *prometheus.CounterVec - AttackBlockedReqBodyBytesTotal *prometheus.CounterVec - AttackPassedReqHeaderBytesTotal *prometheus.CounterVec - AttackPassedReqBodyBytesTotal *prometheus.CounterVec - ShieldRespHeaderBytesTotal *prometheus.CounterVec - ShieldRespBodyBytesTotal *prometheus.CounterVec - OTFPRespHeaderBytesTotal *prometheus.CounterVec - OTFPRespBodyBytesTotal *prometheus.CounterVec - OTFPShieldRespHeaderBytesTotal *prometheus.CounterVec - OTFPShieldRespBodyBytesTotal *prometheus.CounterVec - OTFPTransformRespHeaderBytesTotal *prometheus.CounterVec - OTFPTransformRespBodyBytesTotal *prometheus.CounterVec - OTFPShieldTimeTotal *prometheus.CounterVec - OTFPTransformTimeTotal *prometheus.CounterVec - OTFPDeliverTimeTotal *prometheus.CounterVec - ImgOptoRespHeaderBytesTotal *prometheus.CounterVec - ImgOptoRespBodyBytesTotal *prometheus.CounterVec - ImgOptoShieldRespHeaderBytesTotal *prometheus.CounterVec - ImgOptoShieldRespBodyBytesTotal *prometheus.CounterVec - ImgOptoTransformRespHeaderBytesTotal *prometheus.CounterVec - ImgOptoTransformRespBodyBytesTotal *prometheus.CounterVec - StatusGroupTotal *prometheus.CounterVec - StatusCodeTotal *prometheus.CounterVec - HitsTotal *prometheus.CounterVec - MissesTotal *prometheus.CounterVec - PassesTotal *prometheus.CounterVec - SynthsTotal *prometheus.CounterVec - ErrorsTotal *prometheus.CounterVec - UncacheableTotal *prometheus.CounterVec - HitsTimeTotal *prometheus.CounterVec - MissTimeTotal *prometheus.CounterVec - PassTimeTotal *prometheus.CounterVec - MissDurationSeconds *prometheus.HistogramVec - ObjectSizeBytes *prometheus.HistogramVec - RecvSubTimeTotal *prometheus.CounterVec - RecvSubCountTotal *prometheus.CounterVec - HashSubTimeTotal *prometheus.CounterVec - HashSubCountTotal *prometheus.CounterVec - MissSubTimeTotal *prometheus.CounterVec - MissSubCountTotal *prometheus.CounterVec - FetchSubTimeTotal *prometheus.CounterVec - FetchSubCountTotal *prometheus.CounterVec - DeliverSubTimeTotal *prometheus.CounterVec - DeliverSubCountTotal *prometheus.CounterVec - HitSubTimeTotal *prometheus.CounterVec - HitSubCountTotal *prometheus.CounterVec - PrehashSubTimeTotal *prometheus.CounterVec - PrehashSubCountTotal *prometheus.CounterVec - PredeliverSubTimeTotal *prometheus.CounterVec - PredeliverSubCountTotal *prometheus.CounterVec -} - -// NewMetrics returns a usable set of Prometheus metrics -// that have been registered to the provided registerer. -func NewMetrics(namespace, subsystem string, nameFilter filter.Filter, r prometheus.Registerer) (*Metrics, error) { - var m Metrics - m.RealtimeAPIRequestsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "realtime_api_requests_total", - Help: "Total requests made to the real-time stats API.", - }, []string{"service_id", "service_name", "result"}) - m.ServiceInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{Namespace: namespace, Subsystem: subsystem, - Name: "service_info", - Help: "Static gauge with service ID, name, and version information.", - }, []string{"service_id", "service_name", "service_version"}) - m.RequestsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "requests_total", - Help: "Total number of requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.TLSTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "tls_total", - Help: "Total number of TLS requests.", - }, []string{"service_id", "service_name", "datacenter", "tls_version"}) - m.ShieldTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "shield_total", - Help: "Total number of shield requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.IPv6Total = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "ipv6_total", - Help: "Total number of IPv6 requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_total", - Help: "Total number of image optimization requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoShieldTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_shield_total", - Help: "Total number of image optimization shield requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoTransformTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_transforms_total", - Help: "Total number of image optimization transforms.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_total", - Help: "Total number of on-the-fly package requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPShieldTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_shield_total", - Help: "Total number of on-the-fly package shield requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPTransformTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_transforms_total", - Help: "Total number of on-the-fly package transforms.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPManifestTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_manifests_total", - Help: "Total number of on-the-fly package manifests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.VideoTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "video_total", - Help: "Total number of video requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.PCITotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "pci_total", - Help: "Total number of PCI requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.LoggingTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "logging_total", - Help: "Total number of logging requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.HTTP2Total = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "http2_total", - Help: "Total number of HTTP2 requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.RespHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "resp_header_bytes_total", - Help: "Total size of response headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.HeaderSizeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "header_size_total", - Help: "Total size of headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.RespBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "resp_body_bytes_total", - Help: "Total size of response bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.BodySizeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "body_size_total", - Help: "Total size of bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ReqHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "req_header_bytes_total", - Help: "Total size of request headers, in bytes", - }, []string{"service_id", "service_name", "datacenter"}) - m.BackendReqHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "bereq_header_bytes_total", - Help: "Total size of backend headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.BilledHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "billed_header_bytes_total", - Help: "Total count of billed headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.BilledBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "billed_body_bytes_total", - Help: "Total count of billed bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.WAFBlockedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "waf_blocked_total", - Help: "Total number of WAF blocked requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.WAFLoggedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "waf_logged_total", - Help: "Total number of WAF logged requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.WAFPassedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "waf_passed_total", - Help: "Total number of WAF passed requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackReqHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_req_header_bytes_total", - Help: "Total count of 'attack' classified request headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackReqBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_req_body_bytes_total", - Help: "Total count of 'attack' classified request bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackRespSynthBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_resp_synth_bytes_total", - Help: "Total count of 'attack' classified synth responses, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackLoggedReqHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_logged_req_header_bytes_total", - Help: "Total count of 'attack' classified request headers logged, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackLoggedReqBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_logged_req_body_bytes_total", - Help: "Total count of 'attack' classified request bodies logged, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackBlockedReqHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_blocked_req_header_bytes_total", - Help: "Total count of 'attack' classified request headers blocked, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackBlockedReqBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_blocked_req_body_bytes_total", - Help: "Total count of 'attack' classified request bodies blocked, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackPassedReqHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_passed_req_header_bytes_total", - Help: "Total size of 'attack' classified request headers passed, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.AttackPassedReqBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "attack_passed_req_body_bytes_total", - Help: "Total size of 'attack' classified request bodies passed, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ShieldRespHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "shield_resp_header_bytes_total", - Help: "Total size of shielded response headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ShieldRespBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "shield_resp_body_bytes_total", - Help: "Total size of shielded response bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPRespHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_resp_header_bytes_total", - Help: "Total size of on-the-fly package response headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPRespBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_resp_body_bytes_total", - Help: "Total size of on-the-fly package response bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPShieldRespHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_shield_resp_header_bytes_total", - Help: "Total size of on-the-fly package shield response headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPShieldRespBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_shield_resp_body_bytes_total", - Help: "Total size of on-the-fly package shield response bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPTransformRespHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_transform_resp_header_bytes_total", - Help: "Total size of on-the-fly package transform response headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPTransformRespBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_transform_resp_body_bytes_total", - Help: "Total size of on-the-fly package transform response bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPShieldTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_shield_time_total", - Help: "Total time spent in on-the-fly package shield.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPTransformTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_transform_time_total", - Help: "Total time spent in on-the-fly package transforms.", - }, []string{"service_id", "service_name", "datacenter"}) - m.OTFPDeliverTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "otfp_deliver_time_total", - Help: "Total time spent in on-the-fly package delivery.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoRespHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_resp_header_bytes_total", - Help: "Total count of image optimization response headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoRespBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_resp_body_bytes_total", - Help: "Total count of image optimization response bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoShieldRespHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_shield_resp_header_bytes_total", - Help: "Total count of image optimization shield response headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoShieldRespBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_shield_resp_body_bytes_total", - Help: "Total count of image optimization shield response bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoTransformRespHeaderBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_transform_resp_header_bytes_total", - Help: "Total count of image optimization transform response headers, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ImgOptoTransformRespBodyBytesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "imgopto_transform_resp_body_bytes_total", - Help: "Total count of image optimization transform response bodies, in bytes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.StatusGroupTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "status_group_total", - Help: "Total count of requests, bucketed into status groups e.g. 1xx, 2xx.", - }, []string{"service_id", "service_name", "datacenter", "status_group"}) // e.g. 1xx, 2xx - m.StatusCodeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "status_code_total", - Help: "Total count of requests, bucketed into individual status codes.", - }, []string{"service_id", "service_name", "datacenter", "status_code"}) // e.g. 200, 404 - m.HitsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "hits_total", - Help: "Total count of hits.", - }, []string{"service_id", "service_name", "datacenter"}) - m.MissesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "miss_total", - Help: "Total count of misses.", - }, []string{"service_id", "service_name", "datacenter"}) - m.PassesTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "pass_total", - Help: "Total count of passes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.SynthsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "synth_total", - Help: "Total count of synths.", - }, []string{"service_id", "service_name", "datacenter"}) - m.ErrorsTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "errors_total", - Help: "Total count of errors.", - }, []string{"service_id", "service_name", "datacenter"}) - m.UncacheableTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "uncacheable_total", - Help: "Total count of uncachable responses.", - }, []string{"service_id", "service_name", "datacenter"}) - m.HitsTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "hits_time_total", - Help: "Total time spent serving hits.", - }, []string{"service_id", "service_name", "datacenter"}) - m.MissTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "miss_time_total", - Help: "Total time spent serving misses.", - }, []string{"service_id", "service_name", "datacenter"}) - m.PassTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "pass_time_total", - Help: "Total time spent serving passes.", - }, []string{"service_id", "service_name", "datacenter"}) - m.MissDurationSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{Namespace: namespace, Subsystem: subsystem, - Name: "miss_duration_seconds", - Help: "Total time spent serving misses.", - Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2, 4, 8, 16, 32, 60}, - }, []string{"service_id", "service_name", "datacenter"}) - m.ObjectSizeBytes = prometheus.NewHistogramVec(prometheus.HistogramOpts{Namespace: namespace, Subsystem: subsystem, - Name: "object_size_bytes", - Help: "Size of objects served in bytes.", - Buckets: []float64{1 * 1024, 10 * 1024, 100 * 1024, 1 * 1000 * 1024, 10 * 1000 * 1024, 100 * 1000 * 1024, 1000 * 1000 * 1024}, - }, []string{"service_id", "service_name", "datacenter"}) - m.RecvSubTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "recv_sub_time_total", - Help: "Total receive sub time.", - }, []string{"service_id", "service_name", "datacenter"}) - m.RecvSubCountTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "recv_sub_count_total", - Help: "Total receive sub requests.", - }, []string{"service_id", "service_name", "datacenter"}) - m.HashSubTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "hash_sub_time_total", - Help: "Total hash sub time.", - }, []string{"service_id", "service_name", "datacenter"}) - m.HashSubCountTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "hash_sub_count_total", - Help: "Total hash sub count.", - }, []string{"service_id", "service_name", "datacenter"}) - m.MissSubTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "miss_sub_time_total", - Help: "Total miss sub time.", - }, []string{"service_id", "service_name", "datacenter"}) - m.MissSubCountTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "miss_sub_count_total", - Help: "Total miss sub count.", - }, []string{"service_id", "service_name", "datacenter"}) - m.FetchSubTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "fetch_sub_time_total", - Help: "Total fetch sub time.", - }, []string{"service_id", "service_name", "datacenter"}) - m.FetchSubCountTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "fetch_sub_count_total", - Help: "Total fetch sub count.", - }, []string{"service_id", "service_name", "datacenter"}) - m.DeliverSubTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "deliver_sub_time_total", - Help: "Total deliver sub time.", - }, []string{"service_id", "service_name", "datacenter"}) - m.DeliverSubCountTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "deliver_sub_count_total", - Help: "Total deliver sub count.", - }, []string{"service_id", "service_name", "datacenter"}) - m.HitSubTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "hit_sub_time_total", - Help: "Total hit sub time.", - }, []string{"service_id", "service_name", "datacenter"}) - m.HitSubCountTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "hit_sub_count_total", - Help: "Total hit sub count.", - }, []string{"service_id", "service_name", "datacenter"}) - m.PrehashSubTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "prehash_sub_time_total", - Help: "Total prehash sub time.", - }, []string{"service_id", "service_name", "datacenter"}) - m.PrehashSubCountTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "prehash_sub_count_total", - Help: "Total prehash sub count.", - }, []string{"service_id", "service_name", "datacenter"}) - m.PredeliverSubTimeTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "predeliver_sub_time_total", - Help: "Total predeliver sub time.", - }, []string{"service_id", "service_name", "datacenter"}) - m.PredeliverSubCountTotal = prometheus.NewCounterVec(prometheus.CounterOpts{Namespace: namespace, Subsystem: subsystem, - Name: "predeliver_sub_count_total", - Help: "Total predeliver sub count.", - }, []string{"service_id", "service_name", "datacenter"}) - - for i, v := 0, reflect.ValueOf(m); i < v.NumField(); i++ { - c, ok := v.Field(i).Interface().(prometheus.Collector) - if !ok { - panic(fmt.Sprintf("programmer error: field %d/%d in prom.Metrics isn't a prometheus.Collector", i+1, v.NumField())) - } - if name := getName(c); !nameFilter.Permit(name) { - continue - } - if err := r.Register(c); err != nil { - return nil, errors.Wrapf(err, "error registering metric %d/%d", i+1, v.NumField()) - } - } - - return &m, nil -} - -var descNameRegex = regexp.MustCompile(`fqName: "([^"]+)"`) - -func getName(c prometheus.Collector) string { - d := make(chan *prometheus.Desc, 1) - c.Describe(d) - desc := (<-d).String() - matches := descNameRegex.FindAllStringSubmatch(desc, -1) - if len(matches) == 1 && len(matches[0]) == 2 { - return matches[0][1] - } - return "" -} diff --git a/pkg/prom/metrics_test.go b/pkg/prom/metrics_test.go deleted file mode 100644 index a16261a..0000000 --- a/pkg/prom/metrics_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package prom_test - -import ( - "testing" - - "github.com/peterbourgon/fastly-exporter/pkg/filter" - "github.com/peterbourgon/fastly-exporter/pkg/prom" - "github.com/prometheus/client_golang/prometheus" -) - -func TestRegistration(t *testing.T) { - var ( - namespace = "namespace" - subsystem = "subsystem" - nameFilter = filter.Filter{} // allow all - registry = prometheus.NewRegistry() - ) - - { - _, err := prom.NewMetrics(namespace, subsystem, nameFilter, registry) - if err != nil { - t.Errorf("unexpected error on first construction: %v", err) - } - } - { - _, err := prom.NewMetrics(namespace, subsystem, nameFilter, registry) - if err == nil { - t.Error("unexpected success on second construction") - } - } - { - _, err := prom.NewMetrics("alt"+namespace, subsystem, nameFilter, registry) - if err != nil { - t.Errorf("unexpected error on third, alt-namespace construction: %v", err) - } - } -} diff --git a/pkg/rt/common_test.go b/pkg/rt/common_test.go index c88b47a..7924712 100644 --- a/pkg/rt/common_test.go +++ b/pkg/rt/common_test.go @@ -176,223 +176,282 @@ func prometheusOutput(t *testing.T, registry *prometheus.Registry, prefix string // const rtResponseFixture = `{ - "Data": [ - { - "datacenter": { - "BWI": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - } - }, - "aggregated": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "recorded": 1541085726 - } - ], - "Timestamp": 1541085735, - "AggregateDelay": 9 + "Data": [ + { + "datacenter": { + "SJC": { + "requests": 1, + "tls": 1, + "resp_header_bytes": 450, + "header_size": 450, + "resp_body_bytes": 1494, + "body_size": 1494, + "req_header_bytes": 210, + "bereq_header_bytes": 675, + "billed_header_bytes": 450, + "billed_body_bytes": 1494, + "status_2xx": 1, + "status_200": 1, + "hits": 0, + "miss": 1, + "pass": 0, + "synth": 0, + "errors": 0, + "hits_time": 0, + "miss_time": 0.069132, + "miss_histogram": { + "70": 1 + }, + "tls_v12": 1, + "object_size_10k": 1, + "recv_sub_time": 860249, + "recv_sub_count": 2, + "hash_sub_time": 4540, + "hash_sub_count": 1, + "miss_sub_time": 994, + "miss_sub_count": 1, + "deliver_sub_time": 19082, + "deliver_sub_count": 1, + "prehash_sub_time": 802, + "prehash_sub_count": 1, + "predeliver_sub_time": 835, + "predeliver_sub_count": 1, + "miss_resp_body_bytes": 1494, + "edge_requests": 1, + "edge_resp_header_bytes": 450, + "edge_resp_body_bytes": 1494, + "origin_fetches": 1, + "origin_fetch_header_bytes": 675, + "origin_fetch_resp_header_bytes": 250, + "origin_fetch_resp_body_bytes": 2907 + } + }, + "aggregated": { + "requests": 1, + "tls": 1, + "resp_header_bytes": 450, + "header_size": 450, + "resp_body_bytes": 1494, + "body_size": 1494, + "req_header_bytes": 210, + "bereq_header_bytes": 675, + "billed_header_bytes": 450, + "billed_body_bytes": 1494, + "status_2xx": 1, + "status_200": 1, + "hits": 0, + "miss": 1, + "pass": 0, + "synth": 0, + "errors": 0, + "hits_time": 0, + "miss_time": 0.069132, + "miss_histogram": { + "70": 1 + }, + "tls_v12": 1, + "object_size_10k": 1, + "recv_sub_time": 860249, + "recv_sub_count": 2, + "hash_sub_time": 4540, + "hash_sub_count": 1, + "miss_sub_time": 994, + "miss_sub_count": 1, + "deliver_sub_time": 19082, + "deliver_sub_count": 1, + "prehash_sub_time": 802, + "prehash_sub_count": 1, + "predeliver_sub_time": 835, + "predeliver_sub_count": 1, + "miss_resp_body_bytes": 1494, + "edge_requests": 1, + "edge_resp_header_bytes": 450, + "edge_resp_body_bytes": 1494, + "origin_fetches": 1, + "origin_fetch_header_bytes": 675, + "origin_fetch_resp_header_bytes": 250, + "origin_fetch_resp_body_bytes": 2907 + }, + "recorded": 1600223685 + } + ], + "Timestamp": 1600223694, + "AggregateDelay": 9 }` var expectedMetricsOutputSlice = strings.Split(strings.TrimSpace(` -testspace_testsystem_attack_blocked_req_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_attack_blocked_req_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_attack_logged_req_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_attack_logged_req_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_attack_passed_req_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_attack_passed_req_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_attack_req_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_attack_req_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_attack_resp_synth_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_bereq_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 599 -testspace_testsystem_billed_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 39 -testspace_testsystem_billed_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 441 -testspace_testsystem_body_size_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 39 -testspace_testsystem_deliver_sub_count_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_deliver_sub_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 26291 -testspace_testsystem_errors_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_fetch_sub_count_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 4 -testspace_testsystem_fetch_sub_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 70428 -testspace_testsystem_hash_sub_count_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_hash_sub_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1716 -testspace_testsystem_header_size_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 441 -testspace_testsystem_hit_sub_count_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_hit_sub_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_hits_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_hits_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_http2_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_resp_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_resp_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_shield_resp_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_shield_resp_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_shield_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_transform_resp_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_transform_resp_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_imgopto_transforms_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_ipv6_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_logging_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="+Inf"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="0.005"} 0 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="0.01"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="0.025"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="0.05"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="0.1"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="0.25"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="0.5"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="1"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="16"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="2"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="32"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="4"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="60"} 1 -testspace_testsystem_miss_duration_seconds_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="8"} 1 -testspace_testsystem_miss_duration_seconds_count{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_miss_duration_seconds_sum{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0.009 -testspace_testsystem_miss_sub_count_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 9 -testspace_testsystem_miss_sub_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 60677 -testspace_testsystem_miss_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0.008408 -testspace_testsystem_miss_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_object_size_bytes_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="+Inf"} 1 -testspace_testsystem_object_size_bytes_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="1.024e+06"} 1 -testspace_testsystem_object_size_bytes_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="1.024e+07"} 1 -testspace_testsystem_object_size_bytes_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="1.024e+08"} 1 -testspace_testsystem_object_size_bytes_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="1.024e+09"} 1 -testspace_testsystem_object_size_bytes_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="1024"} 1 -testspace_testsystem_object_size_bytes_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="10240"} 1 -testspace_testsystem_object_size_bytes_bucket{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",le="102400"} 1 -testspace_testsystem_object_size_bytes_count{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_object_size_bytes_sum{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1024 -testspace_testsystem_otfp_deliver_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_manifests_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_resp_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_resp_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_shield_resp_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_shield_resp_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_shield_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_shield_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_transform_resp_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_transform_resp_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_transform_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_otfp_transforms_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_pass_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_pass_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_pci_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_predeliver_sub_count_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_predeliver_sub_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1251 -testspace_testsystem_prehash_sub_count_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_prehash_sub_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 689 +testspace_testsystem_attack_blocked_req_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_attack_blocked_req_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_attack_logged_req_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_attack_logged_req_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_attack_passed_req_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_attack_passed_req_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_attack_req_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_attack_req_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_attack_resp_synth_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_bereq_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_bereq_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 675 +testspace_testsystem_billed_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1494 +testspace_testsystem_billed_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 450 +testspace_testsystem_billed_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_blacklist_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_body_size_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1494 +testspace_testsystem_deliver_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_deliver_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 19082 +testspace_testsystem_edge_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1494 +testspace_testsystem_edge_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 450 +testspace_testsystem_edge_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_error_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_error_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_errors_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_fetch_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_fetch_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_hash_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_hash_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 4540 +testspace_testsystem_header_size_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 450 +testspace_testsystem_hit_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_hit_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_hit_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_hits_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_hits_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_http2_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_shield_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_shield_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_shield_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_transform_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_transform_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgopto_transforms_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgvideo_frames_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgvideo_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgvideo_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgvideo_shield_frames_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgvideo_shield_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgvideo_shield_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgvideo_shield_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_imgvideo_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_ipv6_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_log_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_logging_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="+Inf"} 1 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.005"} 0 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.01"} 0 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.025"} 0 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.05"} 0 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.1"} 1 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.25"} 1 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.5"} 1 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="1"} 1 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="10"} 1 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="2.5"} 1 +testspace_testsystem_miss_duration_seconds_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="5"} 1 +testspace_testsystem_miss_duration_seconds_count{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_miss_duration_seconds_sum{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0.07 +testspace_testsystem_miss_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1494 +testspace_testsystem_miss_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_miss_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 994 +testspace_testsystem_miss_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0.069132 +testspace_testsystem_miss_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="+Inf"} 1 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.005"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.01"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.025"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.05"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.1"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.25"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="0.5"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="1"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="10"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="2.5"} 0 +testspace_testsystem_object_size_bytes_bucket{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",le="5"} 0 +testspace_testsystem_object_size_bytes_count{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_object_size_bytes_sum{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 10240 +testspace_testsystem_origin_fetch_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_origin_fetch_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 675 +testspace_testsystem_origin_fetch_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 2907 +testspace_testsystem_origin_fetch_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 250 +testspace_testsystem_origin_fetches_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_origin_revalidations_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_deliver_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_manifests_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_shield_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_shield_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_shield_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_shield_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_transform_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_transform_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_transform_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_otfp_transforms_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_pass_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_pass_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_pass_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_pass_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_pass_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_pci_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_pipe_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_pipe_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_predeliver_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_predeliver_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 835 +testspace_testsystem_prehash_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1 +testspace_testsystem_prehash_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 802 testspace_testsystem_realtime_api_requests_total{result="success",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_recv_sub_count_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 6 -testspace_testsystem_recv_sub_time_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1.872661e+06 -testspace_testsystem_req_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 294 -testspace_testsystem_requests_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 1 -testspace_testsystem_resp_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 39 -testspace_testsystem_resp_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 441 +testspace_testsystem_recv_sub_count_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 2 +testspace_testsystem_recv_sub_time_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 860249 +testspace_testsystem_req_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_req_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 210 +testspace_testsystem_requests_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 2 +testspace_testsystem_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 1494 +testspace_testsystem_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 450 +testspace_testsystem_restarts_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_segblock_origin_fetches_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_segblock_shield_fetches_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 testspace_testsystem_service_info{service_id="my-service-id",service_name="my-service-name",service_version="123"} 1 -testspace_testsystem_shield_resp_body_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_shield_resp_header_bytes_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_shield_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="200"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="204"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="301"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="302"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="304"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="400"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="401"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="403"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="404"} 1 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="416"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="500"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="501"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="502"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="503"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="504"} 0 -testspace_testsystem_status_code_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_code="505"} 0 -testspace_testsystem_status_group_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_group="1xx"} 0 -testspace_testsystem_status_group_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_group="2xx"} 0 -testspace_testsystem_status_group_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_group="3xx"} 0 -testspace_testsystem_status_group_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_group="4xx"} 1 -testspace_testsystem_status_group_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",status_group="5xx"} 0 -testspace_testsystem_synth_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_tls_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",tls_version="any"} 0 -testspace_testsystem_tls_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",tls_version="v10"} 0 -testspace_testsystem_tls_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",tls_version="v11"} 0 -testspace_testsystem_tls_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",tls_version="v12"} 0 -testspace_testsystem_tls_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name",tls_version="v13"} 0 -testspace_testsystem_uncacheable_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_video_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_waf_blocked_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_waf_logged_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 -testspace_testsystem_waf_passed_total{datacenter="BWI",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_fetch_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_fetch_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_fetch_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_fetch_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_fetches_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_resp_body_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_resp_header_bytes_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_revalidations_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_shield_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="200"} 1 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="204"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="206"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="301"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="302"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="304"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="400"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="401"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="403"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="404"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="416"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="429"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="500"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="501"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="502"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="503"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="504"} 0 +testspace_testsystem_status_code_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_code="505"} 0 +testspace_testsystem_status_group_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_group="1xx"} 0 +testspace_testsystem_status_group_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_group="2xx"} 1 +testspace_testsystem_status_group_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_group="3xx"} 0 +testspace_testsystem_status_group_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_group="4xx"} 0 +testspace_testsystem_status_group_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",status_group="5xx"} 0 +testspace_testsystem_synth_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_tls_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",tls_version="any"} 1 +testspace_testsystem_tls_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",tls_version="v10"} 0 +testspace_testsystem_tls_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",tls_version="v11"} 0 +testspace_testsystem_tls_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",tls_version="v12"} 1 +testspace_testsystem_tls_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name",tls_version="v13"} 0 +testspace_testsystem_uncacheable_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_video_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_waf_blocked_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_waf_logged_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 +testspace_testsystem_waf_passed_total{datacenter="SJC",service_id="my-service-id",service_name="my-service-name"} 0 `), "\n") diff --git a/pkg/rt/manager.go b/pkg/rt/manager.go index 18f86b8..4f09832 100644 --- a/pkg/rt/manager.go +++ b/pkg/rt/manager.go @@ -7,7 +7,7 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" - "github.com/peterbourgon/fastly-exporter/pkg/prom" + "github.com/peterbourgon/fastly-exporter/pkg/gen" ) // ServiceIdentifier is a consumer contract for a subscriber manager. @@ -23,7 +23,7 @@ type Manager struct { ids ServiceIdentifier client HTTPClient token string - metrics *prom.Metrics + metrics *gen.Metrics subscriberOptions []SubscriberOption logger log.Logger @@ -35,7 +35,7 @@ type Manager struct { // regular schedule to keep the set of managed subscribers up-to-date. The HTTP // client, token, metrics, and subscriber options parameters are passed thru to // constructed subscribers. -func NewManager(ids ServiceIdentifier, client HTTPClient, token string, metrics *prom.Metrics, subscriberOptions []SubscriberOption, logger log.Logger) *Manager { +func NewManager(ids ServiceIdentifier, client HTTPClient, token string, metrics *gen.Metrics, subscriberOptions []SubscriberOption, logger log.Logger) *Manager { return &Manager{ ids: ids, client: client, diff --git a/pkg/rt/manager_test.go b/pkg/rt/manager_test.go index 6cb8831..48b17f4 100644 --- a/pkg/rt/manager_test.go +++ b/pkg/rt/manager_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/peterbourgon/fastly-exporter/pkg/api" "github.com/peterbourgon/fastly-exporter/pkg/filter" - "github.com/peterbourgon/fastly-exporter/pkg/prom" + "github.com/peterbourgon/fastly-exporter/pkg/gen" "github.com/peterbourgon/fastly-exporter/pkg/rt" "github.com/prometheus/client_golang/prometheus" ) @@ -23,7 +23,7 @@ func TestManager(t *testing.T) { s3 = api.Service{ID: "3a3b3c", Name: "service 3", Version: 3} client = newMockRealtimeClient(`{}`) token = "irrelevant-token" - metrics, _ = prom.NewMetrics("namespace", "subsystem", filter.Filter{}, prometheus.NewRegistry()) + metrics, _ = gen.NewMetrics("namespace", "subsystem", filter.Filter{}, prometheus.NewRegistry()) logbuf = &bytes.Buffer{} logger = log.NewLogfmtLogger(logbuf) options = []rt.SubscriberOption{rt.WithMetadataProvider(cache)} diff --git a/pkg/rt/performance_test.go b/pkg/rt/performance_test.go deleted file mode 100644 index 0564175..0000000 --- a/pkg/rt/performance_test.go +++ /dev/null @@ -1,2511 +0,0 @@ -package rt - -import ( - "testing" -) - -// Test results as of 2019-07-19: -// BenchmarkUnmarshal_stdlib-12 1000 2248334 ns/op 2488845 B/op 28924 allocs/op -// BenchmarkUnmarshal_jsoniter-12 10000 209825 ns/op 292234 B/op 2954 allocs/op - -func BenchmarkUnmarshal_stdlib(b *testing.B) { - var rt realtimeResponse - b.ReportAllocs() - for i := 0; i < b.N; i++ { - if err := rt.unmarshalStdlib(rtResponseFixtureBig); err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkUnmarshal_jsoniter(b *testing.B) { - var rt realtimeResponse - b.ReportAllocs() - for i := 0; i < b.N; i++ { - if err := rt.unmarshalJsoniter(rtResponseFixtureBig); err != nil { - b.Fatal(err) - } - } -} - -var rtResponseFixtureBig = []byte(`{ - "Data": [ - { - "datacenter": { - "AMS": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "IAD": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "BWI": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "DCA": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "ATL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "FTY": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "PDK": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "AKL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "BOS": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "BNE": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "EZE": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "CPT": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "MAA": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "ORD": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "CHI": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "MDW": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "CMH": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "CPH": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "CWB": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "DFW": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "DAL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "DEL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "DEN": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "FRA": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "HHN": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "FJR": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "HEL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "HKG": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "IAH": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "JNB": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "LCY": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "LHR": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "BUR": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "LAX": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "MAD": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "MEL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "MIA": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "MXP": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "MSP": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "YUL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "BOM": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "JFK": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "LGA": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "EWR": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "ITM": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "OSL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "PAO": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "CDG": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "PER": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "GIG": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "SJC": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "SCL": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "GRU": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "SEA": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "QPG": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "SIN": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "BMA": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "SYD": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "TYO": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "HND": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "NRT": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "YYZ": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "YVR": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "WLG": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - } - }, - "aggregated": { - "requests": 1, - "resp_header_bytes": 441, - "header_size": 441, - "resp_body_bytes": 39, - "body_size": 39, - "req_header_bytes": 294, - "bereq_header_bytes": 599, - "billed_header_bytes": 441, - "billed_body_bytes": 39, - "status_4xx": 1, - "status_404": 1, - "hits": 0, - "miss": 1, - "pass": 0, - "synth": 0, - "errors": 0, - "hits_time": 0, - "miss_time": 0.008408, - "miss_histogram": { - "9": 1 - }, - "object_size_1k": 1, - "recv_sub_time": 1872661, - "recv_sub_count": 6, - "hash_sub_time": 1716, - "hash_sub_count": 1, - "miss_sub_time": 60677, - "miss_sub_count": 9, - "fetch_sub_time": 70428, - "fetch_sub_count": 4, - "deliver_sub_time": 26291, - "deliver_sub_count": 1, - "prehash_sub_time": 689, - "prehash_sub_count": 1, - "predeliver_sub_time": 1251, - "predeliver_sub_count": 1 - }, - "recorded": 1541085726 - } - ], - "Timestamp": 1541085735, - "AggregateDelay": 9 -}`) diff --git a/pkg/rt/process.go b/pkg/rt/process.go deleted file mode 100644 index e1ce95e..0000000 --- a/pkg/rt/process.go +++ /dev/null @@ -1,155 +0,0 @@ -package rt - -import ( - "strconv" - - "github.com/peterbourgon/fastly-exporter/pkg/prom" - "github.com/prometheus/client_golang/prometheus" -) - -// process the data from the realtime response, and feed the interpreted results -// to the Prometheus metrics as observations. -func process(resp realtimeResponse, serviceID, serviceName, serviceVersion string, m *prom.Metrics) { - for _, d := range resp.Data { - for datacenter, stats := range d.Datacenter { - m.ServiceInfo.WithLabelValues(serviceID, serviceName, serviceVersion).Set(1) - m.RequestsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Requests)) - m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "any").Add(float64(stats.TLS)) - m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "v10").Add(float64(stats.TLSv10)) - m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "v11").Add(float64(stats.TLSv11)) - m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "v12").Add(float64(stats.TLSv12)) - m.TLSTotal.WithLabelValues(serviceID, serviceName, datacenter, "v13").Add(float64(stats.TLSv13)) - m.ShieldTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Shield)) - m.IPv6Total.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.IPv6)) - m.ImgOptoTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOpto)) - m.ImgOptoShieldTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoShield)) - m.ImgOptoTransformTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoTransform)) - m.OTFPTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFP)) - m.OTFPShieldTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPShield)) - m.OTFPTransformTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPTransform)) - m.OTFPManifestTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPManifest)) - m.VideoTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Video)) - m.PCITotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PCI)) - m.LoggingTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Logging)) - m.HTTP2Total.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HTTP2)) - m.RespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.RespHeaderBytes)) - m.HeaderSizeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HeaderSize)) - m.RespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.RespBodyBytes)) - m.BodySizeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BodySize)) - m.ReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ReqHeaderBytes)) - m.BackendReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BackendReqHeaderBytes)) - m.BilledHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BilledHeaderBytes)) - m.BilledBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.BilledBodyBytes)) - m.WAFBlockedTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.WAFBlocked)) - m.WAFLoggedTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.WAFLogged)) - m.WAFPassedTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.WAFPassed)) - m.AttackReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackReqHeaderBytes)) - m.AttackReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackReqBodyBytes)) - m.AttackRespSynthBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackRespSynthBytes)) - m.AttackLoggedReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackLoggedReqHeaderBytes)) - m.AttackLoggedReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackLoggedReqBodyBytes)) - m.AttackBlockedReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackBlockedReqHeaderBytes)) - m.AttackBlockedReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackBlockedReqBodyBytes)) - m.AttackPassedReqHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackPassedReqHeaderBytes)) - m.AttackPassedReqBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.AttackPassedReqBodyBytes)) - m.ShieldRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldRespHeaderBytes)) - m.ShieldRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ShieldRespBodyBytes)) - m.OTFPRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPRespHeaderBytes)) - m.OTFPRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPRespBodyBytes)) - m.OTFPShieldRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPShieldRespHeaderBytes)) - m.OTFPShieldRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPShieldRespBodyBytes)) - m.OTFPTransformRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPTransformRespHeaderBytes)) - m.OTFPTransformRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPTransformRespBodyBytes)) - m.OTFPShieldTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPShieldTime)) - m.OTFPTransformTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPTransformTime)) - m.OTFPDeliverTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.OTFPDeliverTime)) - m.ImgOptoRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoRespHeaderBytes)) - m.ImgOptoRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoRespBodyBytes)) - m.ImgOptoShieldRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoShieldRespHeaderBytes)) - m.ImgOptoShieldRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoShieldRespBodyBytes)) - m.ImgOptoTransformRespHeaderBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoTransformRespHeaderBytes)) - m.ImgOptoTransformRespBodyBytesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.ImgOptoTransformRespBodyBytes)) - m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "1xx").Add(float64(stats.Status1xx)) - m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "2xx").Add(float64(stats.Status2xx)) - m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "3xx").Add(float64(stats.Status3xx)) - m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "4xx").Add(float64(stats.Status4xx)) - m.StatusGroupTotal.WithLabelValues(serviceID, serviceName, datacenter, "5xx").Add(float64(stats.Status5xx)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "200").Add(float64(stats.Status200)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "204").Add(float64(stats.Status204)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "301").Add(float64(stats.Status301)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "302").Add(float64(stats.Status302)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "304").Add(float64(stats.Status304)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "400").Add(float64(stats.Status400)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "401").Add(float64(stats.Status401)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "403").Add(float64(stats.Status403)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "404").Add(float64(stats.Status404)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "416").Add(float64(stats.Status416)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "500").Add(float64(stats.Status500)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "501").Add(float64(stats.Status501)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "502").Add(float64(stats.Status502)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "503").Add(float64(stats.Status503)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "504").Add(float64(stats.Status504)) - m.StatusCodeTotal.WithLabelValues(serviceID, serviceName, datacenter, "505").Add(float64(stats.Status505)) - m.HitsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Hits)) - m.MissesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Misses)) - m.PassesTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Passes)) - m.SynthsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Synths)) - m.ErrorsTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Errors)) - m.UncacheableTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.Uncacheable)) - m.HitsTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HitsTime)) - m.MissTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.MissTime)) - m.PassTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PassTime)) - processHistogram(stats.MissHistogram, m.MissDurationSeconds.WithLabelValues(serviceID, serviceName, datacenter)) - processObjectSizes( - stats.ObjectSize1k, stats.ObjectSize10k, stats.ObjectSize100k, - stats.ObjectSize1m, stats.ObjectSize10m, stats.ObjectSize100m, - stats.ObjectSize1g, m.ObjectSizeBytes.WithLabelValues(serviceID, serviceName, datacenter), - ) - m.RecvSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.RecvSubTime)) - m.RecvSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.RecvSubCount)) - m.HashSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HashSubTime)) - m.HashSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HashSubCount)) - m.MissSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.MissSubTime)) - m.MissSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.MissSubCount)) - m.FetchSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.FetchSubTime)) - m.FetchSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.FetchSubCount)) - m.DeliverSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.DeliverSubTime)) - m.DeliverSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.DeliverSubCount)) - m.HitSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HitSubTime)) - m.HitSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.HitSubCount)) - m.PrehashSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PrehashSubTime)) - m.PrehashSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PrehashSubCount)) - m.PredeliverSubTimeTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PredeliverSubTime)) - m.PredeliverSubCountTotal.WithLabelValues(serviceID, serviceName, datacenter).Add(float64(stats.PredeliverSubCount)) - } - } -} - -func processHistogram(src map[string]uint64, obs prometheus.Observer) { - for str, count := range src { - ms, err := strconv.Atoi(str) - if err != nil { - continue - } - s := float64(ms) / 1e3 - for i := 0; i < int(count); i++ { - obs.Observe(s) - } - } -} - -func processObjectSizes(n1k, n10k, n100k, n1m, n10m, n100m, n1g uint64, obs prometheus.Observer) { - for v, n := range map[uint64]uint64{ - 1 * 1024: n1k, - 10 * 1024: n10k, - 100 * 1024: n100k, - 1 * 1000 * 1024: n1m, - 10 * 1000 * 1024: n10m, - 100 * 1000 * 1024: n100m, - 1000 * 1000 * 1024: n1g, - } { - for i := uint64(0); i < n; i++ { - obs.Observe(float64(v)) - } - } -} diff --git a/pkg/rt/subscriber.go b/pkg/rt/subscriber.go index 51ac630..fbef55a 100644 --- a/pkg/rt/subscriber.go +++ b/pkg/rt/subscriber.go @@ -2,7 +2,6 @@ package rt import ( "context" - "encoding/json" "fmt" "net/http" "net/url" @@ -13,7 +12,7 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" jsoniter "github.com/json-iterator/go" - "github.com/peterbourgon/fastly-exporter/pkg/prom" + "github.com/peterbourgon/fastly-exporter/pkg/gen" "github.com/pkg/errors" ) @@ -37,7 +36,7 @@ type Subscriber struct { token string serviceID string provider MetadataProvider - metrics *prom.Metrics + metrics *gen.Metrics postprocess func() logger log.Logger } @@ -78,7 +77,7 @@ const DefaultUserAgent = "Fastly-Exporter (unknown version)" // NewSubscriber returns a ready-to-use subscriber. // Run must be called to update the metrics. -func NewSubscriber(client HTTPClient, token, serviceID string, metrics *prom.Metrics, options ...SubscriberOption) *Subscriber { +func NewSubscriber(client HTTPClient, token, serviceID string, metrics *gen.Metrics, options ...SubscriberOption) *Subscriber { s := &Subscriber{ client: client, userAgent: DefaultUserAgent, @@ -131,7 +130,7 @@ func (s *Subscriber) Run(ctx context.Context) error { // timestamp that should be provided to the next call to query, and an error. // Recoverable errors are logged internally and not returned, so any non-nil // error returned by this method should be considered fatal to the subscriber. -func (s *Subscriber) query(ctx context.Context, ts uint64) (currentName string, result rtResult, delay time.Duration, newts uint64, fatal error) { +func (s *Subscriber) query(ctx context.Context, ts uint64) (currentName string, result apiResult, delay time.Duration, newts uint64, fatal error) { name, ver, found := s.provider.Metadata(s.serviceID) version := strconv.Itoa(ver) if !found { @@ -143,7 +142,7 @@ func (s *Subscriber) query(ctx context.Context, ts uint64) (currentName string, u := fmt.Sprintf("https://rt.fastly.com/v1/channel/%s/ts/%d", url.QueryEscape(s.serviceID), ts) req, err := http.NewRequest("GET", u, nil) if err != nil { - return name, rtResultError, 0, ts, errors.Wrap(err, "error constructing real-time stats API request") + return name, apiResultError, 0, ts, errors.Wrap(err, "error constructing real-time stats API request") } req.Header.Set("User-Agent", s.userAgent) @@ -152,204 +151,66 @@ func (s *Subscriber) query(ctx context.Context, ts uint64) (currentName string, resp, err := s.client.Do(req.WithContext(ctx)) if err != nil { level.Error(s.logger).Log("during", "execute request", "err", err) - return name, rtResultError, time.Second, ts, nil + return name, apiResultError, time.Second, ts, nil } - var rt realtimeResponse - if err := jsoniterAPI.NewDecoder(resp.Body).Decode(&rt); err != nil { + var response gen.APIResponse + if err := jsoniterAPI.NewDecoder(resp.Body).Decode(&response); err != nil { resp.Body.Close() level.Error(s.logger).Log("during", "decode response", "err", err) - return name, rtResultError, time.Second, ts, nil + return name, apiResultError, time.Second, ts, nil } resp.Body.Close() - rterr := rt.Error - if rterr == "" { - rterr = "" + apiErr := response.Error + if apiErr == "" { + apiErr = "" } switch resp.StatusCode { case http.StatusOK: - level.Debug(s.logger).Log("status_code", resp.StatusCode, "response_ts", rt.Timestamp, "err", rterr) - if strings.Contains(rterr, "No data available") { - result = rtResultNoData + level.Debug(s.logger).Log("status_code", resp.StatusCode, "response_ts", response.Timestamp, "err", apiErr) + if strings.Contains(apiErr, "No data available") { + result = apiResultNoData } else { - result = rtResultSuccess + result = apiResultSuccess } - process(rt, s.serviceID, name, version, s.metrics) + gen.Process(&response, s.serviceID, name, version, s.metrics) s.postprocess() case http.StatusUnauthorized, http.StatusForbidden: - result = rtResultError - level.Error(s.logger).Log("status_code", resp.StatusCode, "response_ts", rt.Timestamp, "err", rterr, "msg", "token may be invalid") + result = apiResultError + level.Error(s.logger).Log("status_code", resp.StatusCode, "response_ts", response.Timestamp, "err", apiErr, "msg", "token may be invalid") delay = 15 * time.Second default: - result = rtResultUnknown - level.Error(s.logger).Log("status_code", resp.StatusCode, "response_ts", rt.Timestamp, "err", rterr) + result = apiResultUnknown + level.Error(s.logger).Log("status_code", resp.StatusCode, "response_ts", response.Timestamp, "err", apiErr) delay = 5 * time.Second } - return name, result, delay, rt.Timestamp, nil + return name, result, delay, response.Timestamp, nil } // // // -type rtResult string +var jsoniterAPI = jsoniter.ConfigFastest + +type apiResult string const ( - rtResultUnknown rtResult = "unknown" - rtResultError rtResult = "error" - rtResultNoData rtResult = "no data" - rtResultSuccess rtResult = "success" + apiResultUnknown apiResult = "unknown" + apiResultError apiResult = "error" + apiResultNoData apiResult = "no data" + apiResultSuccess apiResult = "success" ) -// -// -// - type nopMetadataProvider struct{} func (nopMetadataProvider) Metadata(string) (string, int, bool) { return "", 0, false } -// realtimeResponse models the response from rt.fastly.com. It can get quite -// large; when there are lots of services being monitored, unmarshaling to this -// type is the CPU bottleneck of the program. -type realtimeResponse struct { - Timestamp uint64 `json:"Timestamp"` - Data []struct { - Datacenter map[string]datacenter `json:"datacenter"` - Aggregated datacenter `json:"aggregated"` - Recorded uint64 `json:"recorded"` - } `json:"Data"` - Error string `json:"error"` -} - -func (resp *realtimeResponse) unmarshalStdlib(data []byte) error { - return json.Unmarshal(data, resp) -} - -var jsoniterAPI = jsoniter.ConfigFastest - -func (resp *realtimeResponse) unmarshalJsoniter(data []byte) error { - return jsoniterAPI.Unmarshal(data, resp) -} - -type datacenter struct { - Requests uint64 `json:"requests"` - TLS uint64 `json:"tls"` - Shield uint64 `json:"shield"` - IPv6 uint64 `json:"ipv6"` - ImgOpto uint64 `json:"imgopto"` - ImgOptoShield uint64 `json:"imgopto_shield"` - ImgOptoTransform uint64 `json:"imgopto_transforms"` - OTFP uint64 `json:"otfp"` - OTFPShield uint64 `json:"otfp_shield"` - OTFPTransform uint64 `json:"otfp_transforms"` - OTFPManifest uint64 `json:"otfp_manifests"` - Video uint64 `json:"video"` - PCI uint64 `json:"pci"` - Logging uint64 `json:"logging"` - HTTP2 uint64 `json:"http2"` - RespHeaderBytes uint64 `json:"resp_header_bytes"` - HeaderSize uint64 `json:"header_size"` - RespBodyBytes uint64 `json:"resp_body_bytes"` - BodySize uint64 `json:"body_size"` - ReqHeaderBytes uint64 `json:"req_header_bytes"` - BackendReqHeaderBytes uint64 `json:"bereq_header_bytes"` - BilledHeaderBytes uint64 `json:"billed_header_bytes"` - BilledBodyBytes uint64 `json:"billed_body_bytes"` - WAFBlocked uint64 `json:"waf_blocked"` - WAFLogged uint64 `json:"waf_logged"` - WAFPassed uint64 `json:"waf_passed"` - AttackReqHeaderBytes uint64 `json:"attack_req_header_bytes"` - AttackReqBodyBytes uint64 `json:"attack_req_body_bytes"` - AttackRespSynthBytes uint64 `json:"attack_resp_synth_bytes"` - AttackLoggedReqHeaderBytes uint64 `json:"attack_logged_req_header_bytes"` - AttackLoggedReqBodyBytes uint64 `json:"attack_logged_req_body_bytes"` - AttackBlockedReqHeaderBytes uint64 `json:"attack_blocked_req_header_bytes"` - AttackBlockedReqBodyBytes uint64 `json:"attack_blocked_req_body_bytes"` - AttackPassedReqHeaderBytes uint64 `json:"attack_passed_req_header_bytes"` - AttackPassedReqBodyBytes uint64 `json:"attack_passed_req_body_bytes"` - ShieldRespHeaderBytes uint64 `json:"shield_resp_header_bytes"` - ShieldRespBodyBytes uint64 `json:"shield_resp_body_bytes"` - OTFPRespHeaderBytes uint64 `json:"otfp_resp_header_bytes"` - OTFPRespBodyBytes uint64 `json:"otfp_resp_body_bytes"` - OTFPShieldRespHeaderBytes uint64 `json:"otfp_shield_resp_header_bytes"` - OTFPShieldRespBodyBytes uint64 `json:"otfp_shield_resp_body_bytes"` - OTFPTransformRespHeaderBytes uint64 `json:"otfp_transform_resp_header_bytes"` - OTFPTransformRespBodyBytes uint64 `json:"otfp_transform_resp_body_bytes"` - OTFPShieldTime uint64 `json:"otfp_shield_time"` - OTFPTransformTime uint64 `json:"otfp_transform_time"` - OTFPDeliverTime uint64 `json:"otfp_deliver_time"` - ImgOptoRespHeaderBytes uint64 `json:"imgopto_resp_header_bytes"` - ImgOptoRespBodyBytes uint64 `json:"imgopto_resp_body_bytes"` - ImgOptoShieldRespHeaderBytes uint64 `json:"imgopto_shield_resp_header_bytes"` - ImgOptoShieldRespBodyBytes uint64 `json:"imgopto_shield_resp_body_bytes"` - ImgOptoTransformRespHeaderBytes uint64 `json:"imgopto_transform_resp_header_bytes"` - ImgOptoTransformRespBodyBytes uint64 `json:"imgopto_transform_resp_body_bytes"` - Status1xx uint64 `json:"status_1xx"` - Status2xx uint64 `json:"status_2xx"` - Status3xx uint64 `json:"status_3xx"` - Status4xx uint64 `json:"status_4xx"` - Status5xx uint64 `json:"status_5xx"` - Status200 uint64 `json:"status_200"` - Status204 uint64 `json:"status_204"` - Status301 uint64 `json:"status_301"` - Status302 uint64 `json:"status_302"` - Status304 uint64 `json:"status_304"` - Status400 uint64 `json:"status_400"` - Status401 uint64 `json:"status_401"` - Status403 uint64 `json:"status_403"` - Status404 uint64 `json:"status_404"` - Status416 uint64 `json:"status_416"` - Status500 uint64 `json:"status_500"` - Status501 uint64 `json:"status_501"` - Status502 uint64 `json:"status_502"` - Status503 uint64 `json:"status_503"` - Status504 uint64 `json:"status_504"` - Status505 uint64 `json:"status_505"` - Hits uint64 `json:"hits"` - Misses uint64 `json:"miss"` - Passes uint64 `json:"pass"` - Synths uint64 `json:"synth"` - Errors uint64 `json:"errors"` - Uncacheable uint64 `json:"uncacheable"` - HitsTime float64 `json:"hits_time"` - MissTime float64 `json:"miss_time"` - PassTime float64 `json:"pass_time"` - MissHistogram map[string]uint64 `json:"miss_histogram"` - TLSv10 uint64 `json:"tls_v10"` - TLSv11 uint64 `json:"tls_v11"` - TLSv12 uint64 `json:"tls_v12"` - TLSv13 uint64 `json:"tls_v13"` - ObjectSize1k uint64 `json:"object_size_1k"` - ObjectSize10k uint64 `json:"object_size_10k"` - ObjectSize100k uint64 `json:"object_size_100k"` - ObjectSize1m uint64 `json:"object_size_1m"` - ObjectSize10m uint64 `json:"object_size_10m"` - ObjectSize100m uint64 `json:"object_size_100m"` - ObjectSize1g uint64 `json:"object_size_1g"` - RecvSubTime uint64 `json:"recv_sub_time"` - RecvSubCount uint64 `json:"recv_sub_count"` - HashSubTime uint64 `json:"hash_sub_time"` - HashSubCount uint64 `json:"hash_sub_count"` - MissSubTime uint64 `json:"miss_sub_time"` - MissSubCount uint64 `json:"miss_sub_count"` - FetchSubTime uint64 `json:"fetch_sub_time"` - FetchSubCount uint64 `json:"fetch_sub_count"` - DeliverSubTime uint64 `json:"deliver_sub_time"` - DeliverSubCount uint64 `json:"deliver_sub_count"` - HitSubTime uint64 `json:"hit_sub_time"` - HitSubCount uint64 `json:"hit_sub_count"` - PrehashSubTime uint64 `json:"prehash_sub_time"` - PrehashSubCount uint64 `json:"prehash_sub_count"` - PredeliverSubTime uint64 `json:"predeliver_sub_time"` - PredeliverSubCount uint64 `json:"predeliver_sub_count"` -} - func contextSleep(ctx context.Context, d time.Duration) { select { case <-time.After(d): diff --git a/pkg/rt/subscriber_test.go b/pkg/rt/subscriber_test.go index 1fb6593..294efd9 100644 --- a/pkg/rt/subscriber_test.go +++ b/pkg/rt/subscriber_test.go @@ -8,7 +8,7 @@ import ( "github.com/peterbourgon/fastly-exporter/pkg/api" "github.com/peterbourgon/fastly-exporter/pkg/filter" - "github.com/peterbourgon/fastly-exporter/pkg/prom" + "github.com/peterbourgon/fastly-exporter/pkg/gen" "github.com/peterbourgon/fastly-exporter/pkg/rt" "github.com/prometheus/client_golang/prometheus" ) @@ -19,7 +19,7 @@ func TestSubscriberFixture(t *testing.T) { subsystem = "testsystem" registry = prometheus.NewRegistry() nameFilter = filter.Filter{} - metrics, _ = prom.NewMetrics(namespace, subsystem, nameFilter, registry) + metrics, _ = gen.NewMetrics(namespace, subsystem, nameFilter, registry) ) var ( @@ -33,7 +33,7 @@ func TestSubscriberFixture(t *testing.T) { options = []rt.SubscriberOption{rt.WithMetadataProvider(cache), rt.WithPostprocess(postprocess)} subscriber = rt.NewSubscriber(client, "irrelevant token", serviceID, metrics, options...) ) - cache.update([]api.Service{api.Service{ID: serviceID, Name: serviceName, Version: serviceVersion}}) + cache.update([]api.Service{{ID: serviceID, Name: serviceName, Version: serviceVersion}}) var ( ctx, cancel = context.WithCancel(context.Background()) @@ -46,7 +46,8 @@ func TestSubscriberFixture(t *testing.T) { <-processed - assertStringSliceEqual(t, expectedMetricsOutputSlice, prometheusOutput(t, registry, namespace+"_"+subsystem+"_")) + output := prometheusOutput(t, registry, namespace+"_"+subsystem+"_") + assertStringSliceEqual(t, expectedMetricsOutputSlice, output) cancel() <-done @@ -56,7 +57,7 @@ func TestSubscriberNoData(t *testing.T) { var ( client = newMockRealtimeClient(`{"Error": "No data available, please retry"}`, `{}`) registry = prometheus.NewRegistry() - metrics, _ = prom.NewMetrics("ns", "ss", filter.Filter{}, registry) + metrics, _ = gen.NewMetrics("ns", "ss", filter.Filter{}, registry) processed = make(chan struct{}, 100) postprocess = func() { processed <- struct{}{} } options = []rt.SubscriberOption{rt.WithPostprocess(postprocess)} @@ -81,7 +82,7 @@ func TestUserAgent(t *testing.T) { var ( client = newMockRealtimeClient(`{}`) userAgent = "Some user agent string" - metrics, _ = prom.NewMetrics("ns", "ss", filter.Filter{}, prometheus.NewRegistry()) + metrics, _ = gen.NewMetrics("ns", "ss", filter.Filter{}, prometheus.NewRegistry()) processed = make(chan struct{}) postprocess = func() { close(processed) } options = []rt.SubscriberOption{rt.WithUserAgent(userAgent), rt.WithPostprocess(postprocess)} @@ -99,7 +100,7 @@ func TestUserAgent(t *testing.T) { func TestBadTokenNoSpam(t *testing.T) { var ( client = &countingRealtimeClient{code: 403, response: `{"Error": "unauthorized"}`} - metrics, _ = prom.NewMetrics("namespace", "subsystem", filter.Filter{}, prometheus.NewRegistry()) + metrics, _ = gen.NewMetrics("namespace", "subsystem", filter.Filter{}, prometheus.NewRegistry()) subscriber = rt.NewSubscriber(client, "presumably bad token", "service ID", metrics) ) go subscriber.Run(context.Background())