go.d icecast single source response (#18195)
Ilya Mashchenko committed
Jul 18, 2024 at 12:55 UTC
073e2d4110119fc254a12b1a0eb7fdfcacb79e7b
6 files changed
+116
-25
src/go/plugin/go.d/modules/icecast/collect.go
-13
@@ -11,19 +11,6 @@ import (
11
"github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
12
)
13
14
-type (
15
- serverStats struct {
16
- IceStats *struct {
17
- Source []sourceStats `json:"source"`
18
- } `json:"icestats"`
19
- }
20
- sourceStats struct {
21
- ServerName string `json:"server_name"`
22
- StreamStart string `json:"stream_start"`
23
- Listeners int64 `json:"listeners"`
24
- }
25
-)
26
-
14
const (
15
urlPathServerStats = "/status-json.xsl" // https://icecast.org/docs/icecast-trunk/server_stats/
16
)
src/go/plugin/go.d/modules/icecast/icecast_test.go
+44
-12
@@ -19,16 +19,18 @@ var (
19
dataConfigJSON, _ = os.ReadFile("testdata/config.json")
20
dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
21
22
- dataServerStats, _ = os.ReadFile("testdata/server_stats.json")
23
- dataServerStatsNoSources, _ = os.ReadFile("testdata/server_stats_no_sources.json")
22
+ dataServerStatsMultiSource, _ = os.ReadFile("testdata/stats_multi_source.json")
23
+ dataServerStatsSingleSource, _ = os.ReadFile("testdata/stats_single_source.json")
24
+ dataServerStatsNoSources, _ = os.ReadFile("testdata/stats_no_sources.json")
25
)
26
27
func Test_testDataIsValid(t *testing.T) {
28
for name, data := range map[string][]byte{
28
- "dataConfigJSON": dataConfigJSON,
29
- "dataConfigYAML": dataConfigYAML,
30
- "dataServerStats": dataServerStats,
31
- "dataServerStatsNoSources": dataServerStatsNoSources,
29
+ "dataConfigJSON": dataConfigJSON,
30
+ "dataConfigYAML": dataConfigYAML,
31
+ "dataServerStats": dataServerStatsMultiSource,
32
+ "dataServerStatsSingleSource": dataServerStatsSingleSource,
33
+ "dataServerStatsNoSources": dataServerStatsNoSources,
34
} {
35
require.NotNil(t, data, name)
36
}
@@ -80,9 +82,13 @@ func TestIcecast_Check(t *testing.T) {
82
wantFail bool
83
prepare func(t *testing.T) (*Icecast, func())
84
}{
83
- "success default config": {
85
+ "success multiple sources": {
86
wantFail: false,
85
- prepare: prepareCaseOk,
87
+ prepare: prepareCaseMultipleSources,
88
+ },
89
+ "success single source": {
90
+ wantFail: false,
91
+ prepare: prepareCaseMultipleSources,
92
},
93
"fails on no sources": {
94
wantFail: true,
@@ -122,14 +128,21 @@ func TestIcecast_Collect(t *testing.T) {
128
wantMetrics map[string]int64
129
wantCharts int
130
}{
125
- "success default config": {
126
- prepare: prepareCaseOk,
131
+ "success multiple sources": {
132
+ prepare: prepareCaseMultipleSources,
133
wantCharts: len(sourceChartsTmpl) * 2,
134
wantMetrics: map[string]int64{
135
"source_abc_listeners": 1,
136
"source_efg_listeners": 10,
137
},
138
},
139
+ "success single source": {
140
+ prepare: prepareCaseSingleSource,
141
+ wantCharts: len(sourceChartsTmpl) * 1,
142
+ wantMetrics: map[string]int64{
143
+ "source_abc_listeners": 1,
144
+ },
145
+ },
146
"fails on no sources": {
147
prepare: prepareCaseNoSources,
148
},
@@ -160,13 +173,32 @@ func TestIcecast_Collect(t *testing.T) {
173
}
174
}
175
163
-func prepareCaseOk(t *testing.T) (*Icecast, func()) {
176
+func prepareCaseMultipleSources(t *testing.T) (*Icecast, func()) {
177
+ t.Helper()
178
+ srv := httptest.NewServer(http.HandlerFunc(
179
+ func(w http.ResponseWriter, r *http.Request) {
180
+ switch r.URL.Path {
181
+ case urlPathServerStats:
182
+ _, _ = w.Write(dataServerStatsMultiSource)
183
+ default:
184
+ w.WriteHeader(http.StatusNotFound)
185
+ }
186
+ }))
187
+
188
+ icecast := New()
189
+ icecast.URL = srv.URL
190
+ require.NoError(t, icecast.Init())
191
+
192
+ return icecast, srv.Close
193
+}
194
+
195
+func prepareCaseSingleSource(t *testing.T) (*Icecast, func()) {
196
t.Helper()
197
srv := httptest.NewServer(http.HandlerFunc(
198
func(w http.ResponseWriter, r *http.Request) {
199
switch r.URL.Path {
200
case urlPathServerStats:
169
- _, _ = w.Write(dataServerStats)
201
+ _, _ = w.Write(dataServerStatsSingleSource)
202
default:
203
w.WriteHeader(http.StatusNotFound)
204
}
src/go/plugin/go.d/modules/icecast/server_stats.go
new
+45
@@ -0,0 +1,45 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package icecast
4
+
5
+import (
6
+ "encoding/json"
7
+ "fmt"
8
+)
9
+
10
+type (
11
+ serverStats struct {
12
+ IceStats *struct {
13
+ Source iceSource `json:"source"`
14
+ } `json:"icestats"`
15
+ }
16
+ iceSource []sourceStats
17
+ sourceStats struct {
18
+ ServerName string `json:"server_name"`
19
+ StreamStart string `json:"stream_start"`
20
+ Listeners int64 `json:"listeners"`
21
+ }
22
+)
23
+
24
+func (i *iceSource) UnmarshalJSON(data []byte) error {
25
+ var v any
26
+ if err := json.Unmarshal(data, &v); err != nil {
27
+ return err
28
+ }
29
+
30
+ switch v.(type) {
31
+ case []any:
32
+ type plain iceSource
33
+ return json.Unmarshal(data, (*plain)(i))
34
+ case map[string]any:
35
+ var s sourceStats
36
+ if err := json.Unmarshal(data, &s); err != nil {
37
+ return err
38
+ }
39
+ *i = []sourceStats{s}
40
+ default:
41
+ return fmt.Errorf("invalid source data type: expected array or object")
42
+ }
43
+
44
+ return nil
45
+}
src/go/plugin/go.d/modules/icecast/testdata/stats_multi_source.json
renamed
src/go/plugin/go.d/modules/icecast/testdata/stats_no_sources.json
renamed
src/go/plugin/go.d/modules/icecast/testdata/stats_single_source.json
new
+27
@@ -0,0 +1,27 @@
1
+{
2
+ "icestats": {
3
+ "admin": "icemaster@localhost",
4
+ "host": "localhost",
5
+ "location": "Earth",
6
+ "server_id": "Icecast 2.4.4",
7
+ "server_start": "Wed, 17 Jul 2024 11:27:40 +0300",
8
+ "server_start_iso8601": "2024-07-17T11:27:40+0300",
9
+ "source": {
10
+ "audio_info": "ice-bitrate=128;ice-channels=2;ice-samplerate=44100",
11
+ "genre": "(null)",
12
+ "ice-bitrate": 128,
13
+ "ice-channels": 2,
14
+ "ice-samplerate": 44100,
15
+ "listener_peak": 2,
16
+ "listeners": 1,
17
+ "listenurl": "http://localhost:8000/line.nsv",
18
+ "server_description": "(null)",
19
+ "server_name": "abc",
20
+ "server_type": "audio/mpeg",
21
+ "server_url": "(null)",
22
+ "stream_start": "Wed, 17 Jul 2024 12:10:20 +0300",
23
+ "stream_start_iso8601": "2024-07-17T12:10:20+0300",
24
+ "dummy": null
25
+ }
26
+ }
27
+}