Move Prom metrics to a dedicated port + improve Helm chart (#599)

This commit is contained in:
Thomas Miceli
2026-01-26 17:28:51 +08:00
committed by GitHub
parent 24d0918e73
commit 145bf9d81a
18 changed files with 331 additions and 116 deletions

View File

@@ -31,7 +31,7 @@ RUN apk add --no-cache \
gnupg \ gnupg \
xz xz
EXPOSE 6157 2222 16157 EXPOSE 6157 6158 2222 16157
RUN git config --global --add safe.directory /opengist RUN git config --global --add safe.directory /opengist
RUN make install RUN make install
@@ -64,7 +64,7 @@ COPY --from=build --chown=opengist:opengist /opengist/config.yml /config.yml
COPY --from=build --chown=opengist:opengist /opengist/opengist . COPY --from=build --chown=opengist:opengist /opengist/opengist .
COPY --from=build --chown=opengist:opengist /opengist/docker ./docker COPY --from=build --chown=opengist:opengist /opengist/docker ./docker
EXPOSE 6157 2222 EXPOSE 6157 6158 2222
VOLUME /opengist VOLUME /opengist
HEALTHCHECK --interval=60s --timeout=30s --start-period=15s --retries=3 CMD curl -f http://localhost:6157/healthcheck || exit 1 HEALTHCHECK --interval=60s --timeout=30s --start-period=15s --retries=3 CMD curl -f http://localhost:6157/healthcheck || exit 1
ENTRYPOINT ["./docker/entrypoint.sh"] ENTRYPOINT ["./docker/entrypoint.sh"]

View File

@@ -55,9 +55,15 @@ http.git-enabled: true
# File permissions for Unix socket (octal format). Default: 0666 # File permissions for Unix socket (octal format). Default: 0666
unix-socket-permissions: 0666 unix-socket-permissions: 0666
# Enable or disable the metrics endpoint (either `true` or `false`). Default: false # Enable or disable the Prometheus metrics server (either `true` or `false`). Default: false
metrics.enabled: false metrics.enabled: false
# The host on which the metrics server should bind. Default: 0.0.0.0
metrics.host: 0.0.0.0
# The port on which the metrics server should listen. Default: 6158
metrics.port: 6158
# SSH built-in server configuration # SSH built-in server configuration
# Note: it is not using the SSH daemon from your machine (yet) # Note: it is not using the SSH daemon from your machine (yet)

View File

@@ -21,7 +21,9 @@ aside: false
| http.port | OG_HTTP_PORT | `6157` | The port on which the HTTP server should listen. | | http.port | OG_HTTP_PORT | `6157` | The port on which the HTTP server should listen. |
| http.git-enabled | OG_HTTP_GIT_ENABLED | `true` | Enable or disable git operations (clone, pull, push) via HTTP. (`true` or `false`) | | http.git-enabled | OG_HTTP_GIT_ENABLED | `true` | Enable or disable git operations (clone, pull, push) via HTTP. (`true` or `false`) |
| unix-socket-permissions | OG_UNIX_SOCKET_PERMISSIONS | `0666` | File permissions for Unix socket (octal format). | | unix-socket-permissions | OG_UNIX_SOCKET_PERMISSIONS | `0666` | File permissions for Unix socket (octal format). |
| metrics.enabled | OG_METRICS_ENABLED | `false` | Enable or disable Prometheus metrics endpoint at `/metrics` (`true` or `false`) | | metrics.enabled | OG_METRICS_ENABLED | `false` | Enable or disable Prometheus metrics server (`true` or `false`) |
| metrics.host | OG_METRICS_HOST | `0.0.0.0` | The host on which the metrics server should bind. |
| metrics.port | OG_METRICS_PORT | `6158` | The port on which the metrics server should listen. |
| ssh.git-enabled | OG_SSH_GIT_ENABLED | `true` | Enable or disable git operations (clone, pull, push) via SSH. (`true` or `false`) | | ssh.git-enabled | OG_SSH_GIT_ENABLED | `true` | Enable or disable git operations (clone, pull, push) via SSH. (`true` or `false`) |
| ssh.host | OG_SSH_HOST | `0.0.0.0` | The host on which the SSH server should bind. | | ssh.host | OG_SSH_HOST | `0.0.0.0` | The host on which the SSH server should bind. |
| ssh.port | OG_SSH_PORT | `2222` | The port on which the SSH server should listen. | | ssh.port | OG_SSH_PORT | `2222` | The port on which the SSH server should listen. |

View File

@@ -4,10 +4,10 @@ Opengist offers built-in support for Prometheus metrics to help you monitor the
## Enabling metrics ## Enabling metrics
By default, the metrics endpoint is disabled for security and performance reasons. To enable it, update your configuration as stated in the [configuration cheat sheet](cheat-sheet.md): By default, the metrics server is disabled for security and performance reasons. To enable it, update your configuration as stated in the [configuration cheat sheet](cheat-sheet.md):
```yaml ```yaml
metrics.enabled = true metrics.enabled: true
``` ```
Alternatively, you can use the environment variable: Alternatively, you can use the environment variable:
@@ -16,7 +16,25 @@ Alternatively, you can use the environment variable:
OG_METRICS_ENABLED=true OG_METRICS_ENABLED=true
``` ```
Once enabled, metrics are available at the /metrics endpoint. Once enabled, metrics are available on a separate server at `http://0.0.0.0:6158/metrics` by default.
## Configuration
The metrics server runs on a separate port from the main application. By default, it binds to `0.0.0.0` (all interfaces) on port `6158`.
| Config Key | Environment Variable | Default | Description |
|----------------|---------------------|-------------|------------------------------------------------|
| metrics.enabled | OG_METRICS_ENABLED | `false` | Enable or disable the metrics server |
| metrics.host | OG_METRICS_HOST | `0.0.0.0` | The host on which the metrics server binds |
| metrics.port | OG_METRICS_PORT | `6158` | The port on which the metrics server listens |
Example configuration:
```yaml
metrics.enabled: true
metrics.host: 0.0.0.0
metrics.port: 6158
```
## Available metrics ## Available metrics
@@ -36,14 +54,6 @@ These standard metrics follow the Prometheus naming convention and include label
## Security Considerations ## Security Considerations
The metrics endpoint exposes information about your Opengist instance that might be sensitive in some environments. Consider using a reverse proxy with authentication for the `/metrics` endpoint if your Opengist instance is publicly accessible. The metrics server binds to `0.0.0.0` by default, making it accessible on all network interfaces. This default works well for containerized deployments (Docker, Kubernetes) where network isolation is handled at the infrastructure level.
Example with Nginx: For bare-metal or VM deployments where the metrics port may be exposed, consider restricting to localhost by setting `metrics.host: 127.0.0.1` to only allow local access.
```shell
location /metrics {
auth_basic "Metrics";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:6157/metrics;
}
```

View File

@@ -6,6 +6,7 @@ Opengist Helm chart for Kubernetes.
* [Install](#install) * [Install](#install)
* [Configuration](#configuration) * [Configuration](#configuration)
* [Metrics & Monitoring](#metrics--monitoring)
* [Dependencies](#dependencies) * [Dependencies](#dependencies)
* [Meilisearch Indexer](#meilisearch-indexer) * [Meilisearch Indexer](#meilisearch-indexer)
* [PostgreSQL Database](#postgresql-database) * [PostgreSQL Database](#postgresql-database)
@@ -47,6 +48,76 @@ If defined, this existing secret will be used instead of creating a new one.
configExistingSecret: <name of the secret> configExistingSecret: <name of the secret>
``` ```
## Metrics & Monitoring
Opengist exposes Prometheus metrics on a separate port (default: `6158`). The metrics server runs independently from the main HTTP server for security.
### Enabling Metrics
To enable metrics, set `metrics.enabled: true` in your Opengist config:
```yaml
config:
metrics.enabled: true
```
This will:
1. Start a metrics server on port 6158 inside the container
2. Create a Kubernetes Service exposing the metrics ports
### Available Metrics
| Metric Name | Type | Description |
|-------------|------|-------------|
| `opengist_users_total` | Gauge | Total number of registered users |
| `opengist_gists_total` | Gauge | Total number of gists |
| `opengist_ssh_keys_total` | Gauge | Total number of SSH keys |
| `opengist_request_duration_seconds_*` | Histogram | HTTP request duration metrics |
### ServiceMonitor for Prometheus Operator
If you're using [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator), you can enable automatic service discovery with a ServiceMonitor:
```yaml
config:
metrics.enabled: true
service:
metrics:
serviceMonitor:
enabled: true
labels:
release: prometheus # match your Prometheus serviceMonitorSelector
```
### Manual Prometheus Configuration
If you're not using Prometheus Operator, you can configure Prometheus to scrape the metrics endpoint directly:
```yaml
scrape_configs:
- job_name: 'opengist'
static_configs:
- targets: ['opengist-metrics:6158']
metrics_path: /metrics
```
Or use Kubernetes service discovery:
```yaml
scrape_configs:
- job_name: 'opengist'
kubernetes_sd_configs:
- role: service
relabel_configs:
- source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_component]
regex: metrics
action: keep
- source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_name]
regex: opengist
action: keep
```
## Dependencies ## Dependencies
### Meilisearch Indexer ### Meilisearch Indexer

View File

@@ -67,6 +67,11 @@ spec:
- name: http - name: http
containerPort: {{ .Values.service.http.port }} containerPort: {{ .Values.service.http.port }}
protocol: TCP protocol: TCP
{{- if index .Values.config "metrics.enabled" }}
- name: metrics
containerPort: {{ .Values.service.metrics.port }}
protocol: TCP
{{- end }}
{{- if .Values.livenessProbe.enabled }} {{- if .Values.livenessProbe.enabled }}
livenessProbe: livenessProbe:
{{- toYaml (omit .Values.livenessProbe "enabled") | nindent 12 }} {{- toYaml (omit .Values.livenessProbe "enabled") | nindent 12 }}

View File

@@ -0,0 +1,41 @@
{{- if and (index .Values.config "metrics.enabled") .Values.service.metrics.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "opengist.fullname" . }}
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
{{- include "opengist.labels" . | nindent 4 }}
{{- with .Values.service.metrics.serviceMonitor.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.service.metrics.serviceMonitor.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
endpoints:
- port: metrics
{{- with .Values.service.metrics.serviceMonitor.interval }}
interval: {{ . }}
{{- end }}
{{- with .Values.service.metrics.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ . }}
{{- end }}
path: /metrics
{{- with .Values.service.metrics.serviceMonitor.relabelings }}
relabelings:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.service.metrics.serviceMonitor.metricRelabelings }}
metricRelabelings:
{{- toYaml . | nindent 8 }}
{{- end }}
namespaceSelector:
matchNames:
- {{ .Values.namespace | default .Release.Namespace }}
selector:
matchLabels:
{{- include "opengist.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: metrics
{{- end }}

View File

@@ -140,6 +140,11 @@ spec:
containerPort: {{ .Values.service.ssh.port }} containerPort: {{ .Values.service.ssh.port }}
protocol: TCP protocol: TCP
{{- end }} {{- end }}
{{- if index .Values.config "metrics.enabled" }}
- name: metrics
containerPort: {{ .Values.service.metrics.port }}
protocol: TCP
{{- end }}
{{- if .Values.livenessProbe.enabled }} {{- if .Values.livenessProbe.enabled }}
livenessProbe: livenessProbe:
{{- toYaml (omit .Values.livenessProbe "enabled") | nindent 12 }} {{- toYaml (omit .Values.livenessProbe "enabled") | nindent 12 }}

View File

@@ -0,0 +1,32 @@
{{- if index .Values.config "metrics.enabled" }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "opengist.fullname" . }}-metrics
namespace: {{ .Values.namespace | default .Release.Namespace }}
labels:
{{- include "opengist.labels" . | nindent 4 }}
app.kubernetes.io/component: metrics
{{- with .Values.service.metrics.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.service.metrics.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.metrics.type }}
{{- if .Values.service.metrics.clusterIP }}
clusterIP: {{ .Values.service.metrics.clusterIP }}
{{- end }}
ports:
- port: {{ .Values.service.metrics.port }}
targetPort: metrics
protocol: TCP
name: metrics
{{- if and (eq .Values.service.metrics.type "NodePort") .Values.service.metrics.nodePort }}
nodePort: {{ .Values.service.metrics.nodePort }}
{{- end }}
selector:
{{- include "opengist.selectorLabels" . | nindent 4 }}
{{- end }}

View File

@@ -8,6 +8,7 @@ namespace: ""
config: config:
log-level: "warn" log-level: "warn"
log-output: "stdout" log-output: "stdout"
metrics.enabled: false
## If defined, the existing secret will be used instead of creating a new one. ## If defined, the existing secret will be used instead of creating a new one.
## The secret must contain a key named `config.yml` with the YAML configuration. ## The secret must contain a key named `config.yml` with the YAML configuration.
@@ -101,6 +102,26 @@ service:
loadBalancerSourceRanges: [] loadBalancerSourceRanges: []
externalTrafficPolicy: externalTrafficPolicy:
# A metrics K8S service on port 6158 is created when the Opengist config metrics.enabled: true
metrics:
type: ClusterIP
clusterIP:
port: 6158
nodePort:
labels: {}
annotations: {}
# A service monitor can be used to work with your Prometheus setup.
serviceMonitor:
enabled: true
labels: {}
# release: kube-prom-stack
interval:
scrapeTimeout:
annotations: {}
relabelings: []
metricRelabelings: []
## HTTP Ingress for Opengist ## HTTP Ingress for Opengist
## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/ ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/
ingress: ingress:

View File

@@ -9,6 +9,7 @@ import (
"github.com/thomiceli/opengist/internal/git" "github.com/thomiceli/opengist/internal/git"
"github.com/thomiceli/opengist/internal/index" "github.com/thomiceli/opengist/internal/index"
"github.com/thomiceli/opengist/internal/ssh" "github.com/thomiceli/opengist/internal/ssh"
"github.com/thomiceli/opengist/internal/web/handlers/metrics"
"github.com/thomiceli/opengist/internal/web/server" "github.com/thomiceli/opengist/internal/web/server"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"os" "os"
@@ -36,12 +37,18 @@ var CmdStart = cli.Command{
Initialize(ctx) Initialize(ctx)
server := server.NewServer(os.Getenv("OG_DEV") == "1", path.Join(config.GetHomeDir(), "sessions"), false) httpServer := server.NewServer(os.Getenv("OG_DEV") == "1", path.Join(config.GetHomeDir(), "sessions"), false)
go server.Start() go httpServer.Start()
go ssh.Start() go ssh.Start()
var metricsServer *metrics.Server
if config.C.MetricsEnabled {
metricsServer = metrics.NewServer()
go metricsServer.Start()
}
<-stopCtx.Done() <-stopCtx.Done()
shutdown(server) shutdown(httpServer, metricsServer)
return nil return nil
}, },
} }
@@ -131,7 +138,7 @@ func Initialize(ctx *cli.Context) {
} }
} }
func shutdown(server *server.Server) { func shutdown(httpServer *server.Server, metricsServer *metrics.Server) {
log.Info().Msg("Shutting down database...") log.Info().Msg("Shutting down database...")
if err := db.Close(); err != nil { if err := db.Close(); err != nil {
log.Error().Err(err).Msg("Failed to close database") log.Error().Err(err).Msg("Failed to close database")
@@ -142,7 +149,11 @@ func shutdown(server *server.Server) {
index.Close() index.Close()
} }
server.Stop() httpServer.Stop()
if metricsServer != nil {
metricsServer.Stop()
}
log.Info().Msg("Shutdown complete") log.Info().Msg("Shutdown complete")
} }

View File

@@ -79,7 +79,9 @@ type config struct {
OIDCGroupClaimName string `yaml:"oidc.group-claim-name" env:"OG_OIDC_GROUP_CLAIM_NAME"` OIDCGroupClaimName string `yaml:"oidc.group-claim-name" env:"OG_OIDC_GROUP_CLAIM_NAME"`
OIDCAdminGroup string `yaml:"oidc.admin-group" env:"OG_OIDC_ADMIN_GROUP"` OIDCAdminGroup string `yaml:"oidc.admin-group" env:"OG_OIDC_ADMIN_GROUP"`
MetricsEnabled bool `yaml:"metrics.enabled" env:"OG_METRICS_ENABLED"` MetricsEnabled bool `yaml:"metrics.enabled" env:"OG_METRICS_ENABLED"`
MetricsHost string `yaml:"metrics.host" env:"OG_METRICS_HOST"`
MetricsPort string `yaml:"metrics.port" env:"OG_METRICS_PORT"`
LDAPUrl string `yaml:"ldap.url" env:"OG_LDAP_URL"` LDAPUrl string `yaml:"ldap.url" env:"OG_LDAP_URL"`
LDAPBindDn string `yaml:"ldap.bind-dn" env:"OG_LDAP_BIND_DN"` LDAPBindDn string `yaml:"ldap.bind-dn" env:"OG_LDAP_BIND_DN"`
@@ -128,6 +130,8 @@ func configWithDefaults() (*config, error) {
c.GiteaName = "Gitea" c.GiteaName = "Gitea"
c.MetricsEnabled = false c.MetricsEnabled = false
c.MetricsHost = "0.0.0.0"
c.MetricsPort = "6158"
return c, nil return c, nil
} }

View File

@@ -1,16 +1,12 @@
package metrics package metrics
import ( import (
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promauto"
"github.com/thomiceli/opengist/internal/config"
"github.com/thomiceli/opengist/internal/db" "github.com/thomiceli/opengist/internal/db"
"github.com/thomiceli/opengist/internal/web/context"
) )
var ( var (
// Using promauto to automatically register metrics with the default registry
countUsersGauge prometheus.Gauge countUsersGauge prometheus.Gauge
countGistsGauge prometheus.Gauge countGistsGauge prometheus.Gauge
countSSHKeysGauge prometheus.Gauge countSSHKeysGauge prometheus.Gauge
@@ -18,84 +14,52 @@ var (
metricsInitialized bool = false metricsInitialized bool = false
) )
// initMetrics initializes metrics if they're not already initialized
func initMetrics() { func initMetrics() {
if metricsInitialized { if metricsInitialized {
return return
} }
// Only initialize metrics if they're enabled countUsersGauge = promauto.NewGauge(
if config.C.MetricsEnabled { prometheus.GaugeOpts{
countUsersGauge = promauto.NewGauge( Name: "opengist_users_total",
prometheus.GaugeOpts{ Help: "Total number of users",
Name: "opengist_users_total", },
Help: "Total number of users", )
},
)
countGistsGauge = promauto.NewGauge( countGistsGauge = promauto.NewGauge(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "opengist_gists_total", Name: "opengist_gists_total",
Help: "Total number of gists", Help: "Total number of gists",
}, },
) )
countSSHKeysGauge = promauto.NewGauge( countSSHKeysGauge = promauto.NewGauge(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "opengist_ssh_keys_total", Name: "opengist_ssh_keys_total",
Help: "Total number of SSH keys", Help: "Total number of SSH keys",
}, },
) )
metricsInitialized = true metricsInitialized = true
}
} }
// updateMetrics refreshes all metric values from the database
func updateMetrics() { func updateMetrics() {
// Only update metrics if they're enabled if !metricsInitialized {
if !config.C.MetricsEnabled || !metricsInitialized {
return return
} }
// Update users count
countUsers, err := db.CountAll(&db.User{}) countUsers, err := db.CountAll(&db.User{})
if err == nil { if err == nil {
countUsersGauge.Set(float64(countUsers)) countUsersGauge.Set(float64(countUsers))
} }
// Update gists count
countGists, err := db.CountAll(&db.Gist{}) countGists, err := db.CountAll(&db.Gist{})
if err == nil { if err == nil {
countGistsGauge.Set(float64(countGists)) countGistsGauge.Set(float64(countGists))
} }
// Update SSH keys count
countKeys, err := db.CountAll(&db.SSHKey{}) countKeys, err := db.CountAll(&db.SSHKey{})
if err == nil { if err == nil {
countSSHKeysGauge.Set(float64(countKeys)) countSSHKeysGauge.Set(float64(countKeys))
} }
} }
// Metrics handles prometheus metrics endpoint requests.
func Metrics(ctx *context.Context) error {
// If metrics are disabled, return 404
if !config.C.MetricsEnabled {
return ctx.NotFound("Metrics endpoint is disabled")
}
// Initialize metrics if not already done
initMetrics()
// Update metrics
updateMetrics()
// Get the Echo context
echoCtx := ctx.Context
// Use the Prometheus metrics handler
handler := echoprometheus.NewHandler()
// Call the handler
return handler(echoCtx)
}

View File

@@ -0,0 +1,50 @@
package metrics
import (
"net/http"
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"github.com/thomiceli/opengist/internal/config"
)
type Server struct {
echo *echo.Echo
}
func NewServer() *Server {
e := echo.New()
e.HideBanner = true
e.HidePort = true
s := &Server{echo: e}
initMetrics()
e.GET("/metrics", func(ctx echo.Context) error {
updateMetrics()
return echoprometheus.NewHandler()(ctx)
})
return s
}
func (s *Server) Start() {
addr := config.C.MetricsHost + ":" + config.C.MetricsPort
log.Info().Msg("Starting metrics server on http://" + addr)
if err := s.echo.Start(addr); err != nil && err != http.ErrServerClosed {
log.Error().Err(err).Msg("Failed to start metrics server")
}
}
func (s *Server) Stop() {
log.Info().Msg("Stopping metrics server...")
if err := s.echo.Close(); err != nil {
log.Error().Err(err).Msg("Failed to stop metrics server")
}
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.echo.ServeHTTP(w, r)
}

View File

@@ -37,8 +37,7 @@ func (s *Server) registerMiddlewares() {
s.echo.Use(Middleware(dataInit).toEcho()) s.echo.Use(Middleware(dataInit).toEcho())
s.echo.Use(Middleware(locale).toEcho()) s.echo.Use(Middleware(locale).toEcho())
if config.C.MetricsEnabled { if config.C.MetricsEnabled {
p := echoprometheus.NewMiddleware("opengist") s.echo.Use(echoprometheus.NewMiddleware("opengist"))
s.echo.Use(p)
} }
s.echo.Pre(middleware.MethodOverrideWithConfig(middleware.MethodOverrideConfig{ s.echo.Pre(middleware.MethodOverrideWithConfig(middleware.MethodOverrideConfig{

View File

@@ -17,7 +17,6 @@ import (
"github.com/thomiceli/opengist/internal/web/handlers/gist" "github.com/thomiceli/opengist/internal/web/handlers/gist"
"github.com/thomiceli/opengist/internal/web/handlers/git" "github.com/thomiceli/opengist/internal/web/handlers/git"
"github.com/thomiceli/opengist/internal/web/handlers/health" "github.com/thomiceli/opengist/internal/web/handlers/health"
"github.com/thomiceli/opengist/internal/web/handlers/metrics"
"github.com/thomiceli/opengist/internal/web/handlers/settings" "github.com/thomiceli/opengist/internal/web/handlers/settings"
"github.com/thomiceli/opengist/public" "github.com/thomiceli/opengist/public"
) )
@@ -34,10 +33,6 @@ func (s *Server) registerRoutes() {
r.GET("/healthcheck", health.Healthcheck) r.GET("/healthcheck", health.Healthcheck)
if config.C.MetricsEnabled {
r.GET("/metrics", metrics.Metrics)
}
r.GET("/register", auth.Register) r.GET("/register", auth.Register)
r.POST("/register", auth.ProcessRegister) r.POST("/register", auth.ProcessRegister)
r.GET("/login", auth.Login) r.GET("/login", auth.Login)

View File

@@ -1,15 +1,15 @@
package test package test
import ( import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thomiceli/opengist/internal/db"
"io" "io"
"net/http" "net/http/httptest"
"os"
"strconv" "strconv"
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thomiceli/opengist/internal/db"
) )
var ( var (
@@ -41,22 +41,12 @@ var (
// - Total number of SSH keys // - Total number of SSH keys
// //
// The test follows these steps: // The test follows these steps:
// 1. Enables metrics via environment variable // 1. Sets up test environment
// 2. Sets up test environment // 2. Registers and logs in an admin user
// 3. Registers and logs in an admin user // 3. Creates a gist and adds an SSH key
// 4. Creates a gist and adds an SSH key // 4. Creates a metrics server and queries the /metrics endpoint
// 5. Queries the metrics endpoint // 5. Verifies the reported metrics match expected values
// 6. Verifies the reported metrics match expected values
//
// Environment variables:
// - OG_METRICS_ENABLED: Set to "true" for this test
func TestMetrics(t *testing.T) { func TestMetrics(t *testing.T) {
originalValue := os.Getenv("OG_METRICS_ENABLED")
os.Setenv("OG_METRICS_ENABLED", "true")
defer os.Setenv("OG_METRICS_ENABLED", originalValue)
s := Setup(t) s := Setup(t)
defer Teardown(t, s) defer Teardown(t, s)
@@ -72,12 +62,16 @@ func TestMetrics(t *testing.T) {
err = s.Request("POST", "/settings/ssh-keys", SSHKey, 302) err = s.Request("POST", "/settings/ssh-keys", SSHKey, 302)
require.NoError(t, err) require.NoError(t, err)
var metricsRes http.Response // Create a metrics server and query it
err = s.Request("GET", "/metrics", nil, 200, &metricsRes) metricsServer := NewTestMetricsServer()
require.NoError(t, err)
body, err := io.ReadAll(metricsRes.Body) req := httptest.NewRequest("GET", "/metrics", nil)
defer metricsRes.Body.Close() w := httptest.NewRecorder()
metricsServer.ServeHTTP(w, req)
require.Equal(t, 200, w.Code)
body, err := io.ReadAll(w.Body)
require.NoError(t, err) require.NoError(t, err)
lines := strings.Split(string(body), "\n") lines := strings.Split(string(body), "\n")

View File

@@ -22,6 +22,7 @@ import (
"github.com/thomiceli/opengist/internal/config" "github.com/thomiceli/opengist/internal/config"
"github.com/thomiceli/opengist/internal/db" "github.com/thomiceli/opengist/internal/db"
"github.com/thomiceli/opengist/internal/git" "github.com/thomiceli/opengist/internal/git"
"github.com/thomiceli/opengist/internal/web/handlers/metrics"
"github.com/thomiceli/opengist/internal/web/server" "github.com/thomiceli/opengist/internal/web/server"
) )
@@ -240,3 +241,7 @@ type invitationAdmin struct {
nbMax string `form:"nbMax"` nbMax string `form:"nbMax"`
expiredAtUnix string `form:"expiredAtUnix"` expiredAtUnix string `form:"expiredAtUnix"`
} }
func NewTestMetricsServer() *metrics.Server {
return metrics.NewServer()
}