first commit
This commit is contained in:
commit
1136ac0b01
7 changed files with 212 additions and 0 deletions
1
.env.example
Normal file
1
.env.example
Normal file
|
@ -0,0 +1 @@
|
|||
TRAEWELLING_TOKEN=
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.env
|
20
docker-compose.yml
Normal file
20
docker-compose.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
traewelling-metrics:
|
||||
build:
|
||||
context: go/.
|
||||
dockerfile: Dockerfile
|
||||
#ports:
|
||||
# - "8080:8080" # Exponiere Port 8080 für Prometheus-Scraping
|
||||
restart: always # Neustart bei Fehlern oder Updates
|
||||
environment:
|
||||
- TRAEWELLING_TOKEN=${TRAEWELLING_TOKEN}
|
||||
networks:
|
||||
default:
|
||||
dns:
|
||||
ipv4_address: 172.28.0.245
|
||||
|
||||
networks:
|
||||
dns:
|
||||
external: true
|
28
go/Dockerfile
Normal file
28
go/Dockerfile
Normal file
|
@ -0,0 +1,28 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Build the application from source
|
||||
FROM golang:1.21 AS build-stage
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY * ./
|
||||
RUN go mod download
|
||||
|
||||
RUN CGO_ENABLED=0 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-debian11 AS build-release-stage
|
||||
|
||||
WORKDIR /
|
||||
|
||||
COPY --from=build-stage /main /main
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
USER nonroot:nonroot
|
||||
|
||||
ENTRYPOINT ["/main"]
|
17
go/go.mod
Normal file
17
go/go.mod
Normal file
|
@ -0,0 +1,17 @@
|
|||
module traewelling-exporter
|
||||
|
||||
go 1.19
|
||||
|
||||
require github.com/prometheus/client_golang v1.21.1
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // 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.62.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
google.golang.org/protobuf v1.36.1 // indirect
|
||||
)
|
26
go/go.sum
Normal file
26
go/go.sum
Normal file
|
@ -0,0 +1,26 @@
|
|||
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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||
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.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
119
go/main.go
Normal file
119
go/main.go
Normal file
|
@ -0,0 +1,119 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
totalTrips = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "traewelling_total_trips",
|
||||
Help: "Gesamtanzahl der Fahrten",
|
||||
})
|
||||
totalDistance = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "traewelling_total_distance_km",
|
||||
Help: "Gesamtdistanz aller Fahrten in Kilometern",
|
||||
})
|
||||
averageDuration = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "traewelling_average_duration_minutes",
|
||||
Help: "Durchschnittliche Dauer der Fahrten in Minuten",
|
||||
})
|
||||
)
|
||||
|
||||
type DashboardResponse struct {
|
||||
Data []struct {
|
||||
ID int `json:"id"`
|
||||
Train struct {
|
||||
Trip int `json:"trip"`
|
||||
Distance float64 `json:"distance"`
|
||||
Duration int `json:"duration"`
|
||||
Category string `json:"category"`
|
||||
LineName string `json:"lineName"`
|
||||
JourneyNumber int `json:"journeyNumber"`
|
||||
Origin struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"origin"`
|
||||
Destination struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"destination"`
|
||||
} `json:"train"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func fetchTraewellingData() (*DashboardResponse, error) {
|
||||
url := "https://traewelling.de/api/v1/dashboard"
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Fehler beim Erstellen der Anfrage: %v", err)
|
||||
}
|
||||
|
||||
token := os.Getenv("TRAEWELLING_TOKEN")
|
||||
if token == "" {
|
||||
return nil, fmt.Errorf("TRAEWELLING_TOKEN ist nicht gesetzt")
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Fehler beim Senden der Anfrage: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("Fehlerhafte Antwort: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var apiResponse DashboardResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&apiResponse)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Fehler beim Parsen der JSON-Daten: %v", err)
|
||||
}
|
||||
|
||||
return &apiResponse, nil
|
||||
}
|
||||
|
||||
func updateMetrics() {
|
||||
data, err := fetchTraewellingData()
|
||||
if err != nil {
|
||||
fmt.Printf("Fehler beim Abrufen der Daten: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
var totalTripsCount int
|
||||
var totalDistanceSum float64
|
||||
var totalDurationSum int
|
||||
|
||||
for _, trip := range data.Data {
|
||||
totalTripsCount++
|
||||
totalDistanceSum += trip.Train.Distance / 1000
|
||||
totalDurationSum += trip.Train.Duration
|
||||
}
|
||||
|
||||
totalTrips.Set(float64(totalTripsCount))
|
||||
totalDistance.Set(totalDistanceSum)
|
||||
if totalTripsCount > 0 {
|
||||
averageDuration.Set(float64(totalDurationSum) / float64(totalTripsCount))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
go func() {
|
||||
for {
|
||||
updateMetrics()
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
}()
|
||||
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
fmt.Println("Server läuft auf Port 8080...")
|
||||
http.ListenAndServe(":8080", nil)
|
||||
}
|
Loading…
Add table
Reference in a new issue