commit 5817a382fdf10c130dd0d00c588535b8c82b2637 Author: Simon Rieger Date: Sat Nov 2 09:30:54 2024 +0100 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..5fc3ade --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +# pocket-id-exporter + +Der pocket-id-exporter ist ein Prometheus-Exporter für die Pocket ID-Datenbank. Er stellt Metriken über die Anzahl der Anmeldungen und Benutzer bereit. + +## Funktionen + +- Exportiert die Gesamtzahl der Anmeldungen als Metrik `pocket_id_login_count` +- Exportiert die Gesamtzahl der Benutzer als Metrik `pocket_id_user_count` +- Stellt Metriken im Prometheus-Format unter dem `/metrics`-Endpunkt bereit + +## Voraussetzungen + +- Docker +- Docker Compose + +## Verwendung mit Docker Compose + +1. Erstellen Sie eine `docker-compose.yml`-Datei im Projektverzeichnis mit folgendem Inhalt: + +```yaml +version: '3' +services: + pocket-id-exporter: + build: . + ports: + - "3000:3000" + volumes: + - ./data:/app/data +``` + +2. Erstellen Sie eine `Dockerfile` im Projektverzeichnis: + +```Dockerfile +FROM golang:1.17-alpine + +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN go build -o pocket-id-exporter + +EXPOSE 3000 + +CMD ["./pocket-id-exporter"] +``` + +3. Stellen Sie sicher, dass Ihre SQLite-Datenbank im Verzeichnis `./data` mit dem Namen `pocket-id.db` liegt. + +4. Bauen und starten Sie den Container mit Docker Compose: + +```bash +docker-compose up --build +``` + +Der Exporter ist nun unter `http://localhost:3000/metrics` erreichbar. + +## Konfiguration von Prometheus + +Fügen Sie folgende Job-Konfiguration zu Ihrer `prometheus.yml` hinzu, um die Metriken zu scrapen: + +```yaml +scrape_configs: + - job_name: 'pocket-id' + static_configs: + - targets: ['localhost:3000'] +``` + +## Entwicklung + +Um den Exporter lokal zu entwickeln und zu testen: + +1. Installieren Sie Go (Version 1.17 oder höher) +2. Klonen Sie das Repository +3. Installieren Sie die Abhängigkeiten: + +```bash +go mod download +``` + +4. Bauen und starten Sie den Exporter: + +```bash +go build +./pocket-id-exporter +``` + +## Lizenz + +[MIT License](LICENSE) + +https://github.com/stonith404/pocket-id + +https://goneuland.de/pocket-id-mit-docker-und-traefik-installieren/ + +https://github.com/stonith404/pocket-id/issues/56 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..fd74aa7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,54 @@ +services: + pocketid: + image: stonith404/pocket-id:latest + container_name: pocket-id + restart: unless-stopped + env_file: .env + volumes: + - "./data:/app/backend/data" + + environment: + - TRUST_PROXY=true # Set to true if a reverse proxy is in front of the container + - VIRTUAL_HOST=pocket-id.brothertec.eu + - VIRTUAL_PORT=80 + - LETSENCRYPT_HOST=pocket-id.brothertec.eu + - LETSENCRYPT_EMAIL=admin@brothertec.eu + + labels: + - "com.centurylinklabs.watchtower.enable=true" + + networks: + - default + - proxy + - edge-tier + + pocket-id-exporter: + container_name: pocket-id-exporter + build: + context: go/. + args: + - GO111MODULE=off + volumes: + - "./data:/data" + #ports: + # - "3000:3000" + environment: + - TZ=Europe/Berlin + + restart: always + + networks: + default: + dns: + ipv4_address: 172.28.0.93 + +networks: + dns: + name: dns + external: true + proxy: + name: nginx-proxy + external: true + edge-tier: + name: edge + external: true diff --git a/go/Dockerfile b/go/Dockerfile new file mode 100755 index 0000000..eb74f54 --- /dev/null +++ b/go/Dockerfile @@ -0,0 +1,28 @@ +# syntax=docker/dockerfile:1 + +# Build the application from source +FROM golang:1.20 AS build-stage + +WORKDIR /app + +COPY * ./ +RUN go mod download + +RUN CGO_ENABLED=1 GOOS=linux go build -o /main + +# Run the tests in the container +FROM build-stage AS run-test-stage +RUN go test -v ./... + +# Deploy the application binary into a lean image +FROM gcr.io/distroless/base-debian12 AS build-release-stage + +WORKDIR / + +COPY --from=build-stage /main /main + +EXPOSE 8080 + +USER nonroot:nonroot + +ENTRYPOINT ["/main"] diff --git a/go/Dockerfile.old b/go/Dockerfile.old new file mode 100755 index 0000000..2c572c4 --- /dev/null +++ b/go/Dockerfile.old @@ -0,0 +1,22 @@ +# Use an official Golang runtime as a parent image +FROM golang:1.21.4 + +# Set the working directory in the container +WORKDIR /go/src/app + +# Copy the local package files to the container's workspace +COPY . . + +# Download and install any required third-party dependencies into the container. +#RUN go get -u github.com/gorilla/mux +RUN go get -u github.com/go-sql-driver/mysql +RUN go get -u github.com/sirupsen/logrus + +# Build the Go application +RUN go build -o main . + +# Expose port 8080 to the outside world +EXPOSE 8080 + +# Command to run the application with environment variables +CMD ["./main"] diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 0000000..068a048 --- /dev/null +++ b/go/go.mod @@ -0,0 +1,20 @@ +module pocket-id-exporter + +go 1.20 + +require ( + github.com/mattn/go-sqlite3 v1.14.24 + github.com/prometheus/client_golang v1.20.5 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + golang.org/x/sys v0.22.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect +) diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 0000000..668d781 --- /dev/null +++ b/go/go.sum @@ -0,0 +1,24 @@ +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.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= +github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/go/mailu.go b/go/mailu.go new file mode 100644 index 0000000..f23e695 --- /dev/null +++ b/go/mailu.go @@ -0,0 +1,75 @@ +package main + +import ( + "database/sql" + "log" + "net/http" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + _ "github.com/mattn/go-sqlite3" +) + +const ( + dbPath = "./data/pocket-id.db" + port = ":3000" +) + +var ( + db *sql.DB + + loginCount = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "pocket_id_login_count", + Help: "Total number of sign-ins", + }) + + userCount = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "pocket_id_user_count", + Help: "Total number of users", + }) +) + +func init() { + prometheus.MustRegister(loginCount) + prometheus.MustRegister(userCount) +} + +func main() { + var err error + db, err = sql.Open("sqlite3", dbPath) + if err != nil { + log.Fatalf("Error opening database: %v", err) + } + defer db.Close() + + log.Println("Connected to the Pocket ID SQLite database.") + + http.HandleFunc("/metrics", metricsHandler) + http.Handle("/", promhttp.Handler()) + + log.Printf("Server running on http://localhost%s", port) + log.Fatal(http.ListenAndServe(port, nil)) +} + +func metricsHandler(w http.ResponseWriter, r *http.Request) { + updateMetrics() + promhttp.Handler().ServeHTTP(w, r) +} + +func updateMetrics() { + var count int + + err := db.QueryRow("SELECT COUNT(*) FROM Audit_Logs WHERE event = 'SIGN_IN'").Scan(&count) + if err != nil { + log.Printf("Error querying login count: %v", err) + } else { + loginCount.Set(float64(count)) + } + + err = db.QueryRow("SELECT COUNT(*) FROM Users").Scan(&count) + if err != nil { + log.Printf("Error querying user count: %v", err) + } else { + userCount.Set(float64(count)) + } +}