Basic Prometheus metrics
All checks were successful
Nix build / build-docker (pull_request) Successful in 2m25s
Nix build / build-docker-arm (pull_request) Successful in 5m41s

Currently track number of paste views and total pastes in
database. May expand over time.
This commit is contained in:
Gabriel Simmer 2024-05-18 23:02:27 +01:00
parent 5a1cbd6490
commit dfeba31784
Signed by: arch
SSH key fingerprint: SHA256:m3OEcdtrnBpMX+2BDGh/byv3hrCekCLzDYMdvGEKPPQ
4 changed files with 65 additions and 4 deletions

View file

@ -26,6 +26,9 @@ import (
_ "github.com/lib/pq"
"github.com/microcosm-cc/bluemonday"
"github.com/niklasfasching/go-org/org"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/russross/blackfriday"
_ "modernc.org/sqlite"
"tailscale.com/client/tailscale"
@ -43,6 +46,7 @@ var (
hidePasteUserInfo = flag.Bool("hide-funnel-users", hasEnv("HIDE_FUNNEL_USERS"), "if set, display the username and profile picture of the user who created the paste in funneled pastes")
databaseUrl = flag.String("database-url", envOr("DATABASE_URL", ""), "optional database url if you'd rather use Postgres instead of sqlite")
httpPort = flag.String("http-port", envOr("HTTP_PORT", ""), "optional http port to start an http server on, e.g for reverse proxies. will only serve funnel endpoints")
enableMetrics = flag.Bool("enable-metrics", hasEnv("ENABLE_METRICS"), "if set, enabled the /metrics endpoint on the tailnet listener")
//go:embed schema.sql
sqlSchema string
@ -63,6 +67,17 @@ func hasEnv(name string) bool {
const formDataLimit = 64 * 1024 // 64 kilobytes (approx. 32 printed pages of text)
var (
totalPastes = promauto.NewGauge(prometheus.GaugeOpts{
Name: "tclip_total_pastes",
Help: "The total number of stored pastes",
})
pasteViews = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "tclip_paste_views",
Help: "Number of times a paste has been viewed",
}, []string{"id", "origin", "type"})
)
func dataLocation() string {
if dir, ok := os.LookupEnv("DATA_DIR"); ok {
return dir
@ -264,7 +279,7 @@ VALUES
}
log.Printf("new paste: %s", id)
totalPastes.Inc()
switch r.Header.Get("Accept") {
case "text/plain":
w.WriteHeader(http.StatusOK)
@ -460,7 +475,7 @@ WHERE id = $1 AND user_id = $2
s.ShowError(w, r, err, http.StatusInternalServerError)
return
}
totalPastes.Dec()
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
}
@ -470,11 +485,12 @@ func (s *Server) ShowPost(w http.ResponseWriter, r *http.Request) {
if ui != nil {
up = ui.UserProfile
}
origin := "tailnet"
if valAny := r.Context().Value(privacyKey); valAny != nil {
if val, ok := valAny.(mixedCriticalityHandlerCtxKey); ok {
if val == isFunnel {
up = nil
origin = "public"
}
}
}
@ -572,6 +588,9 @@ WHERE p.id = $1`
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, data)
pasteViews.With(prometheus.Labels{"id": id, "origin": origin, "type": "raw"}).Inc()
return
// download file to disk (plain text view plus download hint)
case "dl":
@ -581,6 +600,8 @@ WHERE p.id = $1`
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, data)
pasteViews.With(prometheus.Labels{"id": id, "origin": origin, "type": "download"}).Inc()
return
case "":
// view markdown file with a fancy HTML rendering step
@ -603,6 +624,7 @@ WHERE p.id = $1`
title = ogTitle
}
}
pasteViews.With(prometheus.Labels{"id": id, "origin": origin, "type": "fancy"}).Inc()
err = s.tmpls.ExecuteTemplate(w, "fancypost.html", struct {
Title string
@ -635,6 +657,8 @@ WHERE p.id = $1`
remoteUserID = up.ID
}
pasteViews.With(prometheus.Labels{"id": id, "origin": origin, "type": "normal"}).Inc()
err = s.tmpls.ExecuteTemplate(w, "showpaste.html", struct {
UserInfo *tailcfg.UserProfile
Title string
@ -693,6 +717,17 @@ func main() {
}
defer db.Close()
if *enableMetrics {
q := `
SELECT count(*)
FROM pastes
`
var pastes float64
// Execute query using 'id' and place value into 'output'
db.QueryRow(q).Scan(&pastes)
totalPastes.Set(pastes)
}
lc, err := s.LocalClient()
if err != nil {
log.Fatal(err)
@ -736,6 +771,11 @@ func main() {
tailnetMux.HandleFunc("/", srv.TailnetIndex)
tailnetMux.HandleFunc("/help", srv.TailnetHelp)
if *enableMetrics {
tailnetMux.Handle("/metrics", promhttp.Handler())
log.Printf("metrics enabled on /metrics")
}
funnelMux := http.NewServeMux()
funnelMux.Handle("/static/", http.FileServer(http.FS(staticFiles)))
funnelMux.HandleFunc("/", srv.PublicIndex)

View file

@ -24,7 +24,7 @@
go = pkgs.go;
src = ./.;
subPackages = "cmd/tclipd";
vendorHash = "sha256-Ho39aNWTbygA46/9lkXRVLV6FLkWenAJKxOE3MJUb2M=";
vendorHash = "sha256-nxKlKxpr7PZhDLk/J3TBjdhLjy7EYqmMGF+y4hgRgRQ=";
};
tclip = pkgs.buildGo122Module {

7
go.mod
View file

@ -34,6 +34,8 @@ require (
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
github.com/aws/smithy-go v1.19.0 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/coreos/go-iptables v0.7.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
@ -68,6 +70,10 @@ require (
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/safchain/ethtool v0.3.0 // indirect
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect
@ -98,6 +104,7 @@ require (
golang.org/x/tools v0.17.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gvisor.dev/gvisor v0.0.0-20240306221502-ee1e1f6070e3 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.41.0 // indirect

14
go.sum
View file

@ -40,6 +40,10 @@ github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM=
github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
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.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4=
github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8=
@ -158,6 +162,14 @@ github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
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.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
@ -251,6 +263,8 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=