Compare commits

...

16 Commits

Author SHA1 Message Date
84fcfdde62 Add workflows and fix linter errors
All checks were successful
go-test-build / go-test-build (1.21) (push) Successful in 58s
go-test-build / go-test-build (1.22) (push) Successful in 1m0s
golangci-lint / goglangci-lint (push) Successful in 1m21s
nix-check-build / nix-check-build (push) Successful in 1m26s
2024-10-11 01:18:53 +02:00
4f594f7412 Add golangci-lint 2024-10-11 01:10:59 +02:00
cf83c4b609 Bump deps 2024-10-11 01:09:22 +02:00
7d251291dc Use pname instead of name 2024-10-10 23:37:47 +02:00
5d09d99ff5 Let debouncer delay be configurable 2024-10-10 23:13:00 +02:00
dc40185002 Remove leftover variable 2024-10-10 22:46:06 +02:00
facf18336f Merge pull request 'Add debouncer' (#1) from debounce into master
Reviewed-on: #1
2024-10-10 20:41:05 +00:00
760d293044 Add debouncer 2024-10-10 22:40:29 +02:00
a465fa3adc flake.lock: Update
Flake lock file updates:

• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/ad57eef4ef0659193044870c731987a6df5cf56b' (2024-05-29)
  → 'github:NixOS/nixpkgs/30439d93eb8b19861ccbe3e581abf97bdc91b093' (2024-09-23)
2024-09-27 15:16:00 +02:00
e3daec2670 Flake update 2024-06-03 03:53:23 +02:00
160554e8a4 Switch input device 2024-06-03 03:53:06 +02:00
1dc02bd21b Flake update 2024-05-06 20:39:54 +02:00
106df5c4a5 Nix flake update 2024-04-18 10:11:29 +02:00
a1ba7fb0f3 Flake update 2024-04-03 11:56:18 +02:00
a8c527ba18 Run nix flake update 2024-03-18 14:16:31 +01:00
8d5562a2c7 Add metrics 2024-03-18 14:16:05 +01:00
14 changed files with 454 additions and 54 deletions

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

20
.github/workflows/go-test-build.yaml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: go-test-build
on:
push:
pull_request:
jobs:
go-test-build:
runs-on: ubuntu-latest
container:
image: ghcr.io/catthehacker/ubuntu:runner-latest
strategy:
matrix:
go: [ "1.22", "1.21" ]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- run: go test -v ./...
- run: go build -o main main.go

19
.github/workflows/golangci-lint.yaml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: golangci-lint
on:
push:
pull_request:
jobs:
goglangci-lint:
runs-on: ubuntu-latest
container:
image: ghcr.io/catthehacker/ubuntu:runner-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.61

15
.github/workflows/nix-check-build.yaml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: nix-check-build
on:
push:
pull_request:
jobs:
nix-check-build:
runs-on: ubuntu-latest
container:
image: ghcr.io/catthehacker/ubuntu:runner-latest
steps:
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v27
- run: nix flake check
- run: nix build

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.direnv
result

49
bus/bus.go Normal file
View File

@@ -0,0 +1,49 @@
package bus
import (
"time"
"git.t-juice.club/torjus/ghettoptt/metrics"
"github.com/godbus/dbus/v5"
)
type MumbleBus struct {
conn *dbus.Conn
obj dbus.BusObject
metrics *metrics.MumbleMetricsCollector
lastTalked time.Time
}
func NewMumbleBus(m *metrics.MumbleMetricsCollector) *MumbleBus {
mb := &MumbleBus{
metrics: m,
}
conn, err := dbus.ConnectSessionBus()
if err != nil {
panic(err)
}
mb.obj = conn.Object("net.sourceforge.mumble.mumble", "/")
mb.conn = conn
return mb
}
func (m *MumbleBus) Close() error {
return m.conn.Close()
}
func (m *MumbleBus) StartTalking() error {
m.obj.Call("net.sourceforge.mumble.Mumble.startTalking", 0)
m.lastTalked = time.Now()
m.metrics.PTTTogglesTotal.Add(1)
return nil
}
func (m *MumbleBus) StopTalking() error {
m.obj.Call("net.sourceforge.mumble.Mumble.stopTalking", 0)
duration := time.Since(m.lastTalked)
m.lastTalked = time.Time{}
m.metrics.TalkSecondsTotal.Add(duration.Seconds())
m.metrics.PTTTogglesTotal.Add(1)
return nil
}

53
debouncer/debouncer.go Normal file
View File

@@ -0,0 +1,53 @@
package debouncer
import "time"
type Debouncer struct {
input <-chan bool
C <-chan bool
}
func New(ch <-chan bool, window time.Duration) *Debouncer {
output := make(chan bool)
var currentState bool
var lastState bool
falseTimer := time.NewTimer(0)
falseTimer.Stop()
go func() {
for {
select {
case <-falseTimer.C:
if !currentState && lastState {
output <- false
lastState = false
} else {
falseTimer.Reset(window)
}
case v, ok := <-ch:
if !ok {
falseTimer.Reset(window)
<-falseTimer.C
output <- false
close(output)
return
}
if v {
if !lastState {
output <- true
lastState = true
falseTimer.Reset(window)
}
currentState = true
} else {
falseTimer.Reset(window)
currentState = false
}
}
}
}()
d := &Debouncer{input: ch, C: output}
return d
}

View File

@@ -0,0 +1,89 @@
package debouncer_test
import (
"testing"
"time"
"git.t-juice.club/torjus/ghettoptt/debouncer"
)
func TestDebouncer(t *testing.T) {
t.Run("Simple", func(t *testing.T) {
ch := make(chan bool)
d := debouncer.New(ch, 200*time.Millisecond)
go func() {
ch <- true
close(ch)
}()
if v := <-d.C; v != true {
t.Errorf("Expected true, got %v", v)
}
})
t.Run("TrueTrueTrueFalse", func(t *testing.T) {
ch := make(chan bool)
d := debouncer.New(ch, 200*time.Millisecond)
go func() {
ch <- true
ch <- true
ch <- true
ch <- false
close(ch)
}()
if v := <-d.C; v != true {
t.Errorf("Expected true, got %v", v)
}
if v := <-d.C; v != false {
t.Errorf("Expected false, got %v", v)
}
})
t.Run("Debounce", func(t *testing.T) {
ch := make(chan bool)
d := debouncer.New(ch, 200*time.Millisecond)
go func() {
ch <- true
time.Sleep(10 * time.Millisecond)
ch <- false
time.Sleep(1 * time.Millisecond)
ch <- true
time.Sleep(1 * time.Millisecond)
ch <- false
time.Sleep(10 * time.Millisecond)
close(ch)
}()
if v := <-d.C; v != true {
t.Errorf("Expected first value to be true, got %v", v)
}
if v := <-d.C; v != false {
t.Errorf("Expected second value to be false, got %v", v)
}
if v, ok := <-d.C; ok {
t.Errorf("Expected closed channel, got %v", v)
}
})
t.Run("DebounceDelay", func(t *testing.T) {
ch := make(chan bool)
d := debouncer.New(ch, 200*time.Millisecond)
go func() {
ch <- true
ch <- false
close(ch)
}()
start := time.Now()
if v := <-d.C; v != true {
t.Errorf("Expected first value to be true, got %v", v)
}
if v, ok := <-d.C; v != false || !ok {
if ok {
t.Errorf("Expected second value to be false, got %v", v)
} else {
t.Error("Unexpected closed channel")
}
}
if duration := time.Since(start); duration < 200*time.Millisecond {
t.Errorf("Got false too soon: %s", duration)
}
})
}

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1709703039, "lastModified": 1727122398,
"narHash": "sha256-6hqgQ8OK6gsMu1VtcGKBxKQInRLHtzulDo9Z5jxHEFY=", "narHash": "sha256-o8VBeCWHBxGd4kVMceIayf5GApqTavJbTa44Xcg5Rrk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9df3e30ce24fd28c7b3e2de0d986769db5d6225d", "rev": "30439d93eb8b19861ccbe3e581abf97bdc91b093",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -3,7 +3,8 @@
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }: outputs =
{ self, nixpkgs }:
let let
allSystems = [ allSystems = [
"x86_64-linux" "x86_64-linux"
@@ -11,28 +12,56 @@
"x86_64-darwin" "x86_64-darwin"
"aarch64-darwin" "aarch64-darwin"
]; ];
forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f { forAllSystems =
f:
nixpkgs.lib.genAttrs allSystems (
system:
f {
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs { inherit system; };
}); }
);
in in
{ {
overlays.default = final: prev: { overlays.default = final: prev: {
ghettoptt = self.packages.${prev.system}.default; ghettoptt = self.packages.${prev.system}.default;
}; };
packages = forAllSystems ({ pkgs }: { packages = forAllSystems (
default = pkgs.buildGoModule { { pkgs }:
name = "ghettoptt"; {
src = ./.; default =
vendorHash = "sha256-S/t8EkMRjceGhNcNqGhmnMviQrhqt7n9FiCmpxbKUoI="; let
src = pkgs.lib.sourceFilesBySuffices ./. [
"go.mod"
"go.sum"
".go"
];
version = pkgs.lib.strings.removePrefix "v" (
builtins.elemAt (pkgs.lib.strings.split "\"" (
pkgs.lib.lists.findFirst (x: pkgs.lib.strings.hasInfix "Version" x) null (
pkgs.lib.strings.splitString "\n" (builtins.readFile ./main.go)
)
)) 2
);
in
pkgs.buildGoModule {
version = version;
pname = "ghettoptt";
src = src;
vendorHash = "sha256-Jnk06H/5dIGbb284c2IReZfS7U0TaBoGWYkU/mjyBek=";
}; };
}); }
devShells = forAllSystems ({ pkgs }: { );
devShells = forAllSystems (
{ pkgs }:
{
default = pkgs.mkShell { default = pkgs.mkShell {
packages = with pkgs; [ packages = with pkgs; [
go go
golangci-lint
]; ];
}; };
}); }
);
}; };
} }

17
go.mod
View File

@@ -3,6 +3,19 @@ module git.t-juice.club/torjus/ghettoptt
go 1.21.6 go 1.21.6
require ( require (
github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/godbus/dbus/v5 v5.1.0
github.com/holoplot/go-evdev v0.0.0-20240306072622-217e18f17db1 // indirect github.com/holoplot/go-evdev v0.0.0-20240306072622-217e18f17db1
github.com/prometheus/client_golang v1.20.4
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/klauspost/compress v1.17.10 // 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.60.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
golang.org/x/sys v0.26.0 // indirect
google.golang.org/protobuf v1.35.1 // indirect
) )

38
go.sum
View File

@@ -1,4 +1,42 @@
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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/holoplot/go-evdev v0.0.0-20240306072622-217e18f17db1 h1:92OsBIf5KB1Tatx+uUGOhah73jyNUrt7DmfDRXXJ5Xo= github.com/holoplot/go-evdev v0.0.0-20240306072622-217e18f17db1 h1:92OsBIf5KB1Tatx+uUGOhah73jyNUrt7DmfDRXXJ5Xo=
github.com/holoplot/go-evdev v0.0.0-20240306072622-217e18f17db1/go.mod h1:iHAf8OIncO2gcQ8XOjS7CMJ2aPbX2Bs0wl5pZyanEqk= github.com/holoplot/go-evdev v0.0.0-20240306072622-217e18f17db1/go.mod h1:iHAf8OIncO2gcQ8XOjS7CMJ2aPbX2Bs0wl5pZyanEqk=
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
github.com/prometheus/client_golang v1.20.4/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.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0=
github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.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=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

89
main.go
View File

@@ -4,15 +4,19 @@ import (
"context" "context"
"errors" "errors"
"log/slog" "log/slog"
"net/http"
"os" "os"
"os/signal" "os/signal"
"time" "time"
"github.com/godbus/dbus/v5" "git.t-juice.club/torjus/ghettoptt/bus"
"git.t-juice.club/torjus/ghettoptt/debouncer"
"git.t-juice.club/torjus/ghettoptt/metrics"
"github.com/holoplot/go-evdev" "github.com/holoplot/go-evdev"
"github.com/prometheus/client_golang/prometheus/promhttp"
) )
const Version = "v0.1.1" const Version = "v0.1.4"
func main() { func main() {
// Setup logger // Setup logger
@@ -24,55 +28,96 @@ func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop() defer stop()
// Connect to dbus // Setup metrics
conn, err := dbus.ConnectSessionBus() m := metrics.NewMumbleMetricsCollector()
if err != nil {
panic(err)
}
defer conn.Close()
obj := conn.Object("net.sourceforge.mumble.mumble", "/") mbus := bus.NewMumbleBus(m)
defer mbus.Close()
// Start reading input events // Start reading input events
input, err := evdev.OpenWithFlags("/dev/input/event1", os.O_RDONLY) input, err := evdev.OpenWithFlags("/dev/input/by-id/usb-SteelSeries_SteelSeries_Rival_710_Gaming_Mouse-if02-event-kbd", os.O_RDONLY)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer input.Close() defer input.Close()
input.NonBlock() if err := input.NonBlock(); err != nil {
slog.Error("Failed to set non-blocking mode", "error", err)
os.Exit(1)
}
var done bool // Start metrics server
srvCtx, srvCancel := context.WithCancel(context.Background())
defer srvCancel()
go func() {
mux := http.NewServeMux()
mux.Handle("/metrics", promhttp.Handler())
srv := http.Server{
Handler: mux,
Addr: ":8989",
}
go func() {
<-ctx.Done()
_ = srv.Shutdown(context.Background())
srvCancel()
}()
slog.Info("Starting metrics server", "addr", srv.Addr)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
slog.Warn("Failed to start metrics server", "error", err)
}
}()
// Listen for context cancellation // Listen for context cancellation
go func() { go func() {
<-ctx.Done() <-ctx.Done()
done = true
input.Close() input.Close()
}() }()
var lastOn time.Time
// Start listening for PTT key // Start listening for PTT key
slog.Info("Starting event listener", "version", Version) slog.Info("Starting event listener", "version", Version)
eventCh := make(chan bool)
doneCtx, doneCancel := context.WithCancel(srvCtx)
defer doneCancel()
debouncer := debouncer.New(eventCh, 400*time.Millisecond)
go func() {
var done bool
for !done { for !done {
ev, err := input.ReadOne() ev, err := input.ReadOne()
if err != nil { if err != nil {
if errors.Is(err, os.ErrClosed) { if errors.Is(err, os.ErrClosed) {
continue continue
} }
slog.Error("Error reading fron input device", "error", err) slog.Error("Error reading from input device", "error", err)
_ = mbus.StopTalking()
os.Exit(1) os.Exit(1)
} }
if ev.Code == evdev.KEY_F24 && ev.Value == 1 { if ev.Code == evdev.KEY_F24 && ev.Value == 1 {
slog.Info("PTT ON") slog.Debug("PTT ON")
lastOn = time.Now() eventCh <- true
obj.Call("net.sourceforge.mumble.Mumble.startTalking", 0)
} }
if ev.Code == evdev.KEY_F24 && ev.Value == 0 { if ev.Code == evdev.KEY_F24 && ev.Value == 0 {
speakDuration := time.Since(lastOn).String() slog.Debug("PTT OFF")
slog.Info("PTT OFF", "duration", speakDuration) eventCh <- false
obj.Call("net.sourceforge.mumble.Mumble.stopTalking", 0) }
if doneCtx.Err() != nil {
close(eventCh)
done = true
} }
} }
obj.Call("net.sourceforge.mumble.Mumble.stopTalking", 0) }()
for v := range debouncer.C {
if v {
_ = mbus.StartTalking()
slog.Info("Started talking")
} else {
_ = mbus.StopTalking()
slog.Info("Stopped talking")
}
}
_ = mbus.StopTalking()
<-srvCtx.Done()
slog.Info("Exiting") slog.Info("Exiting")
} }

27
metrics/metrics.go Normal file
View File

@@ -0,0 +1,27 @@
package metrics
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
type MumbleMetricsCollector struct {
TalkSecondsTotal prometheus.Counter
PTTTogglesTotal prometheus.Counter
}
func NewMumbleMetricsCollector() *MumbleMetricsCollector {
talkSecondsTotal := promauto.NewCounter(prometheus.CounterOpts{
Name: "mumble_talk_seconds_total",
Help: "The total number of seconds a user has been talking",
})
pttTogglesTotal := promauto.NewCounter(prometheus.CounterOpts{
Name: "mumble_ptt_toggles_total",
Help: "The total number of seconds a user has been talking",
})
return &MumbleMetricsCollector{
TalkSecondsTotal: talkSecondsTotal,
PTTTogglesTotal: pttTogglesTotal,
}
}