|
1 /* |
|
2 * Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 * Logger DataProcessor |
|
17 * |
|
18 */ |
|
19 package com.nokia.traceviewer.engine.dataprocessor; |
|
20 |
|
21 import java.io.FileNotFoundException; |
|
22 import java.io.FileOutputStream; |
|
23 import java.io.FileWriter; |
|
24 import java.io.IOException; |
|
25 import java.io.PrintWriter; |
|
26 import java.nio.ByteBuffer; |
|
27 import java.nio.channels.FileChannel; |
|
28 import java.util.Iterator; |
|
29 |
|
30 import org.eclipse.core.runtime.IPath; |
|
31 import org.eclipse.core.runtime.Path; |
|
32 |
|
33 import com.nokia.traceviewer.action.TraceViewerActionUtils; |
|
34 import com.nokia.traceviewer.engine.TraceProperties; |
|
35 import com.nokia.traceviewer.engine.TraceViewerGlobals; |
|
36 import com.nokia.traceviewer.engine.TraceViewerUtils; |
|
37 |
|
38 /** |
|
39 * Logger DataProcessor |
|
40 * |
|
41 */ |
|
42 public final class Logger implements DataProcessor { |
|
43 |
|
44 /** |
|
45 * Equals char |
|
46 */ |
|
47 private static final char EQUALS_CHAR = '='; |
|
48 |
|
49 /** |
|
50 * Parameter char |
|
51 */ |
|
52 private static final char PARAMETER_CHAR = 'p'; |
|
53 |
|
54 /** |
|
55 * Machine readable time tag |
|
56 */ |
|
57 private static final String TAG_TIME = "time="; //$NON-NLS-1$ |
|
58 |
|
59 /** |
|
60 * Machine readable CPU ID tag |
|
61 */ |
|
62 private static final String TAG_CPU_ID = "cpuID="; //$NON-NLS-1$ |
|
63 |
|
64 /** |
|
65 * Machine readable Thread ID tag |
|
66 */ |
|
67 private static final String TAG_THREAD_ID = "threadID="; //$NON-NLS-1$ |
|
68 |
|
69 /** |
|
70 * Component ID tag |
|
71 */ |
|
72 private static final String TAG_COMPONENT_ID = "compID="; //$NON-NLS-1$ |
|
73 |
|
74 /** |
|
75 * Group ID tag |
|
76 */ |
|
77 private static final String TAG_GROUP_ID = "groupID="; //$NON-NLS-1$ |
|
78 |
|
79 /** |
|
80 * Trace ID tag |
|
81 */ |
|
82 private static final String TAG_TRACE_ID = "traceID="; //$NON-NLS-1$ |
|
83 |
|
84 /** |
|
85 * Trace text tag |
|
86 */ |
|
87 private static final String TAG_TRACE_TEXT = "trace="; //$NON-NLS-1$ |
|
88 |
|
89 /** |
|
90 * Data tag |
|
91 */ |
|
92 private static final String DATA_TAG = "data="; //$NON-NLS-1$ |
|
93 |
|
94 /** |
|
95 * Comment tag |
|
96 */ |
|
97 private static final String COMMENT_TAG = "comment="; //$NON-NLS-1$ |
|
98 |
|
99 /** |
|
100 * Empty string |
|
101 */ |
|
102 private static final String EMPTY = ""; //$NON-NLS-1$ |
|
103 |
|
104 /** |
|
105 * Start bracket tag |
|
106 */ |
|
107 private static final char TAG_START_BRACKET = '['; |
|
108 |
|
109 /** |
|
110 * End bracket tag |
|
111 */ |
|
112 private static final char TAG_END_BRACKET = ']'; |
|
113 |
|
114 /** |
|
115 * Hyphen char |
|
116 */ |
|
117 private static final char HYPHEN_CHAR = '-'; |
|
118 |
|
119 /** |
|
120 * Underscore char |
|
121 */ |
|
122 private static final char UNDERSCORE_CHAR = '_'; |
|
123 |
|
124 /** |
|
125 * Semicolon char |
|
126 */ |
|
127 private static final char SEMICOLON_CHAR = ';'; |
|
128 |
|
129 /** |
|
130 * End line character \r |
|
131 */ |
|
132 private static final char ENDLINE_R = '\r'; |
|
133 |
|
134 /** |
|
135 * End line character \n |
|
136 */ |
|
137 private static final char ENDLINE_N = '\n'; |
|
138 |
|
139 /** |
|
140 * Tabulator character |
|
141 */ |
|
142 private static final char TABULATOR = '\t'; |
|
143 |
|
144 /** |
|
145 * Writer to be used for writing |
|
146 */ |
|
147 private PrintWriter plainOutput; |
|
148 |
|
149 /** |
|
150 * Filechannel where binary log is written |
|
151 */ |
|
152 private FileChannel binaryOutput; |
|
153 |
|
154 /** |
|
155 * Logging in plain text |
|
156 */ |
|
157 private boolean plainLogging; |
|
158 |
|
159 /** |
|
160 * Logging in binary |
|
161 */ |
|
162 private boolean binaryLogging; |
|
163 |
|
164 /** |
|
165 * Path to plain text log file |
|
166 */ |
|
167 private String plainLogPath; |
|
168 |
|
169 /** |
|
170 * Path to binary log file |
|
171 */ |
|
172 private String binaryLogPath; |
|
173 |
|
174 /** |
|
175 * Omitting timestamp or not |
|
176 */ |
|
177 private boolean omitTimestamps; |
|
178 |
|
179 /** |
|
180 * Machine readable log file |
|
181 */ |
|
182 private boolean machineReadable; |
|
183 |
|
184 /** |
|
185 * Tells if a log file is opened |
|
186 */ |
|
187 private boolean logFileOpened; |
|
188 |
|
189 /** |
|
190 * Opened log file path |
|
191 */ |
|
192 private String openedLogFilePath; |
|
193 |
|
194 /* |
|
195 * (non-Javadoc) |
|
196 * |
|
197 * @see |
|
198 * com.nokia.traceviewer.engine.DataProcessor#processData(com.nokia.traceviewer |
|
199 * .engine.TraceProperties) |
|
200 */ |
|
201 public void processData(TraceProperties properties) { |
|
202 if (!properties.traceConfiguration.isFilteredOut() |
|
203 && !properties.traceConfiguration.isScrolledTrace() |
|
204 && !properties.traceConfiguration.isTriggeredOut()) { |
|
205 |
|
206 // Logging as plain text |
|
207 if (plainLogging) { |
|
208 |
|
209 String trace = createPlainTextTrace(properties); |
|
210 |
|
211 // Write the trace |
|
212 if (trace != null) { |
|
213 plainOutput.write(trace); |
|
214 } |
|
215 } |
|
216 |
|
217 // Binary logging |
|
218 if (binaryLogging) { |
|
219 try { |
|
220 if (properties.byteBuffer != null && binaryOutput != null) { |
|
221 |
|
222 // Write all parts of multipart trace |
|
223 if (properties.bTraceInformation |
|
224 .getMultiPartTraceParts() != null) { |
|
225 Iterator<byte[]> i = properties.bTraceInformation |
|
226 .getMultiPartTraceParts().getTraceParts() |
|
227 .iterator(); |
|
228 |
|
229 while (i.hasNext()) { |
|
230 byte[] byteArr = i.next(); |
|
231 binaryOutput.write(ByteBuffer.wrap(byteArr)); |
|
232 } |
|
233 } else { |
|
234 |
|
235 // Write the message to file |
|
236 int position = properties.byteBuffer.position(); |
|
237 int limit = properties.byteBuffer.limit(); |
|
238 properties.byteBuffer.limit(properties.messageStart |
|
239 + properties.messageLength); |
|
240 properties.byteBuffer |
|
241 .position(properties.messageStart); |
|
242 |
|
243 binaryOutput.write(properties.byteBuffer); |
|
244 properties.byteBuffer.limit(limit); |
|
245 properties.byteBuffer.position(position); |
|
246 } |
|
247 } |
|
248 } catch (IOException e) { |
|
249 e.printStackTrace(); |
|
250 } |
|
251 } |
|
252 } |
|
253 } |
|
254 |
|
255 /** |
|
256 * Create plain text trace |
|
257 * |
|
258 * @param properties |
|
259 * trace properties |
|
260 * @return plain text trace string or null if this trace should not be |
|
261 * logged |
|
262 */ |
|
263 private String createPlainTextTrace(TraceProperties properties) { |
|
264 String ret = null; |
|
265 StringBuffer trace = null; |
|
266 |
|
267 // Normal ASCII trace log |
|
268 if (!machineReadable && !properties.binaryTrace) { |
|
269 |
|
270 // If omitting timestamps, don't write them |
|
271 if (omitTimestamps || properties.timestampString == null) { |
|
272 int traceLen = properties.traceString.length() + 1; |
|
273 trace = new StringBuffer(traceLen); |
|
274 if (properties.bTraceInformation.isTraceMissing()) { |
|
275 trace.append(TraceViewerActionUtils.TRACES_DROPPED_MSG); |
|
276 } |
|
277 trace.append(properties.traceString); |
|
278 trace.append(ENDLINE_N); |
|
279 |
|
280 // Write timestamp |
|
281 } else { |
|
282 StringBuffer timeFromPreviousSB = TraceViewerGlobals |
|
283 .getTraceViewer().getDataProcessorAccess() |
|
284 .getTimestampParser().getTimeFromPreviousString( |
|
285 properties.timeFromPreviousTrace); |
|
286 int traceLen = properties.timestampString.length() + 1 |
|
287 + timeFromPreviousSB.length() |
|
288 + properties.traceString.length() + 1; |
|
289 trace = new StringBuffer(traceLen); |
|
290 if (properties.bTraceInformation.isTraceMissing()) { |
|
291 trace.append(TraceViewerActionUtils.TRACES_DROPPED_MSG); |
|
292 } |
|
293 trace.append(properties.timestampString); |
|
294 trace.append(timeFromPreviousSB); |
|
295 trace.append(TABULATOR); |
|
296 trace.append(properties.traceString); |
|
297 trace.append(ENDLINE_N); |
|
298 } |
|
299 |
|
300 // Machine readable log file |
|
301 } else if (machineReadable) { |
|
302 |
|
303 // Create buffer three times as big as original trace text |
|
304 if (properties.traceString != null) { |
|
305 trace = new StringBuffer(properties.traceString.length() * 3); |
|
306 } else { |
|
307 trace = new StringBuffer(); |
|
308 } |
|
309 |
|
310 // Get trace variables |
|
311 int cid = properties.information.getComponentId(); |
|
312 int gid = properties.information.getGroupId(); |
|
313 int tid = properties.information.getTraceId(); |
|
314 |
|
315 // Timestamp |
|
316 trace.append(TAG_TIME); |
|
317 if (properties.timestampString != null) { |
|
318 trace.append(properties.timestampString); |
|
319 } else { |
|
320 trace.append(properties.timestamp); |
|
321 } |
|
322 trace.append(SEMICOLON_CHAR); |
|
323 |
|
324 // CPU ID |
|
325 trace.append(TAG_CPU_ID); |
|
326 if (properties.bTraceInformation.getCpuId() != -1) { |
|
327 trace.append(properties.bTraceInformation.getCpuId()); |
|
328 } else { |
|
329 trace.append(HYPHEN_CHAR); |
|
330 } |
|
331 trace.append(SEMICOLON_CHAR); |
|
332 |
|
333 // Thread ID |
|
334 trace.append(TAG_THREAD_ID); |
|
335 if (properties.bTraceInformation.getThreadId() != 0) { |
|
336 trace.append(properties.bTraceInformation.getThreadId()); |
|
337 } else { |
|
338 trace.append(HYPHEN_CHAR); |
|
339 } |
|
340 trace.append(SEMICOLON_CHAR); |
|
341 |
|
342 // Get Component, Group and Trace names |
|
343 String[] names = TraceViewerGlobals.getDecodeProvider() |
|
344 .getComponentGroupTraceName(cid, gid, tid); |
|
345 |
|
346 // Component ID |
|
347 String componentName = names[0]; |
|
348 if (componentName == null) { |
|
349 componentName = EMPTY; |
|
350 } |
|
351 trace.append(TAG_COMPONENT_ID); |
|
352 trace |
|
353 .append(componentName.replace(SEMICOLON_CHAR, |
|
354 UNDERSCORE_CHAR)); |
|
355 trace.append(TAG_START_BRACKET); |
|
356 trace.append(cid); |
|
357 trace.append(TAG_END_BRACKET); |
|
358 trace.append(SEMICOLON_CHAR); |
|
359 |
|
360 // Group ID |
|
361 String groupName = names[1]; |
|
362 if (groupName == null) { |
|
363 groupName = EMPTY; |
|
364 } |
|
365 trace.append(TAG_GROUP_ID); |
|
366 trace.append(groupName.replace(SEMICOLON_CHAR, UNDERSCORE_CHAR)); |
|
367 trace.append(TAG_START_BRACKET); |
|
368 trace.append(gid); |
|
369 trace.append(TAG_END_BRACKET); |
|
370 trace.append(SEMICOLON_CHAR); |
|
371 |
|
372 // Trace ID |
|
373 String traceName = names[2]; |
|
374 if (traceName == null) { |
|
375 traceName = EMPTY; |
|
376 } |
|
377 trace.append(TAG_TRACE_ID); |
|
378 trace.append(traceName.replace(SEMICOLON_CHAR, UNDERSCORE_CHAR)); |
|
379 trace.append(TAG_START_BRACKET); |
|
380 trace.append(tid); |
|
381 trace.append(TAG_END_BRACKET); |
|
382 trace.append(SEMICOLON_CHAR); |
|
383 |
|
384 // Parameters |
|
385 for (int i = 0; i < properties.parameters.size(); i++) { |
|
386 trace.append(PARAMETER_CHAR); |
|
387 trace.append(i + 1); |
|
388 trace.append(EQUALS_CHAR); |
|
389 trace.append(properties.parameters.get(i).replace( |
|
390 SEMICOLON_CHAR, UNDERSCORE_CHAR)); |
|
391 trace.append(SEMICOLON_CHAR); |
|
392 } |
|
393 |
|
394 // Trace comment |
|
395 if (properties.traceComment != null) { |
|
396 trace.append(COMMENT_TAG); |
|
397 trace.append(properties.traceComment); |
|
398 trace.append(SEMICOLON_CHAR); |
|
399 } |
|
400 |
|
401 // Trace string |
|
402 if (properties.traceString != null) { |
|
403 trace.append(TAG_TRACE_TEXT); |
|
404 trace.append(properties.traceString.replace(SEMICOLON_CHAR, |
|
405 UNDERSCORE_CHAR)); |
|
406 trace.append(SEMICOLON_CHAR); |
|
407 // Trace as hex |
|
408 } else { |
|
409 // Get data as hex |
|
410 String hexTrace = TraceViewerUtils.getTraceAsHexString( |
|
411 properties.byteBuffer, properties.dataStart, |
|
412 properties.dataLength, false); |
|
413 trace.append(DATA_TAG); |
|
414 trace.append(hexTrace); |
|
415 trace.append(SEMICOLON_CHAR); |
|
416 |
|
417 } |
|
418 |
|
419 trace.append(ENDLINE_R); |
|
420 trace.append(ENDLINE_N); |
|
421 } |
|
422 |
|
423 if (trace != null) { |
|
424 ret = trace.toString(); |
|
425 } |
|
426 |
|
427 return ret; |
|
428 } |
|
429 |
|
430 /** |
|
431 * Constructor |
|
432 */ |
|
433 public Logger() { |
|
434 plainLogging = false; |
|
435 binaryLogging = false; |
|
436 omitTimestamps = false; |
|
437 plainLogPath = EMPTY; |
|
438 binaryLogPath = EMPTY; |
|
439 } |
|
440 |
|
441 /** |
|
442 * Flushes data |
|
443 */ |
|
444 public void flush() { |
|
445 if (plainOutput != null) { |
|
446 plainOutput.flush(); |
|
447 } |
|
448 } |
|
449 |
|
450 /** |
|
451 * Gets plain text logging status |
|
452 * |
|
453 * @return status of plain text logging |
|
454 */ |
|
455 public boolean isPlainLogging() { |
|
456 return plainLogging; |
|
457 } |
|
458 |
|
459 /** |
|
460 * Gets plain text log file path |
|
461 * |
|
462 * @return plainLogPath |
|
463 */ |
|
464 public String getPlainLogPath() { |
|
465 return plainLogPath; |
|
466 } |
|
467 |
|
468 /** |
|
469 * Gets binary log file path |
|
470 * |
|
471 * @return binaryLogPath |
|
472 */ |
|
473 public String getBinaryLogPath() { |
|
474 return binaryLogPath; |
|
475 } |
|
476 |
|
477 /** |
|
478 * Gets logging status |
|
479 * |
|
480 * @return status of binary logging |
|
481 */ |
|
482 public boolean isBinLogging() { |
|
483 return binaryLogging; |
|
484 } |
|
485 |
|
486 /** |
|
487 * Starts plain text logging |
|
488 * |
|
489 * @param filename |
|
490 * file name where to save |
|
491 * @param omitTimestamp |
|
492 * true if timestamps should be omitted |
|
493 * @param machineReadable |
|
494 * true if log file should be machine readable |
|
495 * @return status of starting of logging |
|
496 */ |
|
497 public boolean startPlainTextLogging(String filename, |
|
498 boolean omitTimestamp, boolean machineReadable) { |
|
499 plainLogPath = filename; |
|
500 this.omitTimestamps = omitTimestamp; |
|
501 this.machineReadable = machineReadable; |
|
502 |
|
503 // Build file channel |
|
504 boolean success = buildPlainFileWriter(); |
|
505 plainLogging = true; |
|
506 return success; |
|
507 } |
|
508 |
|
509 /** |
|
510 * Stops plain text logging |
|
511 * |
|
512 * @return status of stopPlainTextLogging |
|
513 */ |
|
514 public boolean stopPlainTextLogging() { |
|
515 plainOutput.close(); |
|
516 plainLogging = false; |
|
517 |
|
518 // Export possible comments |
|
519 TraceViewerGlobals.getTraceViewer().getDataProcessorAccess() |
|
520 .getTraceCommentHandler().exportTraceComments(plainLogPath); |
|
521 |
|
522 return true; |
|
523 } |
|
524 |
|
525 /** |
|
526 * Start binary logging |
|
527 * |
|
528 * @param filename |
|
529 * file name |
|
530 * @return status of binary logging |
|
531 */ |
|
532 public boolean startBinaryLogging(String filename) { |
|
533 boolean success = false; |
|
534 try { |
|
535 binaryLogPath = filename; |
|
536 |
|
537 // Build file channel |
|
538 FileOutputStream outputFile = new FileOutputStream(binaryLogPath); |
|
539 |
|
540 binaryOutput = outputFile.getChannel(); |
|
541 binaryLogging = true; |
|
542 success = true; |
|
543 } catch (FileNotFoundException e) { |
|
544 e.printStackTrace(); |
|
545 } |
|
546 return success; |
|
547 } |
|
548 |
|
549 /** |
|
550 * Stops binary logging |
|
551 * |
|
552 * @return status of stopBinLogging |
|
553 */ |
|
554 public boolean stopBinLogging() { |
|
555 binaryLogging = false; |
|
556 try { |
|
557 binaryOutput.close(); |
|
558 } catch (IOException e) { |
|
559 e.printStackTrace(); |
|
560 } |
|
561 |
|
562 // Export possible comments |
|
563 TraceViewerGlobals.getTraceViewer().getDataProcessorAccess() |
|
564 .getTraceCommentHandler().exportTraceComments(binaryLogPath); |
|
565 |
|
566 return true; |
|
567 } |
|
568 |
|
569 /** |
|
570 * Opens log file |
|
571 * |
|
572 * @param path |
|
573 * path to log file |
|
574 * @param binary |
|
575 * binary file |
|
576 */ |
|
577 public void openLogFile(String path, boolean binary) { |
|
578 TraceViewerGlobals.getTraceViewer().getDataReaderAccess().openLogFile( |
|
579 path, binary); |
|
580 openedLogFilePath = path; |
|
581 } |
|
582 |
|
583 /** |
|
584 * Builds the plain file writer |
|
585 * |
|
586 * @return status of building plain text file |
|
587 */ |
|
588 public boolean buildPlainFileWriter() { |
|
589 boolean success = false; |
|
590 |
|
591 try { |
|
592 plainOutput = new PrintWriter(new FileWriter(plainLogPath)); |
|
593 success = true; |
|
594 } catch (FileNotFoundException e) { |
|
595 e.printStackTrace(); |
|
596 } catch (IOException e) { |
|
597 e.printStackTrace(); |
|
598 } |
|
599 |
|
600 return success; |
|
601 } |
|
602 |
|
603 /** |
|
604 * Tells if log file is opened |
|
605 * |
|
606 * @return true if log file is opened |
|
607 */ |
|
608 public boolean isLogFileOpened() { |
|
609 return logFileOpened; |
|
610 } |
|
611 |
|
612 /** |
|
613 * Sets the log file opened variable |
|
614 * |
|
615 * @param logFileOpened |
|
616 * status of log file opened |
|
617 */ |
|
618 public void setLogFileOpened(boolean logFileOpened) { |
|
619 this.logFileOpened = logFileOpened; |
|
620 |
|
621 if (!logFileOpened) { |
|
622 openedLogFilePath = null; |
|
623 } |
|
624 } |
|
625 |
|
626 /** |
|
627 * Gets currently opened log file path |
|
628 * |
|
629 * @return currently opened log file path or null if no log file is open |
|
630 */ |
|
631 public String getOpenedLogFilePath() { |
|
632 return openedLogFilePath; |
|
633 } |
|
634 |
|
635 /** |
|
636 * Gets currently opened log file name |
|
637 * |
|
638 * @return currently opened log file name or null if no log file is open |
|
639 */ |
|
640 public String getOpenedLogFileName() { |
|
641 String fileName = null; |
|
642 |
|
643 if (openedLogFilePath != null) { |
|
644 IPath filePath = new Path(openedLogFilePath); |
|
645 fileName = filePath.lastSegment(); |
|
646 } |
|
647 |
|
648 return fileName; |
|
649 } |
|
650 } |