From 1ad55d5984659b49bc0e84ed93b53c30ec9106b9 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Thu, 26 Oct 2023 14:13:04 +0200 Subject: [PATCH] feat: secret files, web config and better docs --- changelog/1.1.0_2023-10-26/file-secrets.md | 8 ++ changelog/1.1.0_2023-10-26/pprof-profiler.md | 8 ++ changelog/1.1.0_2023-10-26/web-config.md | 7 ++ docs/content/kubernetes.md | 5 +- docs/content/usage.md | 16 ++++ docs/layouts/partials/style.html | 8 +- docs/partials/envvars.md | 9 +++ docs/partials/metrics.md | 82 ++++++++++---------- go.mod | 22 ++++-- go.sum | 72 +++++++++++++---- hack/generate-metrics-docs.go | 4 +- pkg/action/helper.go | 16 ++++ pkg/action/server.go | 41 +++++++++- pkg/command/command.go | 21 +++++ pkg/config/config.go | 35 +++++++++ pkg/middleware/profiler.go | 12 +++ 16 files changed, 298 insertions(+), 68 deletions(-) create mode 100644 changelog/1.1.0_2023-10-26/file-secrets.md create mode 100644 changelog/1.1.0_2023-10-26/pprof-profiler.md create mode 100644 changelog/1.1.0_2023-10-26/web-config.md create mode 100644 pkg/action/helper.go create mode 100644 pkg/middleware/profiler.go diff --git a/changelog/1.1.0_2023-10-26/file-secrets.md b/changelog/1.1.0_2023-10-26/file-secrets.md new file mode 100644 index 0000000..3a9e990 --- /dev/null +++ b/changelog/1.1.0_2023-10-26/file-secrets.md @@ -0,0 +1,8 @@ +Change: Read secrets form files + +We have added proper support to load secrets like the password from files or +from base64-encoded strings. Just provide the flags or environment variables +for token or private key with a DSN formatted string like `file://path/to/file` +or `base64://Zm9vYmFy`. + +https://github.com/promhippie/scw_exporter/pull/53 diff --git a/changelog/1.1.0_2023-10-26/pprof-profiler.md b/changelog/1.1.0_2023-10-26/pprof-profiler.md new file mode 100644 index 0000000..2f76f01 --- /dev/null +++ b/changelog/1.1.0_2023-10-26/pprof-profiler.md @@ -0,0 +1,8 @@ +Enhancement: Integrate option pprof profiling + +We have added an option to enable a pprof endpoint for proper profiling support +with the help of tools like Parca. The endpoint `/debug/pprof` can now +optionally be enabled to get the profiling details for catching potential memory +leaks. + +https://github.com/promhippie/scw_exporter/pull/53 diff --git a/changelog/1.1.0_2023-10-26/web-config.md b/changelog/1.1.0_2023-10-26/web-config.md new file mode 100644 index 0000000..512555d --- /dev/null +++ b/changelog/1.1.0_2023-10-26/web-config.md @@ -0,0 +1,7 @@ +Change: Integrate standard web config + +We integrated the new web config from the Prometheus toolkit which provides a +configuration for TLS support and also some basic builtin authentication. For +the detailed configuration you can check out the documentation. + +https://github.com/promhippie/scw_exporter/pull/53 diff --git a/docs/content/kubernetes.md b/docs/content/kubernetes.md index 39ae3ae..f9a51d0 100644 --- a/docs/content/kubernetes.md +++ b/docs/content/kubernetes.md @@ -64,7 +64,7 @@ helm install scw-exporter promhippie/scw-exporter {{< / highlight >}} You can also watch that available values and generally the details of the chart -provided by us within our [chart][chart] repository. +provided by us within our [chart][chart] repository or on [Artifacthub][ahub]. After applying this manifest the exporter should be directly visible within your Prometheus instance depending on your installation if you enabled the @@ -72,4 +72,5 @@ annotations or the service monitor. [kustomize]: https://github.com/kubernetes-sigs/kustomize [helm]: https://helm.sh -[chart]: https://github.com/promhippie/charts/tree/master/charts/scw-exporter +[chart]: https://github.com/promhippie/charts/tree/master/stable/scw-exporter +[ahub]: https://artifacthub.io/packages/helm/promhippie/scw-exporter diff --git a/docs/content/usage.md b/docs/content/usage.md index c16cf88..d7ee643 100644 --- a/docs/content/usage.md +++ b/docs/content/usage.md @@ -111,6 +111,22 @@ support for it, for details about the config format look at the - SCW_EXPORTER_LOG_PRETTY=true {{< / highlight >}} +If you want to provide the required secrets from a file it's also possible. For +this use case you can write the secret to a file on any path and reference it +with the following format: + +{{< highlight diff >}} + scw_exporter: + image: promhippie/scw-exporter:latest + restart: always + environment: +- - SCW_EXPORTER_ACESS_KEY=your-access-key +- - SCW_EXPORTER_SECRET_KEY=your-secret-key ++ - SCW_EXPORTER_ACESS_KEY=file://path/to/secret/file/with/access-key ++ - SCW_EXPORTER_SECRET_KEY=file://path/to/secret/file/with/secret-key + - SCW_EXPORTER_LOG_PRETTY=true +{{< / highlight >}} + Finally the exporter should be configured fine, let's start this stack with [docker-compose][compose], you just need to execute `docker-compose up` within the directory where you have stored the `prometheus.yml` and diff --git a/docs/layouts/partials/style.html b/docs/layouts/partials/style.html index cba6e12..6834422 100644 --- a/docs/layouts/partials/style.html +++ b/docs/layouts/partials/style.html @@ -68,7 +68,7 @@ line-height: 1.6; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; color: #242424; - max-width: 800px; + max-width: 900px; margin: 5% auto; } @@ -115,6 +115,7 @@ h3 { font-size: 18px; margin-bottom: 0.3em; + margin-top: 1.0em; } h1 small a { @@ -215,6 +216,11 @@ dl dt { font-weight: bold; + margin-top: 10px; + } + + dl dt:first-child { + margin-top: 0px; } dl dd { diff --git a/docs/partials/envvars.md b/docs/partials/envvars.md index b60c576..65573a4 100644 --- a/docs/partials/envvars.md +++ b/docs/partials/envvars.md @@ -10,6 +10,15 @@ SCW_EXPORTER_WEB_ADDRESS SCW_EXPORTER_WEB_PATH : Path to bind the metrics server, defaults to `/metrics` +SCW_EXPORTER_WEB_PPROF +: Enable pprof debugging for server, defaults to `false` + +SCW_EXPORTER_WEB_TIMEOUT +: Server metrics endpoint timeout, defaults to `10s` + +SCW_EXPORTER_WEB_CONFIG +: Path to web-config file + SCW_EXPORTER_REQUEST_TIMEOUT : Request timeout as duration, defaults to `5s` diff --git a/docs/partials/metrics.md b/docs/partials/metrics.md index 2e00a45..7e3c678 100644 --- a/docs/partials/metrics.md +++ b/docs/partials/metrics.md @@ -1,46 +1,46 @@ -scw_dashboard_images_count{} +scw_dashboard_images_count{zone} : Count of used images -scw_dashboard_ips_count{} +scw_dashboard_ips_count{zone} : Count of used IPs -scw_dashboard_placement_groups_count{} +scw_dashboard_placement_groups_count{zone} : Count of placement groups -scw_dashboard_private_nics_count{} +scw_dashboard_private_nics_count{zone} : Count of private nics -scw_dashboard_running_servers{} +scw_dashboard_running_servers{zone} : Count of running servers -scw_dashboard_security_groups_count{} +scw_dashboard_security_groups_count{zone} : Count of security groups -scw_dashboard_server_types_count{, } +scw_dashboard_server_types_count{zone, type} : Count of servers by type -scw_dashboard_servers_count{} +scw_dashboard_servers_count{zone} : Count of owned servers -scw_dashboard_snapshots_count{} +scw_dashboard_snapshots_count{zone} : Count of used snapshots -scw_dashboard_unused_ips_count{} +scw_dashboard_unused_ips_count{zone} : Count of unused IPs -scw_dashboard_volumes_bssd_count{} +scw_dashboard_volumes_bssd_count{zone} : Count of unused IPs -scw_dashboard_volumes_bssd_total_size{} +scw_dashboard_volumes_bssd_total_size{zone} : Count of unused IPs -scw_dashboard_volumes_count{} +scw_dashboard_volumes_count{zone} : Count of used volumes -scw_dashboard_volumes_lssd_count{} +scw_dashboard_volumes_lssd_count{zone} : Count of unused IPs -scw_dashboard_volumes_lssd_total_size{} +scw_dashboard_volumes_lssd_total_size{zone} : Count of unused IPs scw_request_duration_seconds{collector} @@ -49,80 +49,80 @@ scw_request_duration_seconds{collector} scw_request_failures_total{collector} : Total number of failed requests to the api per collector -scw_security_group_created_timestamp{, , , , } +scw_security_group_created_timestamp{id, name, zone, org, project} : Timestamp when the security group have been created -scw_security_group_defined{, , , , } +scw_security_group_defined{id, name, zone, org, project} : Constant value of 1 that this security group is defined -scw_security_group_enable_default{, , , , } +scw_security_group_enable_default{id, name, zone, org, project} : 1 if the security group is enabled by default, 0 otherwise -scw_security_group_inbound_default_policy{, , , , } +scw_security_group_inbound_default_policy{id, name, zone, org, project} : 1 if the security group inbound default policy is accept, 0 otherwise -scw_security_group_modified_timestamp{, , , , } +scw_security_group_modified_timestamp{id, name, zone, org, project} : Timestamp when the security group have been modified -scw_security_group_outbound_default_policy{, , , , } +scw_security_group_outbound_default_policy{id, name, zone, org, project} : 1 if the security group outbound default policy is accept, 0 otherwise -scw_security_group_project_default{, , , , } +scw_security_group_project_default{id, name, zone, org, project} : 1 if the security group is an project default, 0 otherwise -scw_security_group_servers_count{, , , , } +scw_security_group_servers_count{id, name, zone, org, project} : Number of servers attached to the security group -scw_security_group_stateful{, , , , } +scw_security_group_stateful{id, name, zone, org, project} : 1 if the security group is stateful by default, 0 otherwise -scw_server_created_timestamp{, , , , , , , , } +scw_server_created_timestamp{id, name, zone, org, project, type, private_ip, public_ip, arch} : Timestamp when the server have been created -scw_server_modified_timestamp{, , , , , , , , } +scw_server_modified_timestamp{id, name, zone, org, project, type, private_ip, public_ip, arch} : Timestamp when the server have been modified -scw_server_private_nic_count{, , , , , , , , } +scw_server_private_nic_count{id, name, zone, org, project, type, private_ip, public_ip, arch} : Number of private nics attached -scw_server_state{, , , , , , , , } +scw_server_state{id, name, zone, org, project, type, private_ip, public_ip, arch} : If 1 the server is running, depending on the state otherwise -scw_server_volume_count{, , , , , , , , } +scw_server_volume_count{id, name, zone, org, project, type, private_ip, public_ip, arch} : Number of volumes attached -scw_snapshot_available{, , , , } +scw_snapshot_available{id, name, zone, org, project} : Constant value of 1 that this snapshot is available -scw_snapshot_created_timestamp{, , , , } +scw_snapshot_created_timestamp{id, name, zone, org, project} : Timestamp when the snapshot have been created -scw_snapshot_modified_timestamp{, , , , } +scw_snapshot_modified_timestamp{id, name, zone, org, project} : Timestamp when the snapshot have been modified -scw_snapshot_size_bytes{, , , , } +scw_snapshot_size_bytes{id, name, zone, org, project} : Size of the snapshot in bytes -scw_snapshot_state{, , , , } +scw_snapshot_state{id, name, zone, org, project} : State of the snapshot -scw_snapshot_type{, , , , } +scw_snapshot_type{id, name, zone, org, project} : Type of the snapshot -scw_volume_available{, , , , } +scw_volume_available{id, name, zone, org, project} : Constant value of 1 that this volume is available -scw_volume_created_timestamp{, , , , } +scw_volume_created_timestamp{id, name, zone, org, project} : Timestamp when the volume have been created -scw_volume_modified_timestamp{, , , , } +scw_volume_modified_timestamp{id, name, zone, org, project} : Timestamp when the volume have been modified -scw_volume_size_bytes{, , , , } +scw_volume_size_bytes{id, name, zone, org, project} : Size of the volume in bytes -scw_volume_state{, , , , } +scw_volume_state{id, name, zone, org, project} : State of the snapshot -scw_volume_type{, , , , } +scw_volume_type{id, name, zone, org, project} : Type of the snapshot diff --git a/go.mod b/go.mod index c605249..4595a42 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/joho/godotenv v1.5.1 github.com/oklog/run v1.1.0 github.com/prometheus/client_golang v1.17.0 + github.com/prometheus/exporter-toolkit v0.10.0 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21 github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.25.7 @@ -16,19 +17,28 @@ require ( require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/jpillora/backoff v1.0.0 // indirect github.com/kr/text v0.2.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/sys v0.11.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index cec5849..eb969f3 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,10 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -14,31 +16,38 @@ github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/exporter-toolkit v0.10.0 h1:yOAzZTi4M22ZzVxD+fhy1URTuNRj/36uQJJ5S8IPza8= +github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZNVnKQa3x5qPmDSiPu4ZY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -50,10 +59,45 @@ github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= diff --git a/hack/generate-metrics-docs.go b/hack/generate-metrics-docs.go index c329f93..a2b2b06 100644 --- a/hack/generate-metrics-docs.go +++ b/hack/generate-metrics-docs.go @@ -70,7 +70,9 @@ func main() { Labels: make([]string, 0), } - labels := reflect.ValueOf(desc).Elem().FieldByName("variableLabels") + labels := reflect.Indirect( + reflect.ValueOf(desc).Elem().FieldByName("variableLabels"), + ).FieldByName("names") for i := 0; i < labels.Len(); i++ { m.Labels = append(m.Labels, labels.Index(i).String()) diff --git a/pkg/action/helper.go b/pkg/action/helper.go new file mode 100644 index 0000000..f6fa442 --- /dev/null +++ b/pkg/action/helper.go @@ -0,0 +1,16 @@ +package action + +// boolP returns a boolean pointer. +func boolP(i bool) *bool { + return &i +} + +// stringP returns a string pointer. +func stringP(i string) *string { + return &i +} + +// slceP returns a slice pointer. +func sliceP(i []string) *[]string { + return &i +} diff --git a/pkg/action/server.go b/pkg/action/server.go index 8bc4517..17194b6 100644 --- a/pkg/action/server.go +++ b/pkg/action/server.go @@ -14,6 +14,7 @@ import ( "github.com/go-kit/log/level" "github.com/oklog/run" "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/exporter-toolkit/web" "github.com/promhippie/scw_exporter/pkg/config" "github.com/promhippie/scw_exporter/pkg/exporter" "github.com/promhippie/scw_exporter/pkg/middleware" @@ -31,10 +32,32 @@ func Server(cfg *config.Config, logger log.Logger) error { "go", version.Go, ) + accessKey, err := config.Value(cfg.Target.AccessKey) + + if err != nil { + level.Error(logger).Log( + "msg", "Failed to load access key from file", + "err", err, + ) + + return err + } + + secretKey, err := config.Value(cfg.Target.SecretKey) + + if err != nil { + level.Error(logger).Log( + "msg", "Failed to load secret key from file", + "err", err, + ) + + return err + } + opts := []scw.ClientOption{ scw.WithAuth( - cfg.Target.AccessKey, - cfg.Target.SecretKey, + accessKey, + secretKey, ), scw.WithDefaultPageSize( 100, @@ -126,7 +149,15 @@ func Server(cfg *config.Config, logger log.Logger) error { "addr", cfg.Server.Addr, ) - return server.ListenAndServe() + return web.ListenAndServe( + server, + &web.FlagConfig{ + WebListenAddresses: sliceP([]string{cfg.Server.Addr}), + WebSystemdSocket: boolP(false), + WebConfigFile: stringP(cfg.Server.Web), + }, + logger, + ) }, func(reason error) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -171,6 +202,10 @@ func handler(cfg *config.Config, logger log.Logger, client *scw.Client) *chi.Mux mux.Use(middleware.Timeout) mux.Use(middleware.Cache) + if cfg.Server.Pprof { + mux.Mount("/debug", middleware.Profiler()) + } + if cfg.Collector.Dashboard { level.Debug(logger).Log( "msg", "Dashboard collector registered", diff --git a/pkg/command/command.go b/pkg/command/command.go index aeb07eb..90455d0 100644 --- a/pkg/command/command.go +++ b/pkg/command/command.go @@ -99,6 +99,27 @@ func RootFlags(cfg *config.Config) []cli.Flag { EnvVars: []string{"SCW_EXPORTER_WEB_PATH"}, Destination: &cfg.Server.Path, }, + &cli.BoolFlag{ + Name: "web.debug", + Value: false, + Usage: "Enable pprof debugging for server", + EnvVars: []string{"SCW_EXPORTER_WEB_PPROF"}, + Destination: &cfg.Server.Pprof, + }, + &cli.DurationFlag{ + Name: "web.timeout", + Value: 10 * time.Second, + Usage: "Server metrics endpoint timeout", + EnvVars: []string{"SCW_EXPORTER_WEB_TIMEOUT"}, + Destination: &cfg.Server.Timeout, + }, + &cli.StringFlag{ + Name: "web.config", + Value: "", + Usage: "Path to web-config file", + EnvVars: []string{"SCW_EXPORTER_WEB_CONFIG"}, + Destination: &cfg.Server.Web, + }, &cli.DurationFlag{ Name: "request.timeout", Value: 5 * time.Second, diff --git a/pkg/config/config.go b/pkg/config/config.go index f57e1c2..bd2566e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,6 +1,10 @@ package config import ( + "encoding/base64" + "fmt" + "os" + "strings" "time" ) @@ -9,6 +13,8 @@ type Server struct { Addr string Path string Timeout time.Duration + Web string + Pprof bool } // Logs defines the level and color for log configuration. @@ -50,3 +56,32 @@ type Config struct { func Load() *Config { return &Config{} } + +// Value returns the config value based on a DSN. +func Value(val string) (string, error) { + if strings.HasPrefix(val, "file://") { + content, err := os.ReadFile( + strings.TrimPrefix(val, "file://"), + ) + + if err != nil { + return "", fmt.Errorf("failed to parse secret file: %w", err) + } + + return string(content), nil + } + + if strings.HasPrefix(val, "base64://") { + content, err := base64.StdEncoding.DecodeString( + strings.TrimPrefix(val, "base64://"), + ) + + if err != nil { + return "", fmt.Errorf("failed to parse base64 value: %w", err) + } + + return string(content), nil + } + + return val, nil +} diff --git a/pkg/middleware/profiler.go b/pkg/middleware/profiler.go new file mode 100644 index 0000000..62b8cf6 --- /dev/null +++ b/pkg/middleware/profiler.go @@ -0,0 +1,12 @@ +package middleware + +import ( + "net/http" + + "github.com/go-chi/chi/v5/middleware" +) + +// Profiler just wraps the go-chi profiler middleware. +func Profiler() http.Handler { + return middleware.Profiler() +}