@@ -59,36 +59,48 @@ type StreamRetentionData []struct {
59
59
Duration string `json:"duration"`
60
60
}
61
61
62
- // StreamAlertData is the data structure for stream alerts
63
- type StreamAlertData struct {
64
- Alerts []struct {
65
- Message string `json:"message"`
66
- Name string `json:"name"`
67
- Rule struct {
68
- Config struct {
69
- Column string `json:"column"`
70
- Operator string `json:"operator"`
71
- Repeats int `json:"repeats"`
72
- Value int `json:"value"`
73
- } `json:"config"`
74
- Type string `json:"type"`
75
- } `json:"rule"`
76
- Targets []struct {
77
- Endpoint string `json:"endpoint"`
78
- Password string `json:"password,omitempty"`
79
- Repeat struct {
80
- Interval string `json:"interval"`
81
- Times int `json:"times"`
82
- } `json:"repeat"`
83
- SkipTLSCheck bool `json:"skip_tls_check,omitempty"`
84
- Type string `json:"type"`
85
- Username string `json:"username,omitempty"`
86
- Headers struct {
87
- Authorization string `json:"Authorization"`
88
- } `json:"headers,omitempty"`
89
- } `json:"targets"`
90
- } `json:"alerts"`
91
- Version string `json:"version"`
62
+ // AlertConfig structure
63
+ type AlertConfig struct {
64
+ Version string `json:"version"`
65
+ Alerts []Alert `json:"alerts"`
66
+ }
67
+
68
+ // Alert structure
69
+ type Alert struct {
70
+ Targets []Target `json:"targets"`
71
+ Name string `json:"name"`
72
+ Message string `json:"message"`
73
+ Rule Rule `json:"rule"`
74
+ }
75
+
76
+ // Target structure
77
+ type Target struct {
78
+ Type string `json:"type"`
79
+ Endpoint string `json:"endpoint"`
80
+ Headers map [string ]string `json:"headers"`
81
+ SkipTLSCheck bool `json:"skip_tls_check"`
82
+ Repeat Repeat `json:"repeat"`
83
+ }
84
+
85
+ // Repeat structure
86
+ type Repeat struct {
87
+ Interval string `json:"interval"`
88
+ Times int `json:"times"`
89
+ }
90
+
91
+ // Rule structure
92
+ type Rule struct {
93
+ Type string `json:"type"`
94
+ Config RuleConfig `json:"config"`
95
+ }
96
+
97
+ // RuleConfig structure
98
+ type RuleConfig struct {
99
+ Column string `json:"column"`
100
+ Operator string `json:"operator"`
101
+ IgnoreCase bool `json:"ignoreCase"`
102
+ Value interface {} `json:"value"`
103
+ Repeats int `json:"repeats"`
92
104
}
93
105
94
106
// AddStreamCmd is the parent command for stream
@@ -132,10 +144,11 @@ var StatStreamCmd = &cobra.Command{
132
144
Example : " pb stream info backend_logs" ,
133
145
Short : "Get statistics for a stream" ,
134
146
Args : cobra .ExactArgs (1 ),
135
- RunE : func (_ * cobra.Command , args []string ) error {
147
+ RunE : func (cmd * cobra.Command , args []string ) error {
136
148
name := args [0 ]
137
149
client := DefaultClient ()
138
150
151
+ // Fetch stats data
139
152
stats , err := fetchStats (& client , name )
140
153
if err != nil {
141
154
return err
@@ -144,68 +157,96 @@ var StatStreamCmd = &cobra.Command{
144
157
ingestionCount := stats .Ingestion .Count
145
158
ingestionSize , _ := strconv .Atoi (strings .TrimRight (stats .Ingestion .Size , " Bytes" ))
146
159
storageSize , _ := strconv .Atoi (strings .TrimRight (stats .Storage .Size , " Bytes" ))
160
+ compressionRatio := 100 - (float64 (storageSize ) / float64 (ingestionSize ) * 100 )
147
161
162
+ // Fetch retention data
148
163
retention , err := fetchRetention (& client , name )
149
164
if err != nil {
150
165
return err
151
166
}
152
167
153
- isRetentionSet := len (retention ) > 0
154
-
155
- fmt .Println (StyleBold .Render ("\n Info:" ))
156
- fmt .Printf (" Event Count: %d\n " , ingestionCount )
157
- fmt .Printf (" Ingestion Size: %s\n " , humanize .Bytes (uint64 (ingestionSize )))
158
- fmt .Printf (" Storage Size: %s\n " , humanize .Bytes (uint64 (storageSize )))
159
- fmt .Printf (
160
- " Compression Ratio: %.2f%s\n " ,
161
- 100 - (float64 (storageSize )/ float64 (ingestionSize ))* 100 , "%" )
162
- fmt .Println ()
163
-
164
- if isRetentionSet {
165
- fmt .Println (StyleBold .Render ("Retention:" ))
166
- for _ , item := range retention {
167
- fmt .Printf (" Action: %s\n " , StyleBold .Render (item .Action ))
168
- fmt .Printf (" Duration: %s\n " , StyleBold .Render (item .Duration ))
169
- fmt .Println ()
170
- }
171
- } else {
172
- fmt .Println (StyleBold .Render ("No retention period set on stream\n " ))
173
- }
174
-
168
+ // Fetch alerts data
175
169
alertsData , err := fetchAlerts (& client , name )
176
170
if err != nil {
177
171
return err
178
172
}
179
- alerts := alertsData .Alerts
180
-
181
- isAlertsSet := len (alerts ) > 0
182
-
183
- if isAlertsSet {
184
- fmt .Println (StyleBold .Render ("Alerts:" ))
185
- for _ , alert := range alerts {
186
- fmt .Printf (" Alert: %s\n " , StyleBold .Render (alert .Name ))
187
- ruleFmt := fmt .Sprintf (
188
- "%s %s %s repeated %d times" ,
189
- alert .Rule .Config .Column ,
190
- alert .Rule .Config .Operator ,
191
- fmt .Sprint (alert .Rule .Config .Value ),
192
- alert .Rule .Config .Repeats ,
193
- )
194
- fmt .Printf (" Rule: %s\n " , ruleFmt )
195
- fmt .Printf (" Targets: " )
196
- for _ , target := range alert .Targets {
197
- fmt .Printf ("%s, " , target .Type )
198
- }
199
- fmt .Print ("\n \n " )
173
+
174
+ // Check output format
175
+ output , _ := cmd .Flags ().GetString ("output" )
176
+ if output == "json" {
177
+ // Prepare JSON response
178
+ data := map [string ]interface {}{
179
+ "info" : map [string ]interface {}{
180
+ "event_count" : ingestionCount ,
181
+ "ingestion_size" : humanize .Bytes (uint64 (ingestionSize )),
182
+ "storage_size" : humanize .Bytes (uint64 (storageSize )),
183
+ "compression_ratio" : fmt .Sprintf ("%.2f%%" , compressionRatio ),
184
+ },
185
+ "retention" : retention ,
186
+ "alerts" : alertsData .Alerts ,
187
+ }
188
+
189
+ jsonData , err := json .MarshalIndent (data , "" , " " )
190
+ if err != nil {
191
+ return err
200
192
}
193
+ fmt .Println (string (jsonData ))
201
194
} else {
202
- fmt .Println (StyleBold .Render ("No alerts set on stream\n " ))
195
+ // Default text output
196
+ isRetentionSet := len (retention ) > 0
197
+ isAlertsSet := len (alertsData .Alerts ) > 0
198
+
199
+ fmt .Println (StyleBold .Render ("\n Info:" ))
200
+ fmt .Printf (" Event Count: %d\n " , ingestionCount )
201
+ fmt .Printf (" Ingestion Size: %s\n " , humanize .Bytes (uint64 (ingestionSize )))
202
+ fmt .Printf (" Storage Size: %s\n " , humanize .Bytes (uint64 (storageSize )))
203
+ fmt .Printf (
204
+ " Compression Ratio: %.2f%s\n " ,
205
+ compressionRatio , "%" )
206
+ fmt .Println ()
207
+
208
+ if isRetentionSet {
209
+ fmt .Println (StyleBold .Render ("Retention:" ))
210
+ for _ , item := range retention {
211
+ fmt .Printf (" Action: %s\n " , StyleBold .Render (item .Action ))
212
+ fmt .Printf (" Duration: %s\n " , StyleBold .Render (item .Duration ))
213
+ fmt .Println ()
214
+ }
215
+ } else {
216
+ fmt .Println (StyleBold .Render ("No retention period set on stream\n " ))
217
+ }
218
+
219
+ if isAlertsSet {
220
+ fmt .Println (StyleBold .Render ("Alerts:" ))
221
+ for _ , alert := range alertsData .Alerts {
222
+ fmt .Printf (" Alert: %s\n " , StyleBold .Render (alert .Name ))
223
+ ruleFmt := fmt .Sprintf (
224
+ "%s %s %s repeated %d times" ,
225
+ alert .Rule .Config .Column ,
226
+ alert .Rule .Config .Operator ,
227
+ fmt .Sprint (alert .Rule .Config .Value ),
228
+ alert .Rule .Config .Repeats ,
229
+ )
230
+ fmt .Printf (" Rule: %s\n " , ruleFmt )
231
+ fmt .Printf (" Targets: " )
232
+ for _ , target := range alert .Targets {
233
+ fmt .Printf ("%s, " , target .Type )
234
+ }
235
+ fmt .Print ("\n \n " )
236
+ }
237
+ } else {
238
+ fmt .Println (StyleBold .Render ("No alerts set on stream\n " ))
239
+ }
203
240
}
204
241
205
242
return nil
206
243
},
207
244
}
208
245
246
+ func init () {
247
+ StatStreamCmd .Flags ().String ("output" , "text" , "Output format: text or json" )
248
+ }
249
+
209
250
var RemoveStreamCmd = & cobra.Command {
210
251
Use : "remove stream-name" ,
211
252
Aliases : []string {"rm" },
@@ -345,7 +386,7 @@ func fetchRetention(client *HTTPClient, name string) (data StreamRetentionData,
345
386
return
346
387
}
347
388
348
- func fetchAlerts (client * HTTPClient , name string ) (data StreamAlertData , err error ) {
389
+ func fetchAlerts (client * HTTPClient , name string ) (data AlertConfig , err error ) {
349
390
req , err := client .NewRequest ("GET" , fmt .Sprintf ("logstream/%s/alert" , name ), nil )
350
391
if err != nil {
351
392
return
0 commit comments