monitoring/adapter/filters.go (106 lines of code) (raw):
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package adapter
import (
"strings"
"github.com/elastic/elastic-agent-libs/monitoring"
"github.com/elastic/elastic-agent-libs/str"
)
// provide filters for filtering and adapting a metric type
// to monitoring.Var.
// MetricFilter type used to defined and combine filters.
type MetricFilter func(*metricFilters) *metricFilters
// metricFilters provides set of filters to apply to a new metric.
type metricFilters struct {
filters []varFilter
}
type varFilter func(state) state
// state provides the filter state to be changed by every filter.
//
// After filtering the state will be used to choose on the metric name, the
// metric type , or wether the metric is to be ignored.
type state struct {
kind kind
action action
mode monitoring.Mode
reg *monitoring.Registry
name string
metric interface{}
}
// action defines the action to be
type action uint8
// kind defines the kind of operation to be executed
type kind uint8
const (
kndFind kind = iota
kndAdd
kndRemove
)
const (
actIgnore action = iota
actAccept
)
func makeFilters(in ...MetricFilter) *metricFilters {
if len(in) == 0 {
return nil
}
m := &metricFilters{}
for _, mk := range in {
m = mk(m)
}
return m
}
func (m *metricFilters) apply(st state) state {
if m != nil {
for _, filter := range m.filters {
st = filter(st)
}
}
return st
}
func ApplyIf(pred func(name string) bool, filters ...MetricFilter) MetricFilter {
then := makeFilters(filters...)
return withVarFilter(func(st state) state {
if pred(st.name) {
st = then.apply(st)
}
return st
})
}
var Accept = withVarFilter(func(st state) state {
st.action = actAccept
return st
})
// WhitelistIf will accept a metric if the metrics name matches
// the given predicate.
func WhitelistIf(pred func(string) bool) MetricFilter {
return ApplyIf(pred, Accept)
}
// NameIn checks a metrics name matching any of the set names
func NameIn(names ...string) func(string) bool {
return str.MakeSet(names...).Has
}
// Whitelist sets a list of metric names to be accepted.
func Whitelist(names ...string) MetricFilter {
return WhitelistIf(NameIn(names...))
}
// ReportIf sets variable report mode for all metrics satisfying the predicate.
func ReportIf(pred func(string) bool) MetricFilter {
return ApplyIf(pred, withVarFilter(func(st state) state {
st.mode = monitoring.Reported
return st
}))
}
// ReportNames enables reporting for all metrics matching any of the given names.
func ReportNames(names ...string) MetricFilter {
return ReportIf(NameIn(names...))
}
// ModifyName changes a metric its name using the provided
// function.
func ModifyName(f func(string) string) MetricFilter {
return withVarFilter(func(st state) state {
st.name = f(st.name)
return st
})
}
// Rename renames a metric to `to`, if the names matches `from`
// If the name matches, it will be automatically white-listed.
func Rename(from, to string) MetricFilter {
return withVarFilter(func(st state) state {
if st.name == from {
st.action, st.name = actAccept, to
}
return st
})
}
// NameReplace replaces substrings in a metrics names with `new`.
func NameReplace(old, new string) MetricFilter {
return ModifyName(func(name string) string {
return strings.Replace(name, old, new, -1)
})
}
// ToLowerName converts all metric names to lower-case
var ToLowerName = ModifyName(strings.ToLower)
// ToUpperName converts all metric name to upper-case
var ToUpperName = ModifyName(strings.ToUpper)
// withVarFilter lifts a varFilter into a MetricFilter
func withVarFilter(f varFilter) MetricFilter {
return func(m *metricFilters) *metricFilters {
m.filters = append(m.filters, f)
return m
}
}