Skip to content

Commit

Permalink
feat: Added Prometheus (#15)
Browse files Browse the repository at this point in the history
* feat: Added Prometheus

* fix: lint

* fix: lint
  • Loading branch information
wolmi authored Oct 5, 2023
1 parent ee1af97 commit 03dfe28
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 17 deletions.
10 changes: 10 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"
"livekit-webhook-proxy/types"
"livekit-webhook-proxy/utils"
"log"
"os"
"strings"
Expand All @@ -27,6 +28,9 @@ and manages to publish them in a GCP PubSub topic.`,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()

pm := utils.PromMetrics{}
pm.StartPrometheus(viper.GetBool("prometheus.enable"), viper.GetInt("prometheus.port"))

proxy := types.Proxy{}

proxy.Init(ctx)
Expand Down Expand Up @@ -59,6 +63,12 @@ func init() {

rootCmd.Flags().StringP("project-id", "P", "", "GCP ProjectId")
viper.BindPFlag("project-id", rootCmd.Flags().Lookup("project-id")) // nolint

rootCmd.Flags().Bool("prometheus.enable", true, "Enable Prometheus metrics")
viper.BindPFlag("prometheus.enable", rootCmd.Flags().Lookup("prometheus.enable")) // nolint

rootCmd.Flags().Int("prometheus.port", 9040, "Prometheus port")
viper.BindPFlag("prometheus.port", rootCmd.Flags().Lookup("prometheus.port")) // nolint
}

// initConfig reads in config file and ENV variables if set.
Expand Down
14 changes: 11 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ go 1.20

require (
cloud.google.com/go/compute/metadata v0.2.3
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.4.0
github.com/prometheus/client_golang v1.17.0
)

require (
cloud.google.com/go v0.110.2 // indirect
cloud.google.com/go/iam v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
Expand All @@ -18,20 +22,24 @@ require (
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sync v0.3.0 // indirect
google.golang.org/api v0.126.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)

require (
Expand All @@ -51,7 +59,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.16.0
github.com/subosito/gotenv v1.4.2 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.9.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
22 changes: 22 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,12 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
Expand Down Expand Up @@ -169,6 +173,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
Expand All @@ -182,6 +188,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
Expand All @@ -190,7 +198,15 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
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.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
Expand Down Expand Up @@ -345,6 +361,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -389,6 +407,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down Expand Up @@ -564,6 +584,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
48 changes: 34 additions & 14 deletions types/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,77 @@ import (
"net/http"

"github.com/labstack/gommon/log"
"github.com/prometheus/client_golang/prometheus"

"cloud.google.com/go/pubsub"
"github.com/labstack/echo/v4"
"github.com/spf13/viper"
)

type Proxy struct {
pubsub utils.PubSub
echo *echo.Echo
pubsub utils.PubSub
Server *echo.Echo
Metrics struct {
eventReceived *prometheus.CounterVec
eventPublished *prometheus.CounterVec
}
}

func (p *Proxy) Init(ctx context.Context) {
p.echo = echo.New()
p.Server = echo.New()
p.pubsub.Init(ctx)

p.echo.HideBanner = true
p.Server.HideBanner = true

// get log level from flag
logLevel := viper.GetBool("debug")
if logLevel {
p.echo.Logger.SetLevel(log.DEBUG)
p.Server.Logger.SetLevel(log.DEBUG)
} else {
p.echo.Logger.SetLevel(log.INFO)
p.Server.Logger.SetLevel(log.INFO)
}

p.echo.GET("/", func(c echo.Context) error {
p.Server.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "ok")
})

p.echo.POST("/publish", p.publish)
p.echo.Logger.Fatal(p.echo.Start(fmt.Sprintf(":%d", viper.GetInt("port"))))
p.Server.POST("/publish", p.publish)
p.Server.Logger.Fatal(p.Server.Start(fmt.Sprintf(":%d", viper.GetInt("port"))))

p.Metrics.eventReceived = prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "livekit_webhook_proxy_event_received_total",
Help: "The total number of events received",
}, []string{"event", "room"})
p.Metrics.eventPublished = prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "livekit_webhook_proxy_event_published_total",
Help: "The total number of events published",
}, []string{"event", "room"})
}

func (p *Proxy) publish(c echo.Context) error {
var payload map[string]interface{}
if err := json.NewDecoder(c.Request().Body).Decode(&payload); err != nil {
p.echo.Logger.Errorf("could not decode body: %v", err)
p.Server.Logger.Errorf("could not decode body: %v", err)
return echo.NewHTTPError(http.StatusBadRequest, "could not bind body").SetInternal(err)
}
p.echo.Logger.Infof("livekit event %s in room %s", payload["event"], payload["room"].(map[string]interface{})["name"])
p.Server.Logger.Infof("livekit event %s in room %s", payload["event"], payload["room"].(map[string]interface{})["name"])

p.Metrics.eventReceived.WithLabelValues(payload["event"].(string), payload["room"].(map[string]interface{})["name"].(string)).Inc()

jsonPayload, _ := json.Marshal(payload)
p.echo.Logger.Debugf("event payload data: %s", jsonPayload)
p.Server.Logger.Debugf("event payload data: %s", jsonPayload)

topic := p.pubsub.Client.Topic(viper.GetString("topic"))
res := topic.Publish(c.Request().Context(), &pubsub.Message{
Data: jsonPayload,
})
msgID, err := res.Get(c.Request().Context())
if err != nil {
p.echo.Logger.Fatal(err)
p.Server.Logger.Fatal(err)
}
p.echo.Logger.Debugf("event published with msgID %v", msgID)
p.Server.Logger.Debugf("event published with msgID %v", msgID)

p.Metrics.eventPublished.WithLabelValues(payload["event"].(string), payload["room"].(map[string]interface{})["name"].(string)).Inc()

return c.JSON(http.StatusOK, payload)
}
49 changes: 49 additions & 0 deletions utils/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package utils

import (
"fmt"
"net/http"
"strconv"
"strings"
"time"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

type PromMetrics struct{}

func (m *PromMetrics) StartPrometheus(enable bool, port int) {

if enable {

//Disable golang metris
prometheus.Unregister(collectors.NewGoCollector())

prometheusMux := http.NewServeMux()
// register endpoints
prometheusMux.Handle("/metrics", promhttp.Handler()) //Prometheus endpoint
prometheusMux.HandleFunc("/hltz", m.healthCheck) //Health Check endpoint
prometheusMux.HandleFunc("/", m.healthCheck) //Health Check endpoint
prometheusListenPort := strings.Join([]string{":", strconv.Itoa(port)}, "")
prometheusServer := &http.Server{
ReadHeaderTimeout: 5 * time.Second,
Addr: prometheusListenPort,
Handler: prometheusMux,
}
go func() {
//Start server
fmt.Println("Prometheus endpoint started in port", port)
if err := prometheusServer.ListenAndServe(); err != nil {
panic(err)
}
}()
}
}

// Generic function to handle a helath check
func (m *PromMetrics) healthCheck(w http.ResponseWriter, r *http.Request) { //nolint
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK")) // nolint
}

0 comments on commit 03dfe28

Please sign in to comment.