mirror of
https://github.com/Icinga/icingabeat.git
synced 2025-08-15 14:58:08 +02:00
137 lines
3.6 KiB
Go
137 lines
3.6 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/elastic/go-ucfg/yaml"
|
|
)
|
|
|
|
//This reflects allowed attributes for field definitions in the fields.yml.
|
|
//No logic is put into this data structure.
|
|
//The purpose is to enable using different kinds of transformation, on top of the same data structure.
|
|
//Current transformation:
|
|
// -ElasticSearch Template
|
|
// -Kibana Index Pattern
|
|
|
|
type Fields []Field
|
|
|
|
type Field struct {
|
|
Name string `config:"name"`
|
|
Type string `config:"type"`
|
|
Description string `config:"description"`
|
|
Format string `config:"format"`
|
|
ScalingFactor int `config:"scaling_factor"`
|
|
Fields Fields `config:"fields"`
|
|
MultiFields Fields `config:"multi_fields"`
|
|
ObjectType string `config:"object_type"`
|
|
Enabled *bool `config:"enabled"`
|
|
Analyzer string `config:"analyzer"`
|
|
SearchAnalyzer string `config:"search_analyzer"`
|
|
Norms bool `config:"norms"`
|
|
Dynamic DynamicType `config:"dynamic"`
|
|
Index *bool `config:"index"`
|
|
DocValues *bool `config:"doc_values"`
|
|
CopyTo string `config:"copy_to"`
|
|
|
|
// Kibana specific
|
|
Analyzed *bool `config:"analyzed"`
|
|
Count int `config:"count"`
|
|
Searchable *bool `config:"searchable"`
|
|
Aggregatable *bool `config:"aggregatable"`
|
|
Script string `config:"script"`
|
|
// Kibana params
|
|
Pattern string `config:"pattern"`
|
|
InputFormat string `config:"input_format"`
|
|
OutputFormat string `config:"output_format"`
|
|
OutputPrecision *int `config:"output_precision"`
|
|
LabelTemplate string `config:"label_template"`
|
|
UrlTemplate []VersionizedString `config:"url_template"`
|
|
OpenLinkInCurrentTab *bool `config:"open_link_in_current_tab"`
|
|
|
|
Path string
|
|
}
|
|
|
|
type VersionizedString struct {
|
|
MinVersion string `config:"min_version"`
|
|
Value string `config:"value"`
|
|
}
|
|
|
|
type DynamicType struct{ Value interface{} }
|
|
|
|
func (d *DynamicType) Unpack(s string) error {
|
|
switch s {
|
|
case "true":
|
|
d.Value = true
|
|
case "false":
|
|
d.Value = false
|
|
case "strict":
|
|
d.Value = s
|
|
default:
|
|
return fmt.Errorf("'%v' is invalid dynamic setting", s)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func LoadFieldsYaml(path string) (Fields, error) {
|
|
keys := []Field{}
|
|
|
|
cfg, err := yaml.NewConfigWithFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cfg.Unpack(&keys)
|
|
|
|
fields := Fields{}
|
|
|
|
for _, key := range keys {
|
|
fields = append(fields, key.Fields...)
|
|
}
|
|
return fields, nil
|
|
}
|
|
|
|
// HasKey checks if inside fields the given key exists
|
|
// The key can be in the form of a.b.c and it will check if the nested field exist
|
|
// In case the key is `a` and there is a value `a.b` false is return as it only
|
|
// returns true if it's a leave node
|
|
func (f Fields) HasKey(key string) bool {
|
|
keys := strings.Split(key, ".")
|
|
return f.hasKey(keys)
|
|
}
|
|
|
|
// Recursively generates the correct key based on the dots
|
|
// The mapping requires "properties" between each layer. This is added here.
|
|
func GenerateKey(key string) string {
|
|
if strings.Contains(key, ".") {
|
|
keys := strings.SplitN(key, ".", 2)
|
|
key = keys[0] + ".properties." + GenerateKey(keys[1])
|
|
}
|
|
return key
|
|
}
|
|
|
|
func (f Fields) hasKey(keys []string) bool {
|
|
// Nothing to compare anymore
|
|
if len(keys) == 0 {
|
|
return false
|
|
}
|
|
|
|
key := keys[0]
|
|
keys = keys[1:]
|
|
|
|
for _, field := range f {
|
|
if field.Name == key {
|
|
|
|
if len(field.Fields) > 0 {
|
|
return field.Fields.hasKey(keys)
|
|
}
|
|
// Last entry in the tree but still more keys
|
|
if len(keys) > 0 {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|