1
2
3
4
5
6
7
8
9
10
11 package psiprobe.beans.stats.collectors;
12
13 import jakarta.inject.Inject;
14 import jakarta.servlet.ServletContext;
15
16 import org.apache.catalina.Context;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19 import org.springframework.beans.factory.annotation.Value;
20 import org.springframework.web.context.ServletContextAware;
21
22 import psiprobe.TomcatContainer;
23 import psiprobe.beans.ContainerWrapperBean;
24 import psiprobe.model.Application;
25 import psiprobe.tools.ApplicationUtils;
26 import psiprobe.tools.TimeExpression;
27
28
29
30
31 public class AppStatsCollectorBean extends AbstractStatsCollectorBean
32 implements ServletContextAware {
33
34
35 private static final Logger logger = LoggerFactory.getLogger(AppStatsCollectorBean.class);
36
37
38 @Inject
39 private ContainerWrapperBean containerWrapper;
40
41
42 @Inject
43 private ServletContext servletContext;
44
45
46 private boolean selfIgnored;
47
48
49
50
51
52
53 public ContainerWrapperBean getContainerWrapper() {
54 return containerWrapper;
55 }
56
57
58
59
60
61
62 public void setContainerWrapper(ContainerWrapperBean containerWrapper) {
63 this.containerWrapper = containerWrapper;
64 }
65
66
67
68
69
70
71 public boolean isSelfIgnored() {
72 return selfIgnored;
73 }
74
75
76
77
78
79
80 @Value("${psiprobe.beans.stats.collectors.app.selfIgnored}")
81 public void setSelfIgnored(boolean selfIgnored) {
82 this.selfIgnored = selfIgnored;
83 }
84
85
86
87
88
89
90 protected ServletContext getServletContext() {
91 return servletContext;
92 }
93
94 @Override
95 public void setServletContext(ServletContext servletContext) {
96 this.servletContext = servletContext;
97 }
98
99 @Override
100 public void collect() throws InterruptedException {
101
102 long currentTime = System.currentTimeMillis();
103
104 if (containerWrapper == null) {
105 logger.error("Cannot collect application stats. Container wrapper is not set.");
106 } else {
107 TomcatContainer tomcatContainer = getContainerWrapper().getTomcatContainer();
108
109
110 if (tomcatContainer != null) {
111 long totalReqDelta = 0;
112 long totalErrDelta = 0;
113 long totalAvgProcTime = 0;
114 int participatingAppCount = 0;
115
116 for (Context ctx : tomcatContainer.findContexts()) {
117 if (ctx != null && ctx.getName() != null) {
118 Application app = new Application();
119 ApplicationUtils.collectApplicationServletStats(ctx, app);
120
121 String appName = ctx.getName().isEmpty() ? "/" : ctx.getName();
122
123 long reqDelta =
124 buildDeltaStats("app.requests." + appName, app.getRequestCount(), currentTime);
125 long errDelta = buildDeltaStats("app.errors." + appName, app.getErrorCount());
126 long procTimeDelta =
127 buildDeltaStats("app.proc_time." + appName, app.getProcessingTime(), currentTime);
128
129 long avgProcTime = reqDelta == 0 ? 0 : procTimeDelta / reqDelta;
130 buildAbsoluteStats("app.avg_proc_time." + appName, avgProcTime, currentTime);
131
132
133
134
135
136 if (reqDelta > 0 && !excludeFromTotal(ctx)) {
137 totalReqDelta += reqDelta;
138 totalErrDelta += errDelta;
139 totalAvgProcTime += avgProcTime;
140 participatingAppCount++;
141 }
142 }
143 }
144
145 buildAbsoluteStats("total.requests", totalReqDelta, currentTime);
146 buildAbsoluteStats("total.errors", totalErrDelta, currentTime);
147 buildAbsoluteStats("total.avg_proc_time",
148 participatingAppCount == 0 ? 0 : totalAvgProcTime / participatingAppCount, currentTime);
149 }
150 logger.debug("app stats collected in {}ms", System.currentTimeMillis() - currentTime);
151 }
152 }
153
154
155
156
157
158
159
160
161 private boolean excludeFromTotal(Context ctx) {
162 return isSelfIgnored() && getServletContext().equals(ctx.getServletContext());
163 }
164
165
166
167
168 public void reset() {
169 if (containerWrapper == null) {
170 logger.error("Cannot reset application stats. Container wrapper is not set.");
171 } else {
172 TomcatContainer tomcatContainer = getContainerWrapper().getTomcatContainer();
173 if (tomcatContainer != null) {
174 for (Context ctx : tomcatContainer.findContexts()) {
175 if (ctx != null && ctx.getName() != null) {
176 String appName = ctx.getName().isEmpty() ? "/" : ctx.getName();
177 reset(appName);
178 }
179 }
180 }
181 }
182 resetStats("total.requests");
183 resetStats("total.errors");
184 resetStats("total.avg_proc_time");
185 }
186
187
188
189
190
191
192 public void reset(String appName) {
193 resetStats("app.requests." + appName);
194 resetStats("app.proc_time." + appName);
195 resetStats("app.errors." + appName);
196 resetStats("app.avg_proc_time." + appName);
197 }
198
199
200
201
202
203
204
205 public void setMaxSeries(@Value("${psiprobe.beans.stats.collectors.app.period}") long period,
206 @Value("${psiprobe.beans.stats.collectors.app.span}") long span) {
207 super.setMaxSeries((int) TimeExpression.dataPoints(period, span));
208 }
209
210 }