diff --git a/handlers.go b/handlers.go index 045b7bca5..bd60c544e 100644 --- a/handlers.go +++ b/handlers.go @@ -106,7 +106,11 @@ func newFalcoPayload(payload io.Reader) (types.FalcoPayload, error) { nullClient.CountMetric("falco.accepted", 1, []string{"priority:" + falcopayload.Priority.String()}) stats.Falco.Add(strings.ToLower(falcopayload.Priority.String()), 1) - promStats.Falco.With(map[string]string{"rule": falcopayload.Rule, "priority": falcopayload.Priority.String(), "k8s_ns_name": kn, "k8s_pod_name": kp}).Inc() + promLabels := map[string]string{"rule": falcopayload.Rule, "priority": falcopayload.Priority.String(), "k8s_ns_name": kn, "k8s_pod_name": kp} + for key, value := range config.Customfields { + promLabels[key] = value + } + promStats.Falco.With(promLabels).Inc() if config.Debug == true { body, _ := json.Marshal(falcopayload) diff --git a/main.go b/main.go index 4b565d34d..9e97b7281 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "net/http" + "os" "strings" "github.com/DataDog/datadog-go/statsd" @@ -60,9 +61,16 @@ var ( ) func init() { + // detect unit testing and skip init. + // see: https://github.com/alecthomas/kingpin/issues/187 + testing := (strings.HasSuffix(os.Args[0], ".test") || + strings.HasSuffix(os.Args[0], "__debug_bin")) + if testing { + return + } config = getConfig() stats = getInitStats() - promStats = getInitPromStats() + promStats = getInitPromStats(config) nullClient = &outputs.Client{ OutputType: "null", diff --git a/stats_prometheus.go b/stats_prometheus.go index daf6a43d3..a898d5615 100644 --- a/stats_prometheus.go +++ b/stats_prometheus.go @@ -1,15 +1,18 @@ package main import ( + "log" + "regexp" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/falcosecurity/falcosidekick/types" ) -func getInitPromStats() *types.PromStatistics { +func getInitPromStats(config *types.Configuration) *types.PromStatistics { promStats = &types.PromStatistics{ - Falco: getFalcoNewCounterVec(), + Falco: getFalcoNewCounterVec(config), Inputs: getInputNewCounterVec(), Outputs: getOutputNewCounterVec(), } @@ -34,16 +37,27 @@ func getOutputNewCounterVec() *prometheus.CounterVec { ) } -func getFalcoNewCounterVec() *prometheus.CounterVec { +func getFalcoNewCounterVec(config *types.Configuration) *prometheus.CounterVec { + labelnames := []string{ + "rule", + "priority", + "k8s_ns_name", + "k8s_pod_name", + } + for key := range config.Customfields { + matched, err := regexp.MatchString("^[a-zA-Z_:][a-zA-Z0-9_:]*$", key) + if err != nil { + log.Printf("Error matching prometheus label from custom fields. Err: %s", err) + continue + } + if matched { + labelnames = append(labelnames, key) + } + } return promauto.NewCounterVec( prometheus.CounterOpts{ Name: "falco_events", }, - []string{ - "rule", - "priority", - "k8s_ns_name", - "k8s_pod_name", - }, + labelnames, ) } diff --git a/stats_prometheus_test.go b/stats_prometheus_test.go new file mode 100644 index 000000000..58c122dbc --- /dev/null +++ b/stats_prometheus_test.go @@ -0,0 +1,26 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/falcosecurity/falcosidekick/types" +) + +func TestFalcoNewCounterVec(t *testing.T) { + c := &types.Configuration{ + Customfields: make(map[string]string), + } + c.Customfields["test"] = "foo" + c.Customfields["should*fail"] = "bar" + + cv := getFalcoNewCounterVec(c) + shouldbe := []string{"rule", "priority", "k8s_ns_name", "k8s_pod_name", "test"} + mm, err := cv.GetMetricWithLabelValues(shouldbe...) + if err != nil { + t.Errorf("Error getting Metrics from promauto") + } + metricDescString := mm.Desc().String() + require.Equal(t, metricDescString, "Desc{fqName: \"falco_events\", help: \"\", constLabels: {}, variableLabels: [rule priority k8s_ns_name k8s_pod_name test]}") +}