@cryptotaxi247 / netdata-1 / commits / 073e2d411

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 +}