master
go 106 lines 2.65 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package uwsgi
4
5 import (
6 "encoding/json"
7 "fmt"
8
9 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/oldmetrix"
10 )
11
12 type statsResponse struct {
13 Workers []workerStats `json:"workers"`
14 }
15
16 type workerStats struct {
17 ID int `json:"id"`
18 Accepting int64 `json:"accepting"`
19 Requests int64 `json:"requests"`
20 DeltaRequests int64 `json:"delta_requests"`
21 Exceptions int64 `json:"exceptions"`
22 HarakiriCount int64 `json:"harakiri_count"`
23 Status string `json:"status"`
24 RSS int64 `json:"rss"`
25 VSZ int64 `json:"vsz"`
26 RespawnCount int64 `json:"respawn_count"`
27 TX int64 `json:"tx"`
28 AvgRT int64 `json:"avg_rt"`
29 }
30
31 func (c *Collector) collect() (map[string]int64, error) {
32 stats, err := c.conn.queryStats()
33 if err != nil {
34 return nil, fmt.Errorf("failed to query stats: %v", err)
35 }
36
37 mx := make(map[string]int64)
38
39 if err := c.collectStats(mx, stats); err != nil {
40 return nil, err
41 }
42
43 return mx, nil
44 }
45
46 func (c *Collector) collectStats(mx map[string]int64, stats []byte) error {
47 var resp statsResponse
48 if err := json.Unmarshal(stats, &resp); err != nil {
49 return fmt.Errorf("failed to json decode stats response: %v", err)
50 }
51
52 // stats server returns an empty array if there are no workers
53 if resp.Workers == nil {
54 return fmt.Errorf("unexpected stats response: no workers found")
55 }
56
57 seen := make(map[int]bool)
58
59 mx["workers_tx"] = 0
60 mx["workers_requests"] = 0
61 mx["workers_harakiris"] = 0
62 mx["workers_exceptions"] = 0
63 mx["workers_respawns"] = 0
64
65 for _, w := range resp.Workers {
66 mx["workers_tx"] += w.TX
67 mx["workers_requests"] += w.Requests
68 mx["workers_harakiris"] += w.HarakiriCount
69 mx["workers_exceptions"] += w.Exceptions
70 mx["workers_respawns"] += w.RespawnCount
71
72 seen[w.ID] = true
73
74 if !c.seenWorkers[w.ID] {
75 c.seenWorkers[w.ID] = true
76 c.addWorkerCharts(w.ID)
77 }
78
79 px := fmt.Sprintf("worker_%d_", w.ID)
80
81 mx[px+"tx"] = w.TX
82 mx[px+"requests"] = w.Requests
83 mx[px+"delta_requests"] = w.DeltaRequests
84 mx[px+"average_request_time"] = w.AvgRT
85 mx[px+"harakiris"] = w.HarakiriCount
86 mx[px+"exceptions"] = w.Exceptions
87 mx[px+"respawns"] = w.RespawnCount
88 mx[px+"memory_rss"] = w.RSS
89 mx[px+"memory_vsz"] = w.VSZ
90
91 for _, v := range []string{"idle", "busy", "cheap", "pause", "sig"} {
92 mx[px+"status_"+v] = oldmetrix.Bool(w.Status == v)
93 }
94 mx[px+"request_handling_status_accepting"] = oldmetrix.Bool(w.Accepting == 1)
95 mx[px+"request_handling_status_not_accepting"] = oldmetrix.Bool(w.Accepting == 0)
96 }
97
98 for id := range c.seenWorkers {
99 if !seen[id] {
100 delete(c.seenWorkers, id)
101 c.removeWorkerCharts(id)
102 }
103 }
104
105 return nil
106 }