github.com/netdata/go.d.plugin@v0.58.1/modules/springboot2/springboot2.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package springboot2 4 5 import ( 6 _ "embed" 7 "strings" 8 "time" 9 10 "github.com/netdata/go.d.plugin/pkg/matcher" 11 12 mtx "github.com/netdata/go.d.plugin/pkg/metrics" 13 "github.com/netdata/go.d.plugin/pkg/prometheus" 14 "github.com/netdata/go.d.plugin/pkg/stm" 15 "github.com/netdata/go.d.plugin/pkg/web" 16 17 "github.com/netdata/go.d.plugin/agent/module" 18 ) 19 20 //go:embed "config_schema.json" 21 var configSchema string 22 23 func init() { 24 module.Register("springboot2", module.Creator{ 25 JobConfigSchema: configSchema, 26 Create: func() module.Module { return New() }, 27 }) 28 } 29 30 const ( 31 defaultHTTPTimeout = time.Second 32 ) 33 34 // New returns SpringBoot2 instance with default values 35 func New() *SpringBoot2 { 36 return &SpringBoot2{ 37 HTTP: web.HTTP{ 38 Client: web.Client{ 39 Timeout: web.Duration{Duration: defaultHTTPTimeout}, 40 }, 41 }, 42 } 43 } 44 45 // SpringBoot2 Spring boot 2 module 46 type SpringBoot2 struct { 47 module.Base 48 49 web.HTTP `yaml:",inline"` 50 URIFilter matcher.SimpleExpr `yaml:"uri_filter"` 51 52 uriFilter matcher.Matcher 53 54 prom prometheus.Prometheus 55 } 56 57 type metrics struct { 58 Uptime mtx.Gauge `stm:"uptime,1000"` 59 60 ThreadsDaemon mtx.Gauge `stm:"threads_daemon"` 61 Threads mtx.Gauge `stm:"threads"` 62 63 Resp1xx mtx.Counter `stm:"resp_1xx"` 64 Resp2xx mtx.Counter `stm:"resp_2xx"` 65 Resp3xx mtx.Counter `stm:"resp_3xx"` 66 Resp4xx mtx.Counter `stm:"resp_4xx"` 67 Resp5xx mtx.Counter `stm:"resp_5xx"` 68 69 HeapUsed heap `stm:"heap_used"` 70 HeapCommitted heap `stm:"heap_committed"` 71 72 MemFree mtx.Gauge `stm:"mem_free"` 73 } 74 75 type heap struct { 76 Eden mtx.Gauge `stm:"eden"` 77 Survivor mtx.Gauge `stm:"survivor"` 78 Old mtx.Gauge `stm:"old"` 79 } 80 81 // Cleanup Cleanup 82 func (SpringBoot2) Cleanup() {} 83 84 // Init makes initialization 85 func (s *SpringBoot2) Init() bool { 86 client, err := web.NewHTTPClient(s.Client) 87 if err != nil { 88 s.Error(err) 89 return false 90 } 91 s.uriFilter, err = s.URIFilter.Parse() 92 if err != nil && err != matcher.ErrEmptyExpr { 93 s.Error(err) 94 return false 95 } 96 s.prom = prometheus.New(client, s.Request) 97 return true 98 } 99 100 // Check makes check 101 func (s *SpringBoot2) Check() bool { 102 rawMetrics, err := s.prom.ScrapeSeries() 103 if err != nil { 104 s.Warning(err) 105 return false 106 } 107 jvmMemory := rawMetrics.FindByName("jvm_memory_used_bytes") 108 109 return len(jvmMemory) > 0 110 } 111 112 // Charts creates Charts 113 func (SpringBoot2) Charts() *Charts { 114 return charts.Copy() 115 } 116 117 // Collect collects metrics 118 func (s *SpringBoot2) Collect() map[string]int64 { 119 rawMetrics, err := s.prom.ScrapeSeries() 120 if err != nil { 121 return nil 122 } 123 124 var m metrics 125 126 // uptime 127 m.Uptime.Set(rawMetrics.FindByName("process_uptime_seconds").Max()) 128 129 // response 130 s.gatherResponse(rawMetrics, &m) 131 132 // threads 133 m.ThreadsDaemon.Set(rawMetrics.FindByNames("jvm_threads_daemon", "jvm_threads_daemon_threads").Max()) 134 m.Threads.Set(rawMetrics.FindByNames("jvm_threads_live", "jvm_threads_live_threads").Max()) 135 136 // heap memory 137 gatherHeap(rawMetrics.FindByName("jvm_memory_used_bytes"), &m.HeapUsed) 138 gatherHeap(rawMetrics.FindByName("jvm_memory_committed_bytes"), &m.HeapCommitted) 139 m.MemFree.Set(m.HeapCommitted.Sum() - m.HeapUsed.Sum()) 140 141 return stm.ToMap(m) 142 } 143 144 func gatherHeap(rawMetrics prometheus.Series, m *heap) { 145 for _, metric := range rawMetrics { 146 id := metric.Labels.Get("id") 147 value := metric.Value 148 switch { 149 case strings.Contains(id, "Eden"): 150 m.Eden.Set(value) 151 case strings.Contains(id, "Survivor"): 152 m.Survivor.Set(value) 153 case strings.Contains(id, "Old") || strings.Contains(id, "Tenured"): 154 m.Old.Set(value) 155 } 156 } 157 } 158 159 func (s *SpringBoot2) gatherResponse(rawMetrics prometheus.Series, m *metrics) { 160 for _, metric := range rawMetrics.FindByName("http_server_requests_seconds_count") { 161 if s.uriFilter != nil { 162 uri := metric.Labels.Get("uri") 163 if !s.uriFilter.MatchString(uri) { 164 continue 165 } 166 } 167 168 status := metric.Labels.Get("status") 169 if status == "" { 170 continue 171 } 172 value := metric.Value 173 switch status[0] { 174 case '1': 175 m.Resp1xx.Add(value) 176 case '2': 177 m.Resp2xx.Add(value) 178 case '3': 179 m.Resp3xx.Add(value) 180 case '4': 181 m.Resp4xx.Add(value) 182 case '5': 183 m.Resp5xx.Add(value) 184 } 185 } 186 } 187 188 func (h heap) Sum() float64 { 189 return h.Eden.Value() + h.Survivor.Value() + h.Old.Value() 190 }