feat: add responseWrapper to exclude errors (status codes >= 400) from being reported
This commit is contained in:
parent
02f9dd951c
commit
a978d4921d
4 changed files with 78 additions and 6 deletions
|
|
@ -86,6 +86,7 @@ entryPoints:
|
|||
|---------------------|-------------|------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `disabled` | false | `bool` | Set to `true` to disable the plugin |
|
||||
| `debug` | false | `bool` | Something doesn't work? Set to `true` to see more logs (plugins doesn't have access to Traefik's log level) |
|
||||
| `queueSize` | 1000 | `int` | The maximum number of events that can be queued before they are sent to the Umami server |
|
||||
| `umamiHost` | - | `string` | Umami server url, reachable from within traefik (container), e.g. `http://umami:3000` |
|
||||
| `umamiToken` | - | `string` | An API Token, used to automatize work with websites, not needed if you provide `websites` |
|
||||
| `umamiUsername` | - | `string` | An alternative to `umamiToken`, you can provide an username and password |
|
||||
|
|
@ -93,6 +94,7 @@ entryPoints:
|
|||
| `umamiTeamId` | - | `string` | In order to organize websites, you can use Umami Teams |
|
||||
| `websites` | - | `map` | A map of hostnames and their associated Umami IDs. Can also be used to override or extend fetched websites |
|
||||
| `createNewWebsites` | false | `bool` | If set to `true`, will try to create a new website on Umami, if domain not found there |
|
||||
| `trackErrors` | false | `bool` | If set to `true`, will track errors (status codes >= 400) |
|
||||
| `trackAllResources` | false | `bool` | Defines whether all requests for any resource should be tracked. By default, only requests that are believed to contain content are tracked |
|
||||
| `trackExtensions` | | `string[]` | Defines an alternative list of file extensions that should be tracked |
|
||||
| `ignoreUserAgents` | | `string[]` | A list of user agents that should be ignored from tracking, e.g. `["Googlebot", "Uptime-Kuma"]` (matched with `strings.Contains`) |
|
||||
|
|
|
|||
44
responsewriter.go
Normal file
44
responsewriter.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package traefik_umami_feeder
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Copied and adapted from https://github.com/safing/plausiblefeeder/blob/master/responsewriter.go
|
||||
// Licensed as MIT license
|
||||
|
||||
// ResponseWriter is used to wrap given response writers.
|
||||
type ResponseWriter struct {
|
||||
http.ResponseWriter
|
||||
|
||||
request *http.Request
|
||||
feeder *UmamiFeeder
|
||||
}
|
||||
|
||||
// WriteHeader adds custom handling to the wrapped WriterHeader method.
|
||||
func (rw *ResponseWriter) WriteHeader(code int) {
|
||||
if rw.feeder.shouldTrackStatus(code) {
|
||||
rw.feeder.submitToFeed(rw.request, code)
|
||||
}
|
||||
|
||||
// Continue with the original method.
|
||||
rw.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
hijacker, ok := rw.ResponseWriter.(http.Hijacker)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("%T is not a http.Hijacker", rw.ResponseWriter)
|
||||
}
|
||||
|
||||
return hijacker.Hijack()
|
||||
}
|
||||
|
||||
func (rw *ResponseWriter) Flush() {
|
||||
if flusher, ok := rw.ResponseWriter.(http.Flusher); ok {
|
||||
flusher.Flush()
|
||||
}
|
||||
}
|
||||
36
umami.go
36
umami.go
|
|
@ -20,7 +20,7 @@ type Config struct {
|
|||
// Debug enables debug logging, be prepared for flooding.
|
||||
Debug bool `json:"debug"`
|
||||
// QueueSize defines the size of queue, i.e. the amount of events that are waiting to be submitted to Umami.
|
||||
QueueSize int
|
||||
QueueSize int `json:"queueSize"`
|
||||
|
||||
// UmamiHost is the URL of the Umami instance.
|
||||
UmamiHost string `json:"umamiHost"`
|
||||
|
|
@ -39,6 +39,8 @@ type Config struct {
|
|||
// CreateNewWebsites when set to true, the plugin will create new websites using API, UmamiToken is required.
|
||||
CreateNewWebsites bool `json:"createNewWebsites"`
|
||||
|
||||
// TrackErrors defines whether errors (status codes >= 400) should be tracked.
|
||||
TrackErrors bool `json:"trackErrors"`
|
||||
// TrackAllResources defines whether all requests for any resource should be tracked.
|
||||
// By default, only requests that are believed to contain content are tracked.
|
||||
TrackAllResources bool `json:"trackAllResources"`
|
||||
|
|
@ -58,9 +60,10 @@ type Config struct {
|
|||
// CreateConfig creates the default plugin configuration.
|
||||
func CreateConfig() *Config {
|
||||
return &Config{
|
||||
Disabled: false,
|
||||
Debug: false,
|
||||
QueueSize: 1000,
|
||||
Disabled: false,
|
||||
Debug: false,
|
||||
QueueSize: 1000,
|
||||
TrackErrors: false,
|
||||
|
||||
UmamiHost: "",
|
||||
UmamiToken: "",
|
||||
|
|
@ -96,6 +99,7 @@ type UmamiFeeder struct {
|
|||
websites map[string]string
|
||||
createNewWebsites bool
|
||||
|
||||
trackErrors bool
|
||||
trackAllResources bool
|
||||
trackExtensions []string
|
||||
|
||||
|
|
@ -123,6 +127,7 @@ func New(ctx context.Context, next http.Handler, config *Config, name string) (h
|
|||
websites: config.Websites,
|
||||
createNewWebsites: config.CreateNewWebsites,
|
||||
|
||||
trackErrors: config.TrackErrors,
|
||||
trackAllResources: config.TrackAllResources,
|
||||
trackExtensions: config.TrackExtensions,
|
||||
|
||||
|
|
@ -225,7 +230,16 @@ func (h *UmamiFeeder) verifyConfig(config *Config) error {
|
|||
|
||||
func (h *UmamiFeeder) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if !h.isDisabled && h.shouldTrack(req) {
|
||||
h.submitToFeed(req)
|
||||
// If the resource should be reported, we wrap the response writer and check the status code before reporting
|
||||
wrappedResponseWriter := &ResponseWriter{
|
||||
ResponseWriter: rw,
|
||||
request: req,
|
||||
feeder: h,
|
||||
}
|
||||
|
||||
// Continue with next handler.
|
||||
h.next.ServeHTTP(wrappedResponseWriter, req)
|
||||
return
|
||||
}
|
||||
|
||||
h.next.ServeHTTP(rw, req)
|
||||
|
|
@ -316,6 +330,18 @@ func (h *UmamiFeeder) shouldTrackResource(url string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (h *UmamiFeeder) shouldTrackStatus(statusCode int) (report bool) {
|
||||
if statusCode >= 400 {
|
||||
if h.trackErrors {
|
||||
return true
|
||||
}
|
||||
|
||||
h.debug("not reporting %d error", statusCode)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (h *UmamiFeeder) error(message string) {
|
||||
if h.logHandler != nil {
|
||||
now := time.Now().Format("2006-01-02T15:04:05Z")
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ var headersToCopy = []string{
|
|||
// Copied and adapted from https://github.com/safing/plausiblefeeder/blob/master/event.go
|
||||
// Licensed as MIT license
|
||||
|
||||
func (h *UmamiFeeder) submitToFeed(req *http.Request) {
|
||||
func (h *UmamiFeeder) submitToFeed(req *http.Request, code int) {
|
||||
body := SendBody{
|
||||
Payload: SendPayload{
|
||||
Hostname: parseDomainFromHost(req.Host),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue