1
18 package net.bull.javamelody.internal.web.pdf;
19
20 import java.io.IOException;
21 import java.text.DecimalFormat;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.List;
26
27 import com.lowagie.text.BadElementException;
28 import com.lowagie.text.Document;
29 import com.lowagie.text.DocumentException;
30 import com.lowagie.text.Element;
31 import com.lowagie.text.Font;
32 import com.lowagie.text.Image;
33 import com.lowagie.text.Paragraph;
34 import com.lowagie.text.Phrase;
35
36 import net.bull.javamelody.internal.common.I18N;
37 import net.bull.javamelody.internal.model.Collector;
38 import net.bull.javamelody.internal.model.Counter;
39 import net.bull.javamelody.internal.model.CounterRequest;
40 import net.bull.javamelody.internal.model.CounterRequestAggregation;
41 import net.bull.javamelody.internal.model.JRobin;
42 import net.bull.javamelody.internal.model.Range;
43
44
48 class PdfCounterReport extends PdfAbstractTableReport {
49 private final Collector collector;
50 private final Counter counter;
51 private final Range range;
52 private final boolean includeGraph;
53 private final CounterRequestAggregation counterRequestAggregation;
54 private final DecimalFormat systemErrorFormat = I18N.createPercentFormat();
55 private final DecimalFormat integerFormat = I18N.createIntegerFormat();
56 private final Font infoCellFont = PdfFonts.INFO_CELL.getFont();
57 private final Font warningCellFont = PdfFonts.WARNING_CELL.getFont();
58 private final Font severeCellFont = PdfFonts.SEVERE_CELL.getFont();
59 private final Font normalFont = PdfFonts.NORMAL.getFont();
60
61 PdfCounterReport(Collector collector, Counter counter, Range range, boolean includeGraph,
62 Document document) {
63 super(document);
64 assert collector != null;
65 assert counter != null;
66 assert range != null;
67 this.collector = collector;
68 this.counter = counter;
69 this.range = range;
70 this.includeGraph = includeGraph;
71 this.counterRequestAggregation = new CounterRequestAggregation(counter);
72 }
73
74 @Override
75 void toPdf() throws DocumentException, IOException {
76 final List<CounterRequest> requests = counterRequestAggregation.getRequests();
77 if (requests.isEmpty()) {
78 writeNoRequests();
79 } else if (isErrorAndNotJobCounter()) {
80
81 assert !requests.isEmpty();
82 final List<CounterRequest> summaryRequest = Collections.singletonList(requests.get(0));
83 writeRequests(counter.getChildCounterName(), summaryRequest);
84 } else {
85
86 final CounterRequest globalRequest = counterRequestAggregation.getGlobalRequest();
87 final List<CounterRequest> summaryRequests = Arrays.asList(globalRequest,
88 counterRequestAggregation.getWarningRequest(),
89 counterRequestAggregation.getSevereRequest());
90 writeRequests(counter.getChildCounterName(), summaryRequests);
91 }
92 }
93
94 String getCounterName() {
95 return counter.getName();
96 }
97
98 String getCounterIconName() {
99 return counter.getIconName();
100 }
101
102 boolean isErrorCounter() {
103 return counter.isErrorCounter();
104 }
105
106 private boolean isJobCounter() {
107 return counter.isJobCounter();
108 }
109
110 private boolean isErrorAndNotJobCounter() {
111 return isErrorCounter() && !isJobCounter();
112 }
113
114 void writeRequestDetails() throws DocumentException, IOException {
115
116 final List<CounterRequest> requests = counterRequestAggregation.getRequests();
117 if (requests.isEmpty()) {
118 writeNoRequests();
119 } else {
120
121
122 writeRequests(counter.getChildCounterName(), requests);
123 }
124 }
125
126 private void writeNoRequests() throws DocumentException {
127 final String msg;
128 if (isJobCounter()) {
129 msg = "Aucun_job";
130 } else if (isErrorCounter()) {
131 msg = "Aucune_erreur";
132 } else {
133 msg = "Aucune_requete";
134 }
135 addToDocument(new Phrase(getString(msg), normalFont));
136 }
137
138 void writeErrorDetails() throws DocumentException {
139
140 new PdfCounterErrorReport(counter, getDocument()).toPdf();
141 }
142
143 void writeRequests(String childCounterName, List<CounterRequest> requestList)
144 throws DocumentException, IOException {
145 assert requestList != null;
146 writeHeader(childCounterName);
147
148 for (final CounterRequest request : requestList) {
149 nextRow();
150 writeRequest(request);
151 }
152 addTableToDocument();
153
154
155 writeFooter();
156 }
157
158 private void writeHeader(String childCounterName) throws DocumentException {
159 final List<String> headers = createHeaders(childCounterName);
160 final int[] relativeWidths = new int[headers.size()];
161 Arrays.fill(relativeWidths, 0, headers.size(), 1);
162 relativeWidths[0] = 10;
163 if (includeGraph) {
164 relativeWidths[0] = 8;
165 relativeWidths[1] = 2;
166 }
167
168 initTable(headers, relativeWidths);
169 }
170
171 private List<String> createHeaders(String childCounterName) {
172 final List<String> headers = new ArrayList<>();
173 headers.add(getRequestHeader());
174 if (includeGraph) {
175 headers.add(getString("Evolution"));
176 }
177 if (counterRequestAggregation.isTimesDisplayed()) {
178 headers.add(getString("temps_cumule"));
179 headers.add(getString("Hits"));
180 headers.add(getString("Temps_moyen"));
181 headers.add(getString("Temps_max"));
182 headers.add(getString("Ecart_type"));
183 } else {
184 headers.add(getString("Hits"));
185 }
186 if (counterRequestAggregation.isCpuTimesDisplayed()) {
187 headers.add(getString("temps_cpu_cumule"));
188 headers.add(getString("Temps_cpu_moyen"));
189 }
190 if (counterRequestAggregation.isAllocatedKBytesDisplayed()) {
191 headers.add(getString("Ko_alloues_moyens"));
192 }
193 if (!isErrorAndNotJobCounter()) {
194 headers.add(getString("erreur_systeme"));
195 }
196 if (counterRequestAggregation.isResponseSizeDisplayed()) {
197 headers.add(getString("Taille_moyenne"));
198 }
199 if (counterRequestAggregation.isChildHitsDisplayed()) {
200 headers.add(getFormattedString("hits_fils_moyens", childCounterName));
201 headers.add(getFormattedString("temps_fils_moyen", childCounterName));
202 }
203 return headers;
204 }
205
206 private String getRequestHeader() {
207 if (isJobCounter()) {
208 return getString("Job");
209 } else if (isErrorCounter()) {
210 return getString("Erreur");
211 } else {
212 return getString("Requete");
213 }
214 }
215
216 private void writeFooter() throws DocumentException {
217 final List<CounterRequest> requests = counterRequestAggregation.getRequests();
218 final CounterRequest globalRequest = counterRequestAggregation.getGlobalRequest();
219
220 final long deltaMillis = Math
221 .max(System.currentTimeMillis() - counter.getStartDate().getTime(), 1);
222 final long hitsParMinute = 60 * 1000 * globalRequest.getHits() / deltaMillis;
223 final String key;
224 if (isJobCounter()) {
225 key = "nb_jobs";
226 } else if (isErrorCounter()) {
227 key = "nb_erreurs";
228 } else {
229 key = "nb_requetes";
230 }
231 final Paragraph footer = new Paragraph(getFormattedString(key,
232 integerFormat.format(hitsParMinute), integerFormat.format(requests.size())),
233 normalFont);
234 footer.setAlignment(Element.ALIGN_RIGHT);
235 addToDocument(footer);
236 }
237
238 private void writeRequest(CounterRequest request) throws BadElementException, IOException {
239 getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
240 addCell(getShortRequestName(request));
241 if (includeGraph) {
242 writeRequestGraph(request);
243 }
244 getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
245 final CounterRequest globalRequest = counterRequestAggregation.getGlobalRequest();
246 if (counterRequestAggregation.isTimesDisplayed()) {
247 addPercentageCell(request.getDurationsSum(), globalRequest.getDurationsSum());
248 addCell(integerFormat.format(request.getHits()));
249 final int mean = request.getMean();
250 addCell(new Phrase(integerFormat.format(mean), getSlaFont(mean)));
251 addCell(integerFormat.format(request.getMaximum()));
252 addCell(integerFormat.format(request.getStandardDeviation()));
253 } else {
254 addCell(integerFormat.format(request.getHits()));
255 }
256 if (counterRequestAggregation.isCpuTimesDisplayed()) {
257 addPercentageCell(request.getCpuTimeSum(), globalRequest.getCpuTimeSum());
258 final int cpuTimeMean = request.getCpuTimeMean();
259 addCell(new Phrase(integerFormat.format(cpuTimeMean), getSlaFont(cpuTimeMean)));
260 }
261 if (counterRequestAggregation.isAllocatedKBytesDisplayed()) {
262 final long allocatedKBytesMean = request.getAllocatedKBytesMean();
263 addCell(integerFormat.format(allocatedKBytesMean));
264 }
265 if (!isErrorAndNotJobCounter()) {
266 addCell(systemErrorFormat.format(request.getSystemErrorPercentage()));
267 }
268 if (counterRequestAggregation.isResponseSizeDisplayed()) {
269 addCell(integerFormat.format(request.getResponseSizeMean() / 1024L));
270 }
271 if (counterRequestAggregation.isChildHitsDisplayed()) {
272 addCell(integerFormat.format(request.getChildHitsMean()));
273 addCell(integerFormat.format(request.getChildDurationsMean()));
274 }
275 }
276
277 private String getShortRequestName(CounterRequest request) {
278 final String name = request.getName();
279 if (name.length() > 1000) {
280
281 return name.substring(0, 1000) + "...";
282 }
283 return name;
284 }
285
286 private void writeRequestGraph(CounterRequest request) throws BadElementException, IOException {
287 final JRobin jrobin = collector.getJRobin(request.getId());
288 if (jrobin == null) {
289 addCell("");
290 } else {
291 final byte[] img = jrobin.graph(range, 100, 50);
292 final Image image = Image.getInstance(img);
293 image.scalePercent(50);
294 addCell(image);
295 }
296 }
297
298 Font getSlaFont(int mean) {
299 final Font font;
300 if (mean < counterRequestAggregation.getWarningThreshold() || mean == 0) {
301
302 font = infoCellFont;
303 } else if (mean < counterRequestAggregation.getSevereThreshold()) {
304
305
306 font = warningCellFont;
307 } else {
308
309
310
311 font = severeCellFont;
312 }
313 return font;
314 }
315
316 private void addPercentageCell(long dividende, long diviseur) {
317 if (diviseur == 0) {
318 addCell("0");
319 } else {
320 addCell(integerFormat.format(100 * dividende / diviseur));
321 }
322 }
323 }
324