Skip to content

Commit

Permalink
feat: add support to collect metrics using the OTEL library (#927)
Browse files Browse the repository at this point in the history
* feat: Add support to collect metrics using either a prometheus compatible endpoint or by sending metrics to an OTEL http endpoint

Signed-off-by: Joe Wogan <joe.wogan@10xbanking.com>

* fix: use UpDounCounter rather than gauge for pending request count and
specify otel image for e2e tests

Signed-off-by: Joe Wogan <joe.wogan@10xbanking.com>

---------

Signed-off-by: Joe Wogan <joe.wogan@10xbanking.com>
  • Loading branch information
zorocloud authored Apr 24, 2024
1 parent c7ccd33 commit 0237611
Show file tree
Hide file tree
Showing 29 changed files with 1,228 additions and 73 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This changelog keeps track of work items that have been completed and are ready

### New

- **General**: Add support to collect metrics using either a prometheus compatible endpoint or by sending metrics to an OTEL http endpoint ([#910](https://github.com/kedacore/http-add-on/issues/910))
- **General**: Propagate HTTPScaledObject labels and annotations to ScaledObject ([#840](https://github.com/kedacore/http-add-on/issues/840))
- **General**: Provide support to allow HTTP scaler to work alongside other core KEDA scalers ([#489](https://github.com/kedacore/http-add-on/issues/489))
- **General**: Support aggregation windows ([#882](https://github.com/kedacore/http-add-on/issues/882))
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ deploy: manifests kustomize ## Deploy to the K8s cluster specified in ~/.kube/co
cd config/interceptor && \
$(KUSTOMIZE) edit set image ghcr.io/kedacore/http-add-on-interceptor=${IMAGE_INTERCEPTOR_VERSIONED_TAG}

cd config/interceptor && \
$(KUSTOMIZE) edit add patch --path otel/deployment.yaml --group apps --kind Deployment --name interceptor --version v1

cd config/interceptor && \
$(KUSTOMIZE) edit add patch --path otel/scaledobject.yaml --group keda.sh --kind ScaledObject --name interceptor --version v1alpha1

cd config/scaler && \
$(KUSTOMIZE) edit set image ghcr.io/kedacore/http-add-on-scaler=${IMAGE_SCALER_VERSIONED_TAG}

Expand Down
2 changes: 2 additions & 0 deletions config/interceptor/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ spec:
containerPort: 9090
- name: proxy
containerPort: 8080
- name: metrics
containerPort: 2223
livenessProbe:
httpGet:
path: /livez
Expand Down
1 change: 1 addition & 0 deletions config/interceptor/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ resources:
- role_binding.yaml
- admin.service.yaml
- proxy.service.yaml
- metrics.service.yaml
- service_account.yaml
- scaledobject.yaml
configurations:
Expand Down
11 changes: 11 additions & 0 deletions config/interceptor/metrics.service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: interceptor-metrics
spec:
type: ClusterIP
ports:
- name: metrics
protocol: TCP
port: 2223
targetPort: metrics
23 changes: 23 additions & 0 deletions config/interceptor/otel/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: interceptor
spec:
replicas: 1
template:
spec:
containers:
- name: interceptor
env:
- name: KEDA_HTTP_OTEL_PROM_EXPORTER_ENABLED
value: "true"
- name: KEDA_HTTP_OTEL_PROM_EXPORTER_PORT
value: "2223"
- name: KEDA_HTTP_OTEL_HTTP_EXPORTER_ENABLED
value: "true"
- name: KEDA_HTTP_OTEL_HTTP_COLLECTOR_ENDPOINT
value: "opentelemetry-collector.open-telemetry-system:4318"
- name: KEDA_HTTP_OTEL_HTTP_COLLECTOR_INSECURE
value: "true"
- name: KEDA_HTTP_OTEL_METRIC_EXPORT_INTERVAL
value: "1"
5 changes: 5 additions & 0 deletions config/interceptor/otel/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- scaledobject.yaml
6 changes: 6 additions & 0 deletions config/interceptor/otel/scaledobject.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: interceptor
spec:
minReplicaCount: 1
21 changes: 21 additions & 0 deletions docs/operate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Configuring metrics for the KEDA HTTP Add-on interceptor proxy

### Exportable metrics:
* **Pending request count** - the number of pending requests for a given host.
* **Total request count** - the total number of requests for a given host with method, path and response code attributes.

There are currently 2 supported methods for exposing metrics from the interceptor proxy service - via a Prometheus compatible metrics endpoint or by pushing metrics to a OTEL HTTP collector.

### Configuring the Prometheus compatible metrics endpoint
When configured, the interceptor proxy can expose metrics on a Prometheus compatible endpoint.

This endpoint can be enabled by setting the `KEDA_HTTP_OTEL_PROM_EXPORTER_ENABLED` environment variable to `true` on the interceptor deployment (`true` by default) and by setting `KEDA_HTTP_OTEL_PROM_EXPORTER_PORT` to an unused port for the endpoint to be made avaialble on (`2223` by default).

### Configuring the OTEL HTTP exporter
When configured, the interceptor proxy can export metrics to a OTEL HTTP collector.

The OTEL exporter can be enabled by setting the `KEDA_HTTP_OTEL_HTTP_EXPORTER_ENABLED` environment variable to `true` on the interceptor deployment (`false` by default). When enabled the `KEDA_HTTP_OTEL_HTTP_COLLECTOR_ENDPOINT` environment variable must also be configured so the exporter knows what collector to send the metrics to (e.g. opentelemetry-collector.open-telemetry-system:4318).

If the collector is exposed on a unsecured endpoint then you can set the `KEDA_HTTP_OTEL_HTTP_COLLECTOR_INSECURE` environment variable to `true` (`false` by default) which will disable client security on the exporter.

If you need to provide any headers such as authentication details in order to utilise your OTEL collector you can add them into the `KEDA_HTTP_OTEL_HTTP_HEADERS` environment variable. The frequency at which the metrics are exported can be configured by setting `KEDA_HTTP_OTEL_METRIC_EXPORT_INTERVAL` to the number of seconds you require between each export interval (`30` by default).
1 change: 1 addition & 0 deletions docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Here is an overview of detailed documentation:
- [Design](design.md)
- [Use-Cases](use_cases.md)
- [Walkthrough](walkthrough.md)
- [Operate](operate.md)
- [Developing](developing.md)
- [Integrations](integrations.md)
- [FAQ](faq.md)
23 changes: 19 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ require (
github.com/onsi/ginkgo/v2 v2.17.1
github.com/onsi/gomega v1.31.0
github.com/stretchr/testify v1.8.4
go.opentelemetry.io/otel v1.23.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.0
go.opentelemetry.io/otel/sdk v1.23.0
golang.org/x/sync v0.6.0
google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.33.0
Expand All @@ -24,6 +27,16 @@ require (
sigs.k8s.io/kustomize/kustomize/v5 v5.3.0
)

require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
go.opentelemetry.io/otel/trace v1.23.0 // indirect
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
go.uber.org/zap v1.26.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
Expand Down Expand Up @@ -62,16 +75,18 @@ require (
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.18.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/client_golang v1.18.0
github.com/prometheus/client_model v0.5.0
github.com/prometheus/common v0.46.0
github.com/prometheus/procfs v0.12.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.opentelemetry.io/otel/exporters/prometheus v0.45.1
go.opentelemetry.io/otel/metric v1.23.0
go.opentelemetry.io/otel/sdk/metric v1.23.0
go.starlark.net v0.0.0-20231121155337-90ade8b19d09 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.23.0 // indirect
Expand Down
27 changes: 27 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
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/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
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.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
Expand All @@ -21,9 +23,12 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
Expand Down Expand Up @@ -64,6 +69,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo=
github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
Expand Down Expand Up @@ -145,6 +152,22 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/otel v1.23.0 h1:Df0pqjqExIywbMCMTxkAwzjLZtRf+bBKLbUcpxO2C9E=
go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.0 h1:Lc6m+ytInMOSdTOGl+Y4qPzTlZ7QPb0pL+1JuUEt4Ao=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.0/go.mod h1:Rv15/kBGgH1lHvfd6Y0FlnMuy8F7MdSSiqVjn8Q8KUQ=
go.opentelemetry.io/otel/exporters/prometheus v0.45.1 h1:R/bW3afad6q6VGU+MFYpnEdo0stEARMCdhWu6+JI6aI=
go.opentelemetry.io/otel/exporters/prometheus v0.45.1/go.mod h1:wnHAfKRav5Dfp4iZhyWZ7SzQfT+rDZpEpYG7To+qJ1k=
go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo=
go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo=
go.opentelemetry.io/otel/sdk v1.23.0 h1:0KM9Zl2esnl+WSukEmlaAEjVY5HDZANOHferLq36BPc=
go.opentelemetry.io/otel/sdk v1.23.0/go.mod h1:wUscup7byToqyKJSilEtMf34FgdCAsFpFOjXnAwFfO0=
go.opentelemetry.io/otel/sdk/metric v1.23.0 h1:u81lMvmK6GMgN4Fty7K7S6cSKOZhMKJMK2TB+KaTs0I=
go.opentelemetry.io/otel/sdk/metric v1.23.0/go.mod h1:2LUOToN/FdX6wtfpHybOnCZjoZ6ViYajJYMiJ1LKDtQ=
go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI=
go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk=
go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
go.starlark.net v0.0.0-20231121155337-90ade8b19d09 h1:hzy3LFnSN8kuQK8h9tHl4ndF6UruMj47OqwqsS+/Ai4=
go.starlark.net v0.0.0-20231121155337-90ade8b19d09/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
Expand Down Expand Up @@ -224,6 +247,10 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
Expand Down
31 changes: 31 additions & 0 deletions interceptor/config/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package config

import (
"github.com/kelseyhightower/envconfig"
)

// Metrics is the configuration for configuring metrics in the interceptor.
type Metrics struct {
// Sets whether or not to enable the Prometheus metrics exporter
OtelPrometheusExporterEnabled bool `envconfig:"KEDA_HTTP_OTEL_PROM_EXPORTER_ENABLED" default:"true"`
// Sets the port which the Prometheus compatible metrics endpoint should be served on
OtelPrometheusExporterPort int `envconfig:"KEDA_HTTP_OTEL_PROM_EXPORTER_PORT" default:"2223"`
// Sets whether or not to enable the OTEL metrics exporter
OtelHTTPExporterEnabled bool `envconfig:"KEDA_HTTP_OTEL_HTTP_EXPORTER_ENABLED" default:"false"`
// Sets the HTTP endpoint where metrics should be sent to
OtelHTTPCollectorEndpoint string `envconfig:"KEDA_HTTP_OTEL_HTTP_COLLECTOR_ENDPOINT" default:"localhost:4318"`
// Sets the OTLP headers required by the otel exporter
OtelHTTPHeaders string `envconfig:"KEDA_HTTP_OTEL_HTTP_HEADERS" default:""`
// Set the connection to the otel HTTP collector endpoint to use HTTP rather than HTTPS
OtelHTTPCollectorInsecure bool `envconfig:"KEDA_HTTP_OTEL_HTTP_COLLECTOR_INSECURE" default:"false"`
// Set the interval in seconds to export otel metrics to the configured collector endpoint
OtelMetricExportInterval int `envconfig:"KEDA_HTTP_OTEL_METRIC_EXPORT_INTERVAL" default:"30"`
}

// Parse parses standard configs using envconfig and returns a pointer to the
// newly created config. Returns nil and a non-nil error if parsing failed
func MustParseMetrics() *Metrics {
ret := new(Metrics)
envconfig.MustProcess("", ret)
return ret
}
35 changes: 35 additions & 0 deletions interceptor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import (
"time"

"github.com/go-logr/logr"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/sync/errgroup"
"k8s.io/client-go/kubernetes"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"

"github.com/kedacore/http-add-on/interceptor/config"
"github.com/kedacore/http-add-on/interceptor/handler"
"github.com/kedacore/http-add-on/interceptor/metrics"
"github.com/kedacore/http-add-on/interceptor/middleware"
clientset "github.com/kedacore/http-add-on/operator/generated/clientset/versioned"
informers "github.com/kedacore/http-add-on/operator/generated/informers/externalversions"
Expand All @@ -39,6 +41,7 @@ var (
func main() {
timeoutCfg := config.MustParseTimeouts()
servingCfg := config.MustParseServing()
metricsCfg := config.MustParseMetrics()

opts := zap.Options{
Development: true,
Expand All @@ -59,11 +62,16 @@ func main() {
timeoutCfg,
"servingConfig",
servingCfg,
"metricsConfig",
metricsCfg,
)

proxyPort := servingCfg.ProxyPort
adminPort := servingCfg.AdminPort

// setup the configured metrics collectors
metrics.NewMetricsCollectors(metricsCfg)

cfg := ctrl.GetConfigOrDie()

cl, err := kubernetes.NewForConfig(cfg)
Expand Down Expand Up @@ -139,6 +147,19 @@ func main() {
return nil
})

if metricsCfg.OtelPrometheusExporterEnabled {
// start the prometheus compatible metrics server
// serves a prometheus compatible metrics endpoint on the configured port
eg.Go(func() error {
if err := runMetricsServer(ctx, ctrl.Log, metricsCfg); !util.IsIgnoredErr(err) {
setupLog.Error(err, "could not start the Prometheus metrics server")
return err
}

return nil
})
}

// start the proxy server. this is the server that
// accepts, holds and forwards user requests
eg.Go(func() error {
Expand Down Expand Up @@ -181,6 +202,16 @@ func runAdminServer(
return kedahttp.ServeContext(ctx, addr, adminServer)
}

func runMetricsServer(
ctx context.Context,
lggr logr.Logger,
metricsCfg *config.Metrics,
) error {
lggr.Info("starting the prometheus metrics server", "port", metricsCfg.OtelPrometheusExporterPort, "path", "/metrics")
addr := fmt.Sprintf("0.0.0.0:%d", metricsCfg.OtelPrometheusExporterPort)
return kedahttp.ServeContext(ctx, addr, promhttp.Handler())
}

func runProxyServer(
ctx context.Context,
logger logr.Logger,
Expand Down Expand Up @@ -221,6 +252,10 @@ func runProxyServer(
rootHandler,
)

rootHandler = middleware.NewMetrics(
rootHandler,
)

addr := fmt.Sprintf("0.0.0.0:%d", port)
logger.Info("proxy server starting", "address", addr)
return kedahttp.ServeContext(ctx, addr, rootHandler)
Expand Down
40 changes: 40 additions & 0 deletions interceptor/metrics/metricscollector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package metrics

import (
"github.com/kedacore/http-add-on/interceptor/config"
)

var (
collectors []Collector
)

const meterName = "keda-interceptor-proxy"

type Collector interface {
RecordRequestCount(method string, path string, responseCode int, host string)
RecordPendingRequestCount(host string, value int64)
}

func NewMetricsCollectors(metricsConfig *config.Metrics) {
if metricsConfig.OtelPrometheusExporterEnabled {
promometrics := NewPrometheusMetrics()
collectors = append(collectors, promometrics)
}

if metricsConfig.OtelHTTPExporterEnabled {
otelhttpmetrics := NewOtelMetrics(metricsConfig)
collectors = append(collectors, otelhttpmetrics)
}
}

func RecordRequestCount(method string, path string, responseCode int, host string) {
for _, collector := range collectors {
collector.RecordRequestCount(method, path, responseCode, host)
}
}

func RecordPendingRequestCount(host string, value int64) {
for _, collector := range collectors {
collector.RecordPendingRequestCount(host, value)
}
}
Loading

0 comments on commit 0237611

Please sign in to comment.