17 |
ilm |
1 |
/*
|
|
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
|
3 |
*
|
|
|
4 |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
|
|
|
5 |
*
|
|
|
6 |
* The contents of this file are subject to the terms of the GNU General Public License Version 3
|
|
|
7 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
|
|
|
8 |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
|
|
|
9 |
* language governing permissions and limitations under the License.
|
|
|
10 |
*
|
|
|
11 |
* When distributing the software, include this License Header Notice in each file.
|
|
|
12 |
*/
|
|
|
13 |
|
|
|
14 |
package org.openconcerto.sql.model;
|
|
|
15 |
|
73 |
ilm |
16 |
import org.openconcerto.sql.Log;
|
151 |
ilm |
17 |
import org.openconcerto.ui.FontUtils;
|
65 |
ilm |
18 |
import org.openconcerto.utils.ExceptionUtils;
|
17 |
ilm |
19 |
|
|
|
20 |
import java.awt.BorderLayout;
|
|
|
21 |
import java.awt.Color;
|
|
|
22 |
import java.awt.Component;
|
|
|
23 |
import java.awt.FlowLayout;
|
|
|
24 |
import java.awt.event.ActionEvent;
|
|
|
25 |
import java.awt.event.ActionListener;
|
|
|
26 |
import java.awt.event.MouseAdapter;
|
|
|
27 |
import java.awt.event.MouseEvent;
|
174 |
ilm |
28 |
import java.io.PrintStream;
|
67 |
ilm |
29 |
import java.sql.Connection;
|
73 |
ilm |
30 |
import java.sql.PreparedStatement;
|
80 |
ilm |
31 |
import java.text.DateFormat;
|
17 |
ilm |
32 |
import java.text.DecimalFormat;
|
|
|
33 |
import java.text.SimpleDateFormat;
|
|
|
34 |
import java.util.ArrayList;
|
|
|
35 |
import java.util.HashSet;
|
|
|
36 |
import java.util.List;
|
|
|
37 |
import java.util.Set;
|
94 |
ilm |
38 |
import java.util.Vector;
|
73 |
ilm |
39 |
import java.util.logging.Level;
|
17 |
ilm |
40 |
|
|
|
41 |
import javax.swing.JButton;
|
|
|
42 |
import javax.swing.JFrame;
|
|
|
43 |
import javax.swing.JLabel;
|
|
|
44 |
import javax.swing.JPanel;
|
|
|
45 |
import javax.swing.JScrollPane;
|
|
|
46 |
import javax.swing.JTable;
|
|
|
47 |
import javax.swing.JTextArea;
|
|
|
48 |
import javax.swing.SwingConstants;
|
|
|
49 |
import javax.swing.SwingUtilities;
|
|
|
50 |
import javax.swing.event.ChangeListener;
|
|
|
51 |
import javax.swing.table.DefaultTableCellRenderer;
|
65 |
ilm |
52 |
import javax.swing.table.TableColumn;
|
17 |
ilm |
53 |
import javax.swing.table.TableModel;
|
|
|
54 |
import javax.swing.table.TableRowSorter;
|
|
|
55 |
|
142 |
ilm |
56 |
import net.jcip.annotations.GuardedBy;
|
|
|
57 |
|
17 |
ilm |
58 |
public class SQLRequestLog {
|
|
|
59 |
|
67 |
ilm |
60 |
private static final Color BG_PINK = new Color(254, 240, 240);
|
|
|
61 |
private static final String ACTIVER_LA_CAPTURE = "Enable monitoring";
|
|
|
62 |
private static final String DESACTIVER_LA_CAPTURE = "Disable monitoring";
|
94 |
ilm |
63 |
private static Vector<SQLRequestLog> list = new Vector<SQLRequestLog>(500);
|
174 |
ilm |
64 |
@GuardedBy("this")
|
17 |
ilm |
65 |
private static boolean enabled;
|
174 |
ilm |
66 |
|
|
|
67 |
public static synchronized void setEnabled(boolean enable) {
|
|
|
68 |
enabled = enable;
|
|
|
69 |
}
|
|
|
70 |
|
|
|
71 |
public static synchronized boolean toggleEnabled() {
|
|
|
72 |
final boolean newVal = !isEnabled();
|
|
|
73 |
setEnabled(newVal);
|
|
|
74 |
return newVal;
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
public static synchronized boolean isEnabled() {
|
|
|
78 |
return enabled;
|
|
|
79 |
}
|
|
|
80 |
|
17 |
ilm |
81 |
private String query;
|
|
|
82 |
private String comment;
|
|
|
83 |
private long startAsMs;
|
65 |
ilm |
84 |
private final long startTime, afterCache, afterQueryInfo, afterExecute, afterHandle, endTime;
|
17 |
ilm |
85 |
private String stack;
|
|
|
86 |
private boolean inSwing;
|
|
|
87 |
private int connectionId;
|
|
|
88 |
private boolean forShare;
|
|
|
89 |
private String threadId;
|
|
|
90 |
private static List<ChangeListener> listeners = new ArrayList<ChangeListener>(2);
|
142 |
ilm |
91 |
@GuardedBy("EDT")
|
144 |
ilm |
92 |
private static JLabel textInfo;
|
|
|
93 |
@GuardedBy("EDT")
|
80 |
ilm |
94 |
private static final DateFormat sdt = new SimpleDateFormat("HH:mm:ss.SS");
|
17 |
ilm |
95 |
private static final DecimalFormat dformat = new DecimalFormat("##0.00");
|
|
|
96 |
|
67 |
ilm |
97 |
private boolean isHighlighted = false;
|
142 |
ilm |
98 |
private int rs_count;
|
67 |
ilm |
99 |
|
65 |
ilm |
100 |
private static final String format(final Object nano) {
|
|
|
101 |
final long l = ((Number) nano).longValue();
|
|
|
102 |
return l == 0 ? "" : dformat.format(l / 1000000D) + " ms";
|
|
|
103 |
}
|
|
|
104 |
|
|
|
105 |
public SQLRequestLog(String query, String comment, int connectionId, long starAtMs, String ex, boolean inSwing, long startTime, long afterCache, long afterQueryInfo, long afterExecute,
|
142 |
ilm |
106 |
long afterHandle, long endTime, int count) {
|
17 |
ilm |
107 |
this.query = query;
|
|
|
108 |
this.comment = comment;
|
|
|
109 |
this.connectionId = connectionId;
|
|
|
110 |
this.startAsMs = starAtMs;
|
65 |
ilm |
111 |
this.startTime = startTime;
|
|
|
112 |
this.afterCache = afterCache;
|
|
|
113 |
this.afterQueryInfo = afterQueryInfo;
|
|
|
114 |
this.afterExecute = afterExecute;
|
|
|
115 |
this.afterHandle = afterHandle;
|
|
|
116 |
this.endTime = endTime;
|
142 |
ilm |
117 |
this.rs_count = count;
|
17 |
ilm |
118 |
this.stack = ex;
|
|
|
119 |
this.inSwing = inSwing;
|
|
|
120 |
this.forShare = query.contains("FOR SHARE");
|
|
|
121 |
if (this.forShare) {
|
67 |
ilm |
122 |
this.comment = "Use FOR SHARE. " + comment;
|
17 |
ilm |
123 |
}
|
|
|
124 |
this.threadId = "[" + Thread.currentThread().getId() + "] " + Thread.currentThread().getName();
|
|
|
125 |
}
|
|
|
126 |
|
142 |
ilm |
127 |
static long total_count = 0;
|
93 |
ilm |
128 |
|
142 |
ilm |
129 |
public static void log(String query, String comment, int connectionId, long starAtMs, long startTime, long afterCache, long afterQueryInfo, long afterExecute, long afterHandle, long endTime,
|
|
|
130 |
int count) {
|
93 |
ilm |
131 |
|
174 |
ilm |
132 |
if (isEnabled()) {
|
94 |
ilm |
133 |
if (list.size() < 50000) {
|
|
|
134 |
final String ex = ExceptionUtils.getStackTrace(new Exception());
|
17 |
ilm |
135 |
|
94 |
ilm |
136 |
list.add(new SQLRequestLog(query, comment, connectionId, starAtMs, ex, SwingUtilities.isEventDispatchThread(), startTime, afterCache, afterQueryInfo, afterExecute, afterHandle,
|
142 |
ilm |
137 |
endTime, count));
|
94 |
ilm |
138 |
fireEvent();
|
|
|
139 |
}
|
17 |
ilm |
140 |
|
|
|
141 |
}
|
93 |
ilm |
142 |
count++;
|
17 |
ilm |
143 |
}
|
|
|
144 |
|
65 |
ilm |
145 |
public static void log(String query, String comment, long starAtMs, long startTime) {
|
142 |
ilm |
146 |
log(query, comment, 0, starAtMs, startTime, startTime, startTime, startTime, startTime, startTime, 0);
|
17 |
ilm |
147 |
}
|
|
|
148 |
|
73 |
ilm |
149 |
public static void log(PreparedStatement pStmt, String comment, long timeMs, long startTime, long afterCache, long afterQueryInfo, long afterExecute, long afterHandle, long endTime) {
|
|
|
150 |
// only call potentially expensive and/or exceptions throwing methods if necessary
|
174 |
ilm |
151 |
if (isEnabled()) {
|
73 |
ilm |
152 |
try {
|
142 |
ilm |
153 |
log(pStmt.toString(), comment, pStmt.getConnection(), timeMs, startTime, afterCache, afterQueryInfo, afterExecute, afterHandle, endTime, 0);
|
73 |
ilm |
154 |
} catch (Exception e) {
|
|
|
155 |
// never propagate exceptions
|
|
|
156 |
Log.get().log(Level.WARNING, "Couldn't log " + pStmt, e);
|
|
|
157 |
}
|
|
|
158 |
}
|
|
|
159 |
}
|
|
|
160 |
|
142 |
ilm |
161 |
public static void log(String query, String comment, Connection conn, long timeMs, long startTime, long afterCache, long afterQueryInfo, long afterExecute, long afterHandle, long endTime,
|
|
|
162 |
int count) {
|
|
|
163 |
log(query, comment, System.identityHashCode(conn), timeMs, startTime, afterCache, afterQueryInfo, afterExecute, afterHandle, endTime, count);
|
17 |
ilm |
164 |
}
|
|
|
165 |
|
|
|
166 |
private static void fireEvent() {
|
|
|
167 |
SwingUtilities.invokeLater(new Runnable() {
|
|
|
168 |
@Override
|
|
|
169 |
public void run() {
|
|
|
170 |
int stop = listeners.size();
|
|
|
171 |
for (int i = 0; i < stop; i++) {
|
|
|
172 |
listeners.get(i).stateChanged(null);
|
|
|
173 |
}
|
144 |
ilm |
174 |
if (textInfo != null) {
|
|
|
175 |
final long totalMs = getTotalMs();
|
|
|
176 |
final long totalSQLMs = getTotalSQLMs();
|
|
|
177 |
textInfo.setText("Total: " + totalMs + " ms, Swing: " + getTotalSwing() + " ms, SQL: " + totalSQLMs + " ms, processing: " + (totalMs - totalSQLMs) + " ms , " + getNbConnections()
|
|
|
178 |
+ " conn., " + getNbThread() + " threads. Total: " + list.size() + " / " + total_count);
|
|
|
179 |
}
|
17 |
ilm |
180 |
}
|
|
|
181 |
});
|
|
|
182 |
}
|
|
|
183 |
|
|
|
184 |
protected static int getNbConnections() {
|
|
|
185 |
final Set<Integer> s = new HashSet<Integer>();
|
|
|
186 |
final int stop = list.size();
|
|
|
187 |
|
|
|
188 |
for (int i = 0; i < stop; i++) {
|
|
|
189 |
final SQLRequestLog l = list.get(i);
|
|
|
190 |
if (l.getConnectionId() > 0) {
|
|
|
191 |
s.add(l.getConnectionId());
|
|
|
192 |
}
|
|
|
193 |
|
|
|
194 |
}
|
|
|
195 |
return s.size();
|
|
|
196 |
}
|
|
|
197 |
|
|
|
198 |
protected static int getNbThread() {
|
|
|
199 |
final Set<String> s = new HashSet<String>();
|
|
|
200 |
final int stop = list.size();
|
|
|
201 |
for (int i = 0; i < stop; i++) {
|
|
|
202 |
final SQLRequestLog l = list.get(i);
|
|
|
203 |
s.add(l.getThreadId());
|
|
|
204 |
}
|
|
|
205 |
return s.size();
|
|
|
206 |
}
|
|
|
207 |
|
|
|
208 |
protected static long getTotalMs() {
|
|
|
209 |
final int stop = list.size();
|
|
|
210 |
long t = 0;
|
|
|
211 |
for (int i = 0; i < stop; i++) {
|
65 |
ilm |
212 |
t += (list.get(i).getDurationTotalNano() / 1000);
|
17 |
ilm |
213 |
}
|
|
|
214 |
return t / 1000;
|
|
|
215 |
}
|
|
|
216 |
|
|
|
217 |
protected static long getTotalSQLMs() {
|
|
|
218 |
final int stop = list.size();
|
|
|
219 |
long t = 0;
|
|
|
220 |
for (int i = 0; i < stop; i++) {
|
65 |
ilm |
221 |
t += (list.get(i).getDurationSQLNano() / 1000);
|
17 |
ilm |
222 |
}
|
|
|
223 |
return t / 1000;
|
|
|
224 |
}
|
|
|
225 |
|
|
|
226 |
protected static long getTotalSwing() {
|
|
|
227 |
final int stop = list.size();
|
|
|
228 |
long t = 0;
|
|
|
229 |
for (int i = 0; i < stop; i++) {
|
|
|
230 |
|
|
|
231 |
final SQLRequestLog requestLog = list.get(i);
|
|
|
232 |
if (requestLog.isInSwing()) {
|
65 |
ilm |
233 |
t += (requestLog.getDurationTotalNano() / 1000);
|
17 |
ilm |
234 |
}
|
|
|
235 |
}
|
|
|
236 |
return t / 1000;
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
public boolean isInSwing() {
|
|
|
240 |
return this.inSwing;
|
|
|
241 |
}
|
|
|
242 |
|
|
|
243 |
public static void addChangeListener(ChangeListener l) {
|
|
|
244 |
listeners.add(l);
|
|
|
245 |
}
|
|
|
246 |
|
|
|
247 |
public static void showFrame() {
|
144 |
ilm |
248 |
if (textInfo != null)
|
|
|
249 |
return;
|
|
|
250 |
|
67 |
ilm |
251 |
JFrame f = new JFrame("SQL monitoring");
|
17 |
ilm |
252 |
final SQLRequestLogModel model = new SQLRequestLogModel();
|
|
|
253 |
final JTable table = new JTable(model);
|
151 |
ilm |
254 |
table.setRowHeight(FontUtils.getPreferredRowHeight(table));
|
|
|
255 |
final TableRowSorter<TableModel> sorter = new TableRowSorter<>(table.getModel());
|
17 |
ilm |
256 |
table.setRowSorter(sorter);
|
|
|
257 |
|
|
|
258 |
table.getTableHeader().setReorderingAllowed(false);
|
|
|
259 |
|
|
|
260 |
table.addMouseListener(new MouseAdapter() {
|
|
|
261 |
@Override
|
|
|
262 |
public void mouseClicked(MouseEvent e) {
|
|
|
263 |
if (e.getClickCount() >= 2) {
|
|
|
264 |
showStack(model, sorter, table.getSelectedRow());
|
|
|
265 |
}
|
67 |
ilm |
266 |
highLight(model, sorter, table.getSelectedRow());
|
17 |
ilm |
267 |
|
|
|
268 |
}
|
|
|
269 |
});
|
65 |
ilm |
270 |
|
17 |
ilm |
271 |
// Column Date
|
65 |
ilm |
272 |
final TableColumn timeCol = table.getColumnModel().getColumn(0);
|
|
|
273 |
timeCol.setCellRenderer(new DefaultTableCellRenderer() {
|
17 |
ilm |
274 |
@Override
|
65 |
ilm |
275 |
protected void setValue(Object value) {
|
|
|
276 |
super.setValue(sdt.format(value));
|
17 |
ilm |
277 |
}
|
67 |
ilm |
278 |
|
|
|
279 |
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
|
|
280 |
final Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
|
|
281 |
final SQLRequestLog rowAt = model.getRowAt(sorter.convertRowIndexToModel(row));
|
|
|
282 |
if (rowAt.isHighlighted) {
|
|
|
283 |
tableCellRendererComponent.setBackground(Color.black);
|
|
|
284 |
tableCellRendererComponent.setForeground(Color.white);
|
|
|
285 |
} else {
|
|
|
286 |
tableCellRendererComponent.setBackground(Color.white);
|
|
|
287 |
tableCellRendererComponent.setForeground(Color.black);
|
|
|
288 |
}
|
|
|
289 |
return tableCellRendererComponent;
|
|
|
290 |
}
|
65 |
ilm |
291 |
});
|
|
|
292 |
timeCol.setMaxWidth(80);
|
|
|
293 |
timeCol.setMinWidth(80);
|
|
|
294 |
|
|
|
295 |
// SQL
|
17 |
ilm |
296 |
final DefaultTableCellRenderer cellRendererDurationSQL = new DefaultTableCellRenderer() {
|
|
|
297 |
@Override
|
|
|
298 |
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
65 |
ilm |
299 |
final Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
17 |
ilm |
300 |
if (!isSelected) {
|
|
|
301 |
final SQLRequestLog rowAt = model.getRowAt(sorter.convertRowIndexToModel(row));
|
|
|
302 |
float ratio = 1;
|
|
|
303 |
// Ignore processing >2ms
|
65 |
ilm |
304 |
if (rowAt.getDurationTotalNano() > 0 && (rowAt.getDurationTotalNano() - rowAt.getDurationSQLNano()) > 2000000) {
|
|
|
305 |
ratio = rowAt.getDurationSQLNano() / (float) rowAt.getDurationTotalNano();
|
17 |
ilm |
306 |
}
|
|
|
307 |
int b = Math.round(255f * (ratio * ratio));
|
|
|
308 |
if (b < 0)
|
|
|
309 |
b = 0;
|
|
|
310 |
if (b > 255)
|
|
|
311 |
b = 255;
|
|
|
312 |
tableCellRendererComponent.setBackground(new Color(255, 255, b));
|
|
|
313 |
tableCellRendererComponent.setForeground(Color.BLACK);
|
|
|
314 |
}
|
|
|
315 |
return tableCellRendererComponent;
|
|
|
316 |
}
|
65 |
ilm |
317 |
|
|
|
318 |
@Override
|
|
|
319 |
protected void setValue(Object value) {
|
|
|
320 |
super.setValue(format(value));
|
|
|
321 |
}
|
17 |
ilm |
322 |
};
|
|
|
323 |
cellRendererDurationSQL.setHorizontalAlignment(SwingConstants.RIGHT);
|
65 |
ilm |
324 |
final TableColumn execCol = table.getColumnModel().getColumn(1);
|
|
|
325 |
execCol.setCellRenderer(cellRendererDurationSQL);
|
67 |
ilm |
326 |
execCol.setMaxWidth(80);
|
|
|
327 |
execCol.setMinWidth(80);
|
17 |
ilm |
328 |
|
|
|
329 |
// Traitement
|
|
|
330 |
final DefaultTableCellRenderer cellRendererTraitement = new DefaultTableCellRenderer() {
|
|
|
331 |
@Override
|
|
|
332 |
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
|
|
333 |
final JLabel tableCellRendererComponent = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
|
|
334 |
if (!isSelected) {
|
65 |
ilm |
335 |
final long l = ((Number) value).longValue();
|
17 |
ilm |
336 |
if (l > 100 * 1000000) {
|
|
|
337 |
tableCellRendererComponent.setBackground(new Color(254, 254, 0));
|
|
|
338 |
} else {
|
|
|
339 |
tableCellRendererComponent.setBackground(Color.WHITE);
|
|
|
340 |
}
|
|
|
341 |
tableCellRendererComponent.setForeground(Color.BLACK);
|
|
|
342 |
}
|
|
|
343 |
return tableCellRendererComponent;
|
|
|
344 |
}
|
65 |
ilm |
345 |
|
|
|
346 |
@Override
|
|
|
347 |
protected void setValue(Object value) {
|
|
|
348 |
super.setValue(format(value));
|
|
|
349 |
}
|
17 |
ilm |
350 |
};
|
|
|
351 |
cellRendererTraitement.setHorizontalAlignment(SwingConstants.RIGHT);
|
65 |
ilm |
352 |
final TableColumn processingCol = table.getColumnModel().getColumn(2);
|
|
|
353 |
processingCol.setCellRenderer(cellRendererTraitement);
|
67 |
ilm |
354 |
processingCol.setMaxWidth(80);
|
|
|
355 |
processingCol.setMinWidth(80);
|
17 |
ilm |
356 |
|
67 |
ilm |
357 |
// Clean Up
|
|
|
358 |
final DefaultTableCellRenderer nanoRenderer = new DefaultTableCellRenderer() {
|
65 |
ilm |
359 |
|
67 |
ilm |
360 |
{
|
|
|
361 |
this.setHorizontalAlignment(SwingConstants.RIGHT);
|
|
|
362 |
}
|
|
|
363 |
|
|
|
364 |
@Override
|
|
|
365 |
protected void setValue(Object value) {
|
|
|
366 |
super.setValue(format(value));
|
|
|
367 |
}
|
|
|
368 |
};
|
|
|
369 |
final TableColumn cleanupCol = table.getColumnModel().getColumn(3);
|
|
|
370 |
cleanupCol.setCellRenderer(nanoRenderer);
|
|
|
371 |
cleanupCol.setMaxWidth(80);
|
|
|
372 |
cleanupCol.setMinWidth(80);
|
|
|
373 |
|
|
|
374 |
// Column Total SQL
|
|
|
375 |
final TableColumn totalCol = table.getColumnModel().getColumn(4);
|
|
|
376 |
|
|
|
377 |
totalCol.setCellRenderer(nanoRenderer);
|
|
|
378 |
totalCol.setMaxWidth(80);
|
|
|
379 |
totalCol.setMinWidth(80);
|
|
|
380 |
|
|
|
381 |
// Request
|
|
|
382 |
final TableColumn reqCol = table.getColumnModel().getColumn(5);
|
17 |
ilm |
383 |
final DefaultTableCellRenderer cellRendererQuery = new DefaultTableCellRenderer() {
|
|
|
384 |
@Override
|
|
|
385 |
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
|
|
386 |
final JLabel tableCellRendererComponent = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
|
|
387 |
if (!isSelected) {
|
67 |
ilm |
388 |
final SQLRequestLog rowAt = model.getRowAt(sorter.convertRowIndexToModel(row));
|
|
|
389 |
if (rowAt.isInSwing() && !rowAt.getComment().contains("cache")) {
|
|
|
390 |
tableCellRendererComponent.setBackground(BG_PINK);
|
|
|
391 |
} else {
|
|
|
392 |
tableCellRendererComponent.setBackground(Color.WHITE);
|
|
|
393 |
}
|
|
|
394 |
tableCellRendererComponent.setForeground(Color.BLACK);
|
|
|
395 |
}
|
|
|
396 |
return tableCellRendererComponent;
|
|
|
397 |
}
|
|
|
398 |
};
|
|
|
399 |
reqCol.setCellRenderer(cellRendererQuery);
|
|
|
400 |
reqCol.setMinWidth(400);
|
|
|
401 |
|
|
|
402 |
// Column Info
|
|
|
403 |
final DefaultTableCellRenderer cellRendererInfo = new DefaultTableCellRenderer() {
|
|
|
404 |
@Override
|
|
|
405 |
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
|
|
406 |
final JLabel tableCellRendererComponent = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
|
|
407 |
if (!isSelected) {
|
17 |
ilm |
408 |
if (model.getRowAt(sorter.convertRowIndexToModel(row)).isForShare()) {
|
|
|
409 |
tableCellRendererComponent.setBackground(new Color(254, 254, 150));
|
|
|
410 |
} else {
|
|
|
411 |
tableCellRendererComponent.setBackground(Color.WHITE);
|
|
|
412 |
}
|
|
|
413 |
tableCellRendererComponent.setForeground(Color.BLACK);
|
|
|
414 |
}
|
|
|
415 |
return tableCellRendererComponent;
|
|
|
416 |
}
|
|
|
417 |
};
|
67 |
ilm |
418 |
table.getColumnModel().getColumn(6).setCellRenderer(cellRendererInfo);
|
|
|
419 |
table.getColumnModel().getColumn(6).setMaxWidth(200);
|
|
|
420 |
table.getColumnModel().getColumn(6).setMinWidth(80);
|
17 |
ilm |
421 |
// Column Connexion
|
|
|
422 |
|
67 |
ilm |
423 |
table.getColumnModel().getColumn(7).setMaxWidth(80);
|
|
|
424 |
table.getColumnModel().getColumn(7).setMinWidth(80);
|
17 |
ilm |
425 |
// Column Thread
|
|
|
426 |
final DefaultTableCellRenderer cellRendererThread = new DefaultTableCellRenderer() {
|
|
|
427 |
@Override
|
|
|
428 |
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
|
|
429 |
final JLabel tableCellRendererComponent = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
|
|
430 |
if (!isSelected) {
|
|
|
431 |
if (model.getRowAt(sorter.convertRowIndexToModel(row)).isInSwing()) {
|
67 |
ilm |
432 |
tableCellRendererComponent.setBackground(BG_PINK);
|
17 |
ilm |
433 |
} else {
|
|
|
434 |
tableCellRendererComponent.setBackground(Color.WHITE);
|
|
|
435 |
}
|
|
|
436 |
tableCellRendererComponent.setForeground(Color.BLACK);
|
|
|
437 |
}
|
|
|
438 |
return tableCellRendererComponent;
|
|
|
439 |
}
|
|
|
440 |
};
|
|
|
441 |
|
65 |
ilm |
442 |
table.getColumnModel().getColumn(8).setCellRenderer(cellRendererThread);
|
67 |
ilm |
443 |
table.getColumnModel().getColumn(8).setMinWidth(150);
|
17 |
ilm |
444 |
JPanel p = new JPanel(new BorderLayout());
|
|
|
445 |
|
|
|
446 |
JPanel bar = new JPanel(new FlowLayout());
|
|
|
447 |
|
|
|
448 |
final JButton b0 = new JButton();
|
174 |
ilm |
449 |
if (isEnabled()) {
|
17 |
ilm |
450 |
b0.setText(DESACTIVER_LA_CAPTURE);
|
|
|
451 |
} else {
|
|
|
452 |
b0.setText(ACTIVER_LA_CAPTURE);
|
|
|
453 |
}
|
|
|
454 |
b0.addActionListener(new ActionListener() {
|
|
|
455 |
@Override
|
174 |
ilm |
456 |
public void actionPerformed(ActionEvent e) {
|
|
|
457 |
if (!toggleEnabled()) {
|
17 |
ilm |
458 |
b0.setText(ACTIVER_LA_CAPTURE);
|
|
|
459 |
} else {
|
|
|
460 |
b0.setText(DESACTIVER_LA_CAPTURE);
|
|
|
461 |
}
|
|
|
462 |
|
|
|
463 |
}
|
|
|
464 |
});
|
|
|
465 |
bar.add(b0);
|
67 |
ilm |
466 |
final JButton b1 = new JButton("Clear");
|
17 |
ilm |
467 |
b1.addActionListener(new ActionListener() {
|
|
|
468 |
@Override
|
|
|
469 |
public void actionPerformed(ActionEvent e) {
|
|
|
470 |
clear();
|
|
|
471 |
|
|
|
472 |
}
|
|
|
473 |
});
|
|
|
474 |
bar.add(b1);
|
67 |
ilm |
475 |
final JButton b2 = new JButton("Show stacktrace");
|
17 |
ilm |
476 |
b2.addActionListener(new ActionListener() {
|
|
|
477 |
@Override
|
|
|
478 |
public void actionPerformed(ActionEvent e) {
|
|
|
479 |
int s = table.getSelectedRow();
|
|
|
480 |
showStack(model, sorter, s);
|
|
|
481 |
}
|
|
|
482 |
});
|
|
|
483 |
bar.add(b2);
|
|
|
484 |
|
|
|
485 |
p.add(bar, BorderLayout.NORTH);
|
67 |
ilm |
486 |
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
|
|
487 |
table.getTableHeader().setReorderingAllowed(true);
|
17 |
ilm |
488 |
JScrollPane sc = new JScrollPane(table);
|
|
|
489 |
|
|
|
490 |
p.add(sc, BorderLayout.CENTER);
|
|
|
491 |
|
144 |
ilm |
492 |
textInfo = new JLabel("Total: ");
|
17 |
ilm |
493 |
p.add(textInfo, BorderLayout.SOUTH);
|
|
|
494 |
f.setContentPane(p);
|
|
|
495 |
f.setSize(960, 480);
|
|
|
496 |
f.setVisible(true);
|
|
|
497 |
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
|
|
498 |
f.setVisible(true);
|
|
|
499 |
}
|
|
|
500 |
|
93 |
ilm |
501 |
public static synchronized void clear() {
|
17 |
ilm |
502 |
list.clear();
|
|
|
503 |
fireEvent();
|
142 |
ilm |
504 |
total_count = 0;
|
17 |
ilm |
505 |
}
|
|
|
506 |
|
93 |
ilm |
507 |
public static long getCount() {
|
142 |
ilm |
508 |
return total_count;
|
93 |
ilm |
509 |
}
|
|
|
510 |
|
17 |
ilm |
511 |
public static synchronized int getSize() {
|
|
|
512 |
return list.size();
|
|
|
513 |
}
|
|
|
514 |
|
|
|
515 |
public static synchronized SQLRequestLog get(int rowIndex) {
|
|
|
516 |
return list.get(rowIndex);
|
|
|
517 |
}
|
|
|
518 |
|
|
|
519 |
public String getQuery() {
|
|
|
520 |
return this.query;
|
|
|
521 |
}
|
|
|
522 |
|
67 |
ilm |
523 |
public String getComment() {
|
17 |
ilm |
524 |
return this.comment;
|
|
|
525 |
}
|
|
|
526 |
|
|
|
527 |
public long getStartAsMs() {
|
|
|
528 |
return this.startAsMs;
|
|
|
529 |
}
|
|
|
530 |
|
|
|
531 |
public long getDurationTotalNano() {
|
65 |
ilm |
532 |
return this.getEndTime() - this.getStartTime();
|
17 |
ilm |
533 |
}
|
|
|
534 |
|
|
|
535 |
public long getDurationSQLNano() {
|
65 |
ilm |
536 |
return this.getAfterExecute() - this.getAfterQueryInfo();
|
17 |
ilm |
537 |
}
|
|
|
538 |
|
65 |
ilm |
539 |
public long getDurationHandleNano() {
|
|
|
540 |
return this.getAfterHandle() - this.getAfterExecute();
|
|
|
541 |
}
|
|
|
542 |
|
|
|
543 |
// close + cache
|
|
|
544 |
public long getDurationCleanupNano() {
|
|
|
545 |
return this.getEndTime() - this.getAfterHandle();
|
|
|
546 |
}
|
|
|
547 |
|
|
|
548 |
public final long getStartTime() {
|
|
|
549 |
return this.startTime;
|
|
|
550 |
}
|
|
|
551 |
|
|
|
552 |
public final long getAfterCache() {
|
|
|
553 |
return this.afterCache;
|
|
|
554 |
}
|
|
|
555 |
|
|
|
556 |
public final long getAfterQueryInfo() {
|
|
|
557 |
return this.afterQueryInfo;
|
|
|
558 |
}
|
|
|
559 |
|
|
|
560 |
public final long getAfterExecute() {
|
|
|
561 |
return this.afterExecute;
|
|
|
562 |
}
|
|
|
563 |
|
|
|
564 |
public final long getAfterHandle() {
|
|
|
565 |
return this.afterHandle;
|
|
|
566 |
}
|
|
|
567 |
|
|
|
568 |
public final long getEndTime() {
|
|
|
569 |
return this.endTime;
|
|
|
570 |
}
|
|
|
571 |
|
17 |
ilm |
572 |
public String getStack() {
|
|
|
573 |
return this.stack;
|
|
|
574 |
}
|
|
|
575 |
|
|
|
576 |
public boolean isForShare() {
|
|
|
577 |
return this.forShare;
|
|
|
578 |
}
|
|
|
579 |
|
142 |
ilm |
580 |
public int getResultCount() {
|
|
|
581 |
return rs_count;
|
|
|
582 |
}
|
|
|
583 |
|
17 |
ilm |
584 |
public void printStack() {
|
|
|
585 |
System.err.println("Stacktrace of : " + this.query);
|
|
|
586 |
System.err.println(this.stack);
|
|
|
587 |
}
|
|
|
588 |
|
|
|
589 |
public int getConnectionId() {
|
|
|
590 |
return this.connectionId;
|
|
|
591 |
}
|
|
|
592 |
|
|
|
593 |
public String getThreadId() {
|
|
|
594 |
return this.threadId;
|
|
|
595 |
}
|
|
|
596 |
|
|
|
597 |
private static void showStack(final SQLRequestLogModel model, TableRowSorter<TableModel> sorter, int s) {
|
142 |
ilm |
598 |
assert SwingUtilities.isEventDispatchThread();
|
17 |
ilm |
599 |
if (s >= 0 && s < model.getRowCount()) {
|
|
|
600 |
final SQLRequestLog rowAt = model.getRowAt(sorter.convertRowIndexToModel(s));
|
|
|
601 |
rowAt.printStack();
|
|
|
602 |
String text = "Thread: " + rowAt.getThreadId();
|
|
|
603 |
if (rowAt.isInSwing()) {
|
|
|
604 |
text += " (Swing)";
|
|
|
605 |
}
|
67 |
ilm |
606 |
text += "\nStart: " + sdt.format(rowAt.getStartAsMs()) + "\n";
|
17 |
ilm |
607 |
|
67 |
ilm |
608 |
text += "Total duration: " + dformat.format(rowAt.getDurationTotalNano() / 1000000D) + " ms, " + dformat.format(rowAt.getDurationSQLNano() / 1000000D) + " ms SQL\n";
|
17 |
ilm |
609 |
text += rowAt.getQuery() + "\n" + rowAt.getStack();
|
|
|
610 |
JTextArea area = new JTextArea(text);
|
|
|
611 |
|
|
|
612 |
area.setFont(area.getFont().deriveFont(12f));
|
|
|
613 |
area.setLineWrap(true);
|
|
|
614 |
JFrame fStack = new JFrame("Stacktrace");
|
|
|
615 |
fStack.setContentPane(new JScrollPane(area));
|
|
|
616 |
fStack.pack();
|
|
|
617 |
fStack.setSize(800, 600);
|
|
|
618 |
fStack.setLocationRelativeTo(null);
|
|
|
619 |
fStack.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
|
|
620 |
fStack.setVisible(true);
|
|
|
621 |
}
|
|
|
622 |
}
|
67 |
ilm |
623 |
|
94 |
ilm |
624 |
protected synchronized static void highLight(SQLRequestLogModel model, TableRowSorter<TableModel> sorter, int s) {
|
67 |
ilm |
625 |
if (s >= 0 && s < model.getRowCount()) {
|
|
|
626 |
final SQLRequestLog rowAt = model.getRowAt(sorter.convertRowIndexToModel(s));
|
|
|
627 |
String req = rowAt.getQuery();
|
|
|
628 |
for (SQLRequestLog l : list) {
|
|
|
629 |
l.isHighlighted = l.getQuery().equals(req);
|
|
|
630 |
}
|
|
|
631 |
model.fireTableRowsUpdated(0, model.getRowCount() - 1);
|
|
|
632 |
}
|
|
|
633 |
}
|
174 |
ilm |
634 |
|
|
|
635 |
public static void dump(PrintStream out) {
|
|
|
636 |
final DecimalFormat dformat = new DecimalFormat("##0.00");
|
|
|
637 |
for (SQLRequestLog log : list) {
|
|
|
638 |
out.print(dformat.format(log.getDurationTotalNano() / 1000000D) + " ms ");
|
|
|
639 |
out.print("\t");
|
|
|
640 |
out.print(log.getQuery());
|
|
|
641 |
out.println();
|
|
|
642 |
}
|
|
|
643 |
|
|
|
644 |
}
|
17 |
ilm |
645 |
}
|