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 @Value("${psiprobe.beans.stats.collectors.app.selfIgnored}")
47 private boolean selfIgnored;
48
49 @Override
50 public void collect() throws InterruptedException {
51
52 long currentTime = System.currentTimeMillis();
53
54 if (containerWrapper == null) {
55 logger.error("Cannot collect application stats. Container wrapper is not set.");
56 } else {
57 TomcatContainer tomcatContainer = containerWrapper.getTomcatContainer();
58
59
60 if (tomcatContainer != null) {
61 long totalReqDelta = 0;
62 long totalErrDelta = 0;
63 long totalAvgProcTime = 0;
64 int participatingAppCount = 0;
65
66 for (Context ctx : tomcatContainer.findContexts()) {
67 if (ctx != null && ctx.getName() != null) {
68 Application app = new Application();
69 ApplicationUtils.collectApplicationServletStats(ctx, app);
70
71 String appName = ctx.getName().isEmpty() ? "/" : ctx.getName();
72
73 long reqDelta =
74 buildDeltaStats("app.requests." + appName, app.getRequestCount(), currentTime);
75 long errDelta = buildDeltaStats("app.errors." + appName, app.getErrorCount());
76 long procTimeDelta =
77 buildDeltaStats("app.proc_time." + appName, app.getProcessingTime(), currentTime);
78
79 long avgProcTime = reqDelta == 0 ? 0 : procTimeDelta / reqDelta;
80 buildAbsoluteStats("app.avg_proc_time." + appName, avgProcTime, currentTime);
81
82
83
84
85
86 if (reqDelta > 0 && !excludeFromTotal(ctx)) {
87 totalReqDelta += reqDelta;
88 totalErrDelta += errDelta;
89 totalAvgProcTime += avgProcTime;
90 participatingAppCount++;
91 }
92 }
93 }
94
95 buildAbsoluteStats("total.requests", totalReqDelta, currentTime);
96 buildAbsoluteStats("total.errors", totalErrDelta, currentTime);
97 buildAbsoluteStats("total.avg_proc_time",
98 participatingAppCount == 0 ? 0 : totalAvgProcTime / participatingAppCount, currentTime);
99 }
100 logger.debug("app stats collected in {}ms", System.currentTimeMillis() - currentTime);
101 }
102 }
103
104
105
106
107
108
109
110
111 private boolean excludeFromTotal(Context ctx) {
112 return selfIgnored && servletContext.equals(ctx.getServletContext());
113 }
114
115
116
117
118 public void reset() {
119 if (containerWrapper == null) {
120 logger.error("Cannot reset application stats. Container wrapper is not set.");
121 } else {
122 TomcatContainer tomcatContainer = containerWrapper.getTomcatContainer();
123 if (tomcatContainer != null) {
124 for (Context ctx : tomcatContainer.findContexts()) {
125 if (ctx != null && ctx.getName() != null) {
126 String appName = ctx.getName().isEmpty() ? "/" : ctx.getName();
127 reset(appName);
128 }
129 }
130 }
131 }
132 resetStats("total.requests");
133 resetStats("total.errors");
134 resetStats("total.avg_proc_time");
135 }
136
137
138
139
140
141
142 public void reset(String appName) {
143 resetStats("app.requests." + appName);
144 resetStats("app.proc_time." + appName);
145 resetStats("app.errors." + appName);
146 resetStats("app.avg_proc_time." + appName);
147 }
148
149
150
151
152
153
154
155 public void setMaxSeries(@Value("${psiprobe.beans.stats.collectors.app.period}") String period,
156 @Value("${psiprobe.beans.stats.collectors.app.span}") String span) {
157 super.setMaxSeries((int) TimeExpression.dataPoints(period, span));
158 }
159
160 @Override
161 public void setServletContext(ServletContext servletContext) {
162
163 }
164
165 }