watch-tool/patterns/repository.go

87 lines
1.7 KiB
Go

package patterns
import (
"fmt"
"os"
"regexp"
"sync"
"gopkg.in/yaml.v3"
)
type Config struct {
Patterns map[string]ServiceConfig `yaml:"patterns"`
}
type ServiceConfig struct {
Extractors []ExtractorConfig `yaml:"extractors"`
}
type ExtractorConfig struct {
Name string `yaml:"name"`
Regex string `yaml:"regex"`
Fields map[string]string `yaml:"fields"`
}
type CompiledExtractor struct {
Name string
Pattern *regexp.Regexp
Fields map[string]string
}
type Repository struct {
services map[string][]CompiledExtractor
mu sync.RWMutex
}
var (
instance *Repository
once sync.Once
)
func GetInstance() *Repository {
once.Do(func() {
instance = &Repository{
services: make(map[string][]CompiledExtractor),
}
})
return instance
}
func (r *Repository) Load(path string) error {
r.mu.Lock()
defer r.mu.Unlock()
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("failed to read patterns file: %w", err)
}
var cfg Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return fmt.Errorf("failed to parse yaml: %w", err)
}
for service, svcCfg := range cfg.Patterns {
var compiledList []CompiledExtractor
for _, ext := range svcCfg.Extractors {
re, err := regexp.Compile(ext.Regex)
if err != nil {
return fmt.Errorf("invalid regex in service %s extractor %s: %w", service, ext.Name, err)
}
compiledList = append(compiledList, CompiledExtractor{
Name: ext.Name,
Pattern: re,
Fields: ext.Fields,
})
}
r.services[service] = compiledList
}
return nil
}
func (r *Repository) GetExtractors(service string) []CompiledExtractor {
r.mu.RLock()
defer r.mu.RUnlock()
return r.services[service]
}