...
1 package metrics
2
3 import (
4 "context"
5 _ "embed"
6 "io/fs"
7 "maps"
8 "os"
9 "path/filepath"
10 "strings"
11
12 "gopkg.in/yaml.v3"
13 )
14
15 func NewYAMLMetricReaderWriter(ctx context.Context, path string) (ReaderWriter, error) {
16 if path == "" {
17 return NewDefaultMetricReader(ctx)
18 }
19 return &fileMetricReader{
20 ctx: ctx,
21 path: path,
22 }, nil
23 }
24
25 type fileMetricReader struct {
26 ctx context.Context
27 path string
28 }
29
30 func (fmr *fileMetricReader) WriteMetrics(metricDefs *Metrics) error {
31 yamlData, _ := yaml.Marshal(metricDefs)
32 return os.WriteFile(fmr.path, yamlData, 0644)
33 }
34
35
36 var defaultMetricsYAML []byte
37
38 func (fmr *fileMetricReader) GetMetrics() (metrics *Metrics, err error) {
39 metrics = &Metrics{MetricDefs{}, PresetDefs{}}
40 if fmr.path == "" {
41 err = yaml.Unmarshal(defaultMetricsYAML, metrics)
42 return
43 }
44
45 fi, err := os.Stat(fmr.path)
46 if err != nil {
47 return nil, err
48 }
49 switch mode := fi.Mode(); {
50 case mode.IsDir():
51 err = filepath.WalkDir(fmr.path, func(path string, d fs.DirEntry, err error) error {
52 if err != nil {
53 return err
54 }
55 ext := strings.ToLower(filepath.Ext(d.Name()))
56 if d.IsDir() || ext != ".yaml" && ext != ".yml" {
57 return nil
58 }
59 var m *Metrics
60 if m, err = fmr.getMetrics(path); err == nil {
61 maps.Copy(metrics.PresetDefs, m.PresetDefs)
62 maps.Copy(metrics.MetricDefs, m.MetricDefs)
63 }
64 return err
65 })
66 case mode.IsRegular():
67 metrics, err = fmr.getMetrics(fmr.path)
68 }
69 return
70 }
71
72 func (fmr *fileMetricReader) getMetrics(metricsFilePath string) (metrics *Metrics, err error) {
73 var yamlFile []byte
74 if yamlFile, err = os.ReadFile(metricsFilePath); err != nil {
75 return
76 }
77 metrics = &Metrics{MetricDefs{}, PresetDefs{}}
78 err = yaml.Unmarshal(yamlFile, &metrics)
79 return
80 }
81
82 func (fmr *fileMetricReader) DeleteMetric(metricName string) error {
83 metrics, err := fmr.GetMetrics()
84 if err != nil {
85 return err
86 }
87 delete(metrics.MetricDefs, metricName)
88 return fmr.WriteMetrics(metrics)
89 }
90
91 func (fmr *fileMetricReader) UpdateMetric(metricName string, metric Metric) error {
92 metrics, err := fmr.GetMetrics()
93 if err != nil {
94 return err
95 }
96 metrics.MetricDefs[metricName] = metric
97 return fmr.WriteMetrics(metrics)
98 }
99
100 func (fmr *fileMetricReader) CreateMetric(metricName string, metric Metric) error {
101 metrics, err := fmr.GetMetrics()
102 if err != nil {
103 return err
104 }
105
106 if _, exists := metrics.MetricDefs[metricName]; exists {
107 return ErrMetricExists
108 }
109 metrics.MetricDefs[metricName] = metric
110 return fmr.WriteMetrics(metrics)
111 }
112
113 func (fmr *fileMetricReader) DeletePreset(presetName string) error {
114 metrics, err := fmr.GetMetrics()
115 if err != nil {
116 return err
117 }
118 delete(metrics.PresetDefs, presetName)
119 return fmr.WriteMetrics(metrics)
120 }
121
122 func (fmr *fileMetricReader) UpdatePreset(presetName string, preset Preset) error {
123 metrics, err := fmr.GetMetrics()
124 if err != nil {
125 return err
126 }
127 metrics.PresetDefs[presetName] = preset
128 return fmr.WriteMetrics(metrics)
129 }
130
131 func (fmr *fileMetricReader) CreatePreset(presetName string, preset Preset) error {
132 metrics, err := fmr.GetMetrics()
133 if err != nil {
134 return err
135 }
136
137 if _, exists := metrics.PresetDefs[presetName]; exists {
138 return ErrPresetExists
139 }
140 metrics.PresetDefs[presetName] = preset
141 return fmr.WriteMetrics(metrics)
142 }
143