001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.loggers.debug;
028
029 import org.opends.server.api.DebugLogPublisher;
030 import org.opends.server.api.ProtocolElement;
031 import org.opends.server.types.DebugLogCategory;
032 import org.opends.server.types.DebugLogLevel;
033 import org.opends.server.loggers.LogLevel;
034 import org.opends.server.loggers.LogCategory;
035
036 import java.util.Map;
037 import java.nio.ByteBuffer;
038
039 import com.sleepycat.je.OperationStatus;
040 import com.sleepycat.je.Transaction;
041 import com.sleepycat.je.DatabaseEntry;
042 import com.sleepycat.je.Database;
043
044 /**
045 * Class for source-code tracing at the method level.
046 *
047 * One DebugTracer instance exists for each Java class using tracing.
048 * Tracer must be registered with the DebugLogger.
049 *
050 * Logging is always done at a level basis, with debug log messages
051 * exceeding the trace threshold being traced, others being discarded.
052 */
053
054 public class DebugTracer
055 {
056 // The class this aspect traces.
057 private String className;
058
059 /**
060 * A class that represents a settings cache entry.
061 */
062 private class PublisherSettings
063 {
064 DebugLogPublisher debugPublisher;
065 TraceSettings classSettings;
066 Map<String, TraceSettings> methodSettings;
067 }
068
069 PublisherSettings[] publisherSettings;
070
071 /**
072 * Construct a new DebugTracer object with cached settings obtained from
073 * the provided array of publishers.
074 *
075 * @param publishers The array of publishers to obtain the settings from.
076 */
077 @SuppressWarnings("unchecked")
078 DebugTracer(DebugLogPublisher[] publishers)
079 {
080 // Trim off the debug logging and non OpenDS frames.
081 StackTraceElement callerFrame =
082 getCallerFrame(Thread.currentThread().getStackTrace());
083
084 // TODO: What if this is null or 0 length?
085 if(callerFrame != null)
086 {
087 // The caller should be the first item on the stack.
088 className = callerFrame.getClassName();
089 }
090
091 publisherSettings = new PublisherSettings[publishers.length];
092
093 // Get the settings from all publishers.
094 for(int i = 0; i < publishers.length; i++)
095 {
096 DebugLogPublisher publisher = publishers[i];
097 PublisherSettings settings = new PublisherSettings();
098
099 settings.debugPublisher = publisher;
100 settings.classSettings = publisher.getClassSettings(className);
101
102 // For some reason, the compiler doesn't see that
103 // debugLogPublihser.getMethodSettings returns a parameterized Map.
104 // This problem goes away if a parameterized verson of DebugLogPublisher
105 // is used. However, we can't not use reflection to instantiate a generic
106 // DebugLogPublisher<? extends DebugLogPublisherCfg> type. The only thing
107 // we can do is to just supress the compiler warnings.
108 settings.methodSettings = publisher.getMethodSettings(className);
109
110 publisherSettings[i] = settings;
111 }
112 }
113
114 /**
115 * Log an constructor execution event.
116 *
117 * @param level The level of the message being logged.
118 * @param args The arguments passed to the constructor.
119 */
120 public void debugConstructor(LogLevel level, Object... args)
121 {
122 if(DebugLogger.debugEnabled())
123 {
124 StackTraceElement[] stackTrace = null;
125 StackTraceElement[] filteredStackTrace = null;
126 StackTraceElement callerFrame = null;
127 for (PublisherSettings settings : publisherSettings)
128 {
129 TraceSettings activeSettings = settings.classSettings;
130 Map<String, TraceSettings> methodSettings = settings.methodSettings;
131
132 if (shouldLog(level, DebugLogCategory.CONSTRUCTOR,
133 activeSettings) || methodSettings != null)
134 {
135 if(stackTrace == null)
136 {
137 stackTrace = Thread.currentThread().getStackTrace();
138 }
139 if (callerFrame == null)
140 {
141 callerFrame = getCallerFrame(stackTrace);
142 }
143
144 String signature = callerFrame.getMethodName();
145
146 // Specific method settings still could exist. Try getting
147 // the settings for this method.
148 if(methodSettings != null)
149 {
150 TraceSettings mSettings = methodSettings.get(signature);
151
152 if (mSettings == null)
153 {
154 // Try looking for an undecorated method name
155 int idx = signature.indexOf('(');
156 if (idx != -1)
157 {
158 mSettings =
159 methodSettings.get(signature.substring(0, idx));
160 }
161 }
162
163 // If this method does have a specific setting and it is not
164 // suppose to be logged, continue.
165 if (mSettings != null)
166 {
167 if(!shouldLog(level, DebugLogCategory.CONSTRUCTOR,
168 mSettings))
169 {
170 continue;
171 }
172 else
173 {
174 activeSettings = mSettings;
175 }
176 }
177 }
178
179 String sl = callerFrame.getFileName() + ":" +
180 callerFrame.getLineNumber();
181
182 if (activeSettings.noArgs)
183 {
184 args = null;
185 }
186
187 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
188 {
189 filteredStackTrace =
190 DebugStackTraceFormatter.SMART_FRAME_FILTER.
191 getFilteredStackTrace(stackTrace);
192 }
193
194 settings.debugPublisher.traceConstructor(level,
195 activeSettings, signature,
196 sl, args,
197 filteredStackTrace);
198 }
199 }
200 }
201 }
202
203 /**
204 * Log an non static method entry event.
205 *
206 * @param level The level of the message being logged.
207 * @param obj The object type instance the method is a member of.
208 * @param args The arguments passed to the method.
209 */
210 public void debugMethodEntry(LogLevel level, Object obj, Object... args)
211 {
212 if(DebugLogger.debugEnabled())
213 {
214 StackTraceElement[] stackTrace = null;
215 StackTraceElement[] filteredStackTrace = null;
216 StackTraceElement callerFrame = null;
217 for (PublisherSettings settings : publisherSettings)
218 {
219 TraceSettings activeSettings = settings.classSettings;
220 Map<String, TraceSettings> methodSettings = settings.methodSettings;
221
222 if (shouldLog(level, DebugLogCategory.ENTER,
223 activeSettings) || methodSettings != null)
224 {
225 if(stackTrace == null)
226 {
227 stackTrace = Thread.currentThread().getStackTrace();
228 }
229 if (callerFrame == null)
230 {
231 callerFrame = getCallerFrame(stackTrace);
232 }
233
234 String signature = callerFrame.getMethodName();
235
236 // Specific method settings still could exist. Try getting
237 // the settings for this method.
238 if(methodSettings != null)
239 {
240 TraceSettings mSettings = methodSettings.get(signature);
241
242 if (mSettings == null)
243 {
244 // Try looking for an undecorated method name
245 int idx = signature.indexOf('(');
246 if (idx != -1)
247 {
248 mSettings =
249 methodSettings.get(signature.substring(0, idx));
250 }
251 }
252
253 // If this method does have a specific setting and it is not
254 // suppose to be logged, continue.
255 if (mSettings != null)
256 {
257 if(!shouldLog(level, DebugLogCategory.ENTER,
258 mSettings))
259 {
260 continue;
261 }
262 else
263 {
264 activeSettings = mSettings;
265 }
266 }
267 }
268
269 String sl = callerFrame.getFileName() + ":" +
270 callerFrame.getLineNumber();
271
272 if (activeSettings.noArgs)
273 {
274 args = null;
275 }
276
277 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
278 {
279 filteredStackTrace =
280 DebugStackTraceFormatter.SMART_FRAME_FILTER.
281 getFilteredStackTrace(stackTrace);
282 }
283
284 settings.debugPublisher.traceMethodEntry(level,
285 activeSettings, signature,
286 sl, obj, args,
287 filteredStackTrace);
288 }
289 }
290 }
291 }
292
293 /**
294 * Log an static method entry event.
295 *
296 * @param level The level of the message being logged.
297 * @param args The arguments passed to the method.
298 */
299 public void debugStaticMethodEntry(LogLevel level, Object... args)
300 {
301 if(DebugLogger.debugEnabled())
302 {
303 StackTraceElement[] stackTrace = null;
304 StackTraceElement[] filteredStackTrace = null;
305 StackTraceElement callerFrame = null;
306 for (PublisherSettings settings : publisherSettings)
307 {
308 TraceSettings activeSettings = settings.classSettings;
309 Map<String, TraceSettings> methodSettings = settings.methodSettings;
310
311 if (shouldLog(level, DebugLogCategory.ENTER,
312 activeSettings) || methodSettings != null)
313 {
314 if(stackTrace == null)
315 {
316 stackTrace = Thread.currentThread().getStackTrace();
317 }
318 if (callerFrame == null)
319 {
320 callerFrame = getCallerFrame(stackTrace);
321 }
322
323 String signature = callerFrame.getMethodName();
324
325 // Specific method settings still could exist. Try getting
326 // the settings for this method.
327 if(methodSettings != null)
328 {
329 TraceSettings mSettings = methodSettings.get(signature);
330
331 if (mSettings == null)
332 {
333 // Try looking for an undecorated method name
334 int idx = signature.indexOf('(');
335 if (idx != -1)
336 {
337 mSettings =
338 methodSettings.get(signature.substring(0, idx));
339 }
340 }
341
342 // If this method does have a specific setting and it is not
343 // suppose to be logged, continue.
344 if (mSettings != null)
345 {
346 if(!shouldLog(level, DebugLogCategory.ENTER,
347 mSettings))
348 {
349 continue;
350 }
351 else
352 {
353 activeSettings = mSettings;
354 }
355 }
356 }
357
358 String sl = callerFrame.getFileName() + ":" +
359 callerFrame.getLineNumber();
360
361 if (activeSettings.noArgs)
362 {
363 args = null;
364 }
365
366 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
367 {
368 filteredStackTrace =
369 DebugStackTraceFormatter.SMART_FRAME_FILTER.
370 getFilteredStackTrace(stackTrace);
371 }
372
373 settings.debugPublisher.traceStaticMethodEntry(level,
374 activeSettings,
375 signature, sl, args,
376 filteredStackTrace);
377 }
378 }
379 }
380 }
381
382 /**
383 * Log a return from a method call event.
384 *
385 * @param level The level of the message being logged.
386 * @param ret The value being returned from the method.
387 */
388 public void debugReturn(LogLevel level, Object ret)
389 {
390 if(DebugLogger.debugEnabled())
391 {
392 StackTraceElement[] stackTrace = null;
393 StackTraceElement[] filteredStackTrace = null;
394 StackTraceElement callerFrame = null;
395 for (PublisherSettings settings : publisherSettings)
396 {
397 TraceSettings activeSettings = settings.classSettings;
398 Map<String, TraceSettings> methodSettings = settings.methodSettings;
399
400 if (shouldLog(level, DebugLogCategory.ENTER,
401 activeSettings) || methodSettings != null)
402 {
403 if(stackTrace == null)
404 {
405 stackTrace = Thread.currentThread().getStackTrace();
406 }
407 if (callerFrame == null)
408 {
409 callerFrame = getCallerFrame(stackTrace);
410 }
411
412 String signature = callerFrame.getMethodName();
413
414 // Specific method settings still could exist. Try getting
415 // the settings for this method.
416 if(methodSettings != null)
417 {
418 TraceSettings mSettings = methodSettings.get(signature);
419
420 if (mSettings == null)
421 {
422 // Try looking for an undecorated method name
423 int idx = signature.indexOf('(');
424 if (idx != -1)
425 {
426 mSettings =
427 methodSettings.get(signature.substring(0, idx));
428 }
429 }
430
431 // If this method does have a specific setting and it is not
432 // suppose to be logged, continue.
433 if (mSettings != null)
434 {
435 if(!shouldLog(level, DebugLogCategory.ENTER,
436 mSettings))
437 {
438 continue;
439 }
440 else
441 {
442 activeSettings = mSettings;
443 }
444 }
445 }
446
447 String sl = callerFrame.getFileName() + ":" +
448 callerFrame.getLineNumber();
449
450 if (activeSettings.noRetVal)
451 {
452 ret = null;
453 }
454
455 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
456 {
457 filteredStackTrace =
458 DebugStackTraceFormatter.SMART_FRAME_FILTER.
459 getFilteredStackTrace(stackTrace);
460 }
461
462 settings.debugPublisher.traceReturn(level,
463 activeSettings, signature,
464 sl, ret,
465 filteredStackTrace);
466 }
467 }
468 }
469 }
470
471 /**
472 * Log an exception thrown from a method.
473 *
474 * @param level The level of the message being logged.
475 * @param ex The exception being thrown.
476 */
477 public void debugThrown(LogLevel level, Throwable ex)
478 {
479 if(DebugLogger.debugEnabled())
480 {
481 StackTraceElement[] stackTrace = null;
482 StackTraceElement[] filteredStackTrace = null;
483 StackTraceElement callerFrame = null;
484 for (PublisherSettings settings : publisherSettings)
485 {
486 TraceSettings activeSettings = settings.classSettings;
487 Map<String, TraceSettings> methodSettings = settings.methodSettings;
488
489 if (shouldLog(level, DebugLogCategory.THROWN,
490 activeSettings) || methodSettings != null)
491 {
492 if(stackTrace == null)
493 {
494 stackTrace = Thread.currentThread().getStackTrace();
495 }
496 if (callerFrame == null)
497 {
498 callerFrame = getCallerFrame(stackTrace);
499 }
500
501 String signature = callerFrame.getMethodName();
502
503 // Specific method settings still could exist. Try getting
504 // the settings for this method.
505 if(methodSettings != null)
506 {
507 TraceSettings mSettings = methodSettings.get(signature);
508
509 if (mSettings == null)
510 {
511 // Try looking for an undecorated method name
512 int idx = signature.indexOf('(');
513 if (idx != -1)
514 {
515 mSettings =
516 methodSettings.get(signature.substring(0, idx));
517 }
518 }
519
520 // If this method does have a specific setting and it is not
521 // suppose to be logged, continue.
522 if (mSettings != null)
523 {
524 if(!shouldLog(level, DebugLogCategory.THROWN,
525 mSettings))
526 {
527 continue;
528 }
529 else
530 {
531 activeSettings = mSettings;
532 }
533 }
534 }
535
536 String sl = callerFrame.getFileName() + ":" +
537 callerFrame.getLineNumber();
538
539 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
540 {
541 filteredStackTrace =
542 DebugStackTraceFormatter.SMART_FRAME_FILTER.
543 getFilteredStackTrace(ex.getStackTrace());
544 }
545
546 settings.debugPublisher.traceThrown(level, activeSettings, signature,
547 sl, ex, filteredStackTrace);
548 }
549 }
550 }
551 }
552
553 /**
554 * Log an arbitrary event at the verbose level.
555 * Same as debugMessage(DebugLogLevel.ERROR, msg)
556 *
557 * @param msg message to format and log.
558 */
559 public void debugVerbose(String msg)
560 {
561 debugMessage(DebugLogLevel.VERBOSE, msg, new Object[]{});
562 }
563
564 /**
565 * Log an arbitrary event at the verbose level.
566 * Same as debugMessage(DebugLogLevel.ERROR, msg, msgArgs...)
567 *
568 * @param msg message to format and log.
569 * @param msgArgs arguments to place into the format string.
570 */
571 public void debugVerbose(String msg, Object... msgArgs)
572 {
573 debugMessage(DebugLogLevel.VERBOSE, msg, msgArgs);
574 }
575
576 /**
577 * Log an arbitrary event at the info level.
578 * Same as debugMessage(DebugLogLevel.ERROR, msg)
579 *
580 * @param msg message to format and log.
581 */
582 public void debugInfo(String msg)
583 {
584 debugMessage(DebugLogLevel.INFO, msg, new Object[]{});
585 }
586
587 /**
588 * Log an arbitrary event at the info level.
589 * Same as debugMessage(DebugLogLevel.ERROR, msg, msgArgs...)
590 *
591 * @param msg message to format and log.
592 * @param msgArgs arguments to place into the format string.
593 */
594 public void debugInfo(String msg, Object... msgArgs)
595 {
596 debugMessage(DebugLogLevel.INFO, msg, msgArgs);
597 }
598
599 /**
600 * Log an arbitrary event at the warning level.
601 * Same as debugMessage(DebugLogLevel.ERROR, msg)
602 *
603 * @param msg message to format and log.
604 */
605 public void debugWarning(String msg)
606
607 {
608 debugMessage(DebugLogLevel.WARNING, msg, new Object[]{});
609 }
610
611 /**
612 * Log an arbitrary event at the warning level.
613 * Same as debugMessage(DebugLogLevel.ERROR, msg, msgArgs...)
614 *
615 * @param msg message to format and log.
616 * @param msgArgs arguments to place into the format string.
617 */
618 public void debugWarning(String msg, Object... msgArgs)
619 {
620 debugMessage(DebugLogLevel.WARNING, msg, msgArgs);
621 }
622
623 /**
624 * Log an arbitrary event at the error level.
625 * Same as debugMessage(DebugLogLevel.ERROR, msg)
626 *
627 * @param msg message to format and log.
628 */
629 public void debugError(String msg)
630
631 {
632 debugMessage(DebugLogLevel.ERROR, msg, new Object[]{});
633 }
634
635 /**
636 * Log an arbitrary event at the error level.
637 * Same as debugMessage(DebugLogLevel.ERROR, msg, msgArgs...)
638 *
639 * @param msg message to format and log.
640 * @param msgArgs arguments to place into the format string.
641 */
642 public void debugError(String msg, Object... msgArgs)
643 {
644 debugMessage(DebugLogLevel.ERROR, msg, msgArgs);
645 }
646
647 /**
648 * Log an arbitrary event.
649 *
650 * @param level the level of the log message.
651 * @param msg message to format and log.
652 */
653 public void debugMessage(LogLevel level, String msg)
654 {
655 debugMessage(level, msg, new Object[]{});
656 }
657
658 /**
659 * Log an arbitrary event.
660 *
661 * @param level the level of the log message.
662 * @param msg message to format and log.
663 * @param msgArgs arguments to place into the format string.
664 */
665 public void debugMessage(LogLevel level, String msg, Object... msgArgs)
666 {
667 if(DebugLogger.debugEnabled())
668 {
669 StackTraceElement[] stackTrace = null;
670 StackTraceElement[] filteredStackTrace = null;
671 StackTraceElement callerFrame = null;
672 for (PublisherSettings settings : publisherSettings)
673 {
674 TraceSettings activeSettings = settings.classSettings;
675 Map<String, TraceSettings> methodSettings = settings.methodSettings;
676
677 if (shouldLog(level, DebugLogCategory.MESSAGE,
678 activeSettings) || methodSettings != null)
679 {
680 if(stackTrace == null)
681 {
682 stackTrace = Thread.currentThread().getStackTrace();
683 }
684 if (callerFrame == null)
685 {
686 callerFrame = getCallerFrame(stackTrace);
687 }
688
689 String signature = callerFrame.getMethodName();
690
691 // Specific method settings still could exist. Try getting
692 // the settings for this method.
693 if(methodSettings != null)
694 {
695 TraceSettings mSettings = methodSettings.get(signature);
696
697 if (mSettings == null)
698 {
699 // Try looking for an undecorated method name
700 int idx = signature.indexOf('(');
701 if (idx != -1)
702 {
703 mSettings =
704 methodSettings.get(signature.substring(0, idx));
705 }
706 }
707
708 // If this method does have a specific setting and it is not
709 // suppose to be logged, continue.
710 if (mSettings != null)
711 {
712 if(!shouldLog(level, DebugLogCategory.MESSAGE,
713 mSettings))
714 {
715 continue;
716 }
717 else
718 {
719 activeSettings = mSettings;
720 }
721 }
722 }
723
724 String sl = callerFrame.getFileName() + ":" +
725 callerFrame.getLineNumber();
726
727 if(msgArgs != null && msgArgs.length > 0)
728 {
729 msg = String.format(msg, msgArgs);
730 }
731
732 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
733 {
734 filteredStackTrace =
735 DebugStackTraceFormatter.SMART_FRAME_FILTER.
736 getFilteredStackTrace(stackTrace);
737 }
738
739 settings.debugPublisher.traceMessage(level, activeSettings, signature,
740 sl, msg, filteredStackTrace);
741 }
742 }
743 }
744 }
745
746 /**
747 * Log an cought exception.
748 *
749 * @param level the level of the log message.
750 * @param ex the exception caught.
751 */
752 public void debugCaught(LogLevel level, Throwable ex)
753 {
754 if(DebugLogger.debugEnabled())
755 {
756 StackTraceElement[] stackTrace = null;
757 StackTraceElement[] filteredStackTrace = null;
758 StackTraceElement callerFrame = null;
759 for (PublisherSettings settings : publisherSettings)
760 {
761 TraceSettings activeSettings = settings.classSettings;
762 Map<String, TraceSettings> methodSettings = settings.methodSettings;
763
764 if (shouldLog(level, DebugLogCategory.CAUGHT,
765 activeSettings) || methodSettings != null)
766 {
767 if(stackTrace == null)
768 {
769 stackTrace = Thread.currentThread().getStackTrace();
770 }
771 if (callerFrame == null)
772 {
773 callerFrame = getCallerFrame(stackTrace);
774 }
775
776 String signature = callerFrame.getMethodName();
777
778 // Specific method settings still could exist. Try getting
779 // the settings for this method.
780 if(methodSettings != null)
781 {
782 TraceSettings mSettings = methodSettings.get(signature);
783
784 if (mSettings == null)
785 {
786 // Try looking for an undecorated method name
787 int idx = signature.indexOf('(');
788 if (idx != -1)
789 {
790 mSettings =
791 methodSettings.get(signature.substring(0, idx));
792 }
793 }
794
795 // If this method does have a specific setting and it is not
796 // suppose to be logged, continue.
797 if (mSettings != null)
798 {
799 if(!shouldLog(level, DebugLogCategory.CAUGHT,
800 mSettings))
801 {
802 continue;
803 }
804 else
805 {
806 activeSettings = mSettings;
807 }
808 }
809 }
810
811 String sl = callerFrame.getFileName() + ":" +
812 callerFrame.getLineNumber();
813
814 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
815 {
816 filteredStackTrace =
817 DebugStackTraceFormatter.SMART_FRAME_FILTER.
818 getFilteredStackTrace(ex.getStackTrace());
819 }
820
821 settings.debugPublisher.traceCaught(level, activeSettings, signature,
822 sl, ex, filteredStackTrace);
823 }
824 }
825 }
826 }
827
828 /**
829 * Log a JE database access event.
830 *
831 * @param level the level of the log message.
832 * @param status status of the JE operation.
833 * @param database the database handle.
834 * @param txn transaction handle (may be null).
835 * @param key the key to dump.
836 * @param data the data to dump.
837 */
838 public void debugJEAccess(LogLevel level, OperationStatus status,
839 Database database, Transaction txn,
840 DatabaseEntry key, DatabaseEntry data)
841 {
842 if(DebugLogger.debugEnabled())
843 {
844 StackTraceElement[] stackTrace = null;
845 StackTraceElement[] filteredStackTrace = null;
846 StackTraceElement callerFrame = null;
847 for (PublisherSettings settings : publisherSettings)
848 {
849 TraceSettings activeSettings = settings.classSettings;
850 Map<String, TraceSettings> methodSettings = settings.methodSettings;
851
852 if (shouldLog(level, DebugLogCategory.DATABASE_ACCESS,
853 activeSettings) || methodSettings != null)
854 {
855 if(stackTrace == null)
856 {
857 stackTrace = Thread.currentThread().getStackTrace();
858 }
859 if (callerFrame == null)
860 {
861 callerFrame = getCallerFrame(stackTrace);
862 }
863
864 String signature = callerFrame.getMethodName();
865
866 // Specific method settings still could exist. Try getting
867 // the settings for this method.
868 if(methodSettings != null)
869 {
870 TraceSettings mSettings = methodSettings.get(signature);
871
872 if (mSettings == null)
873 {
874 // Try looking for an undecorated method name
875 int idx = signature.indexOf('(');
876 if (idx != -1)
877 {
878 mSettings =
879 methodSettings.get(signature.substring(0, idx));
880 }
881 }
882
883 // If this method does have a specific setting and it is not
884 // suppose to be logged, continue.
885 if (mSettings != null)
886 {
887 if(!shouldLog(level, DebugLogCategory.DATABASE_ACCESS,
888 mSettings))
889 {
890 continue;
891 }
892 else
893 {
894 activeSettings = mSettings;
895 }
896 }
897 }
898
899 String sl = callerFrame.getFileName() + ":" +
900 callerFrame.getLineNumber();
901
902 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
903 {
904 filteredStackTrace =
905 DebugStackTraceFormatter.SMART_FRAME_FILTER.
906 getFilteredStackTrace(stackTrace);
907 }
908
909 settings.debugPublisher.traceJEAccess(level, activeSettings,
910 signature, sl, status, database,
911 txn, key, data,
912 filteredStackTrace);
913 }
914 }
915 }
916 }
917
918 /**
919 * Log raw data in the form of a byte array.
920 *
921 * @param level the level of the log message.
922 * @param data the data to dump.
923 */
924 public void debugData(LogLevel level, byte[] data)
925 {
926 if(DebugLogger.debugEnabled() && data != null)
927 {
928 StackTraceElement[] stackTrace = null;
929 StackTraceElement[] filteredStackTrace = null;
930 StackTraceElement callerFrame = null;
931 for (PublisherSettings settings : publisherSettings)
932 {
933 TraceSettings activeSettings = settings.classSettings;
934 Map<String, TraceSettings> methodSettings = settings.methodSettings;
935
936 if (shouldLog(level, DebugLogCategory.DATA,
937 activeSettings) || methodSettings != null)
938 {
939 if(stackTrace == null)
940 {
941 stackTrace = Thread.currentThread().getStackTrace();
942 }
943 if (callerFrame == null)
944 {
945 callerFrame = getCallerFrame(stackTrace);
946 }
947
948 String signature = callerFrame.getMethodName();
949
950 // Specific method settings still could exist. Try getting
951 // the settings for this method.
952 if(methodSettings != null)
953 {
954 TraceSettings mSettings = methodSettings.get(signature);
955
956 if (mSettings == null)
957 {
958 // Try looking for an undecorated method name
959 int idx = signature.indexOf('(');
960 if (idx != -1)
961 {
962 mSettings =
963 methodSettings.get(signature.substring(0, idx));
964 }
965 }
966
967 // If this method does have a specific setting and it is not
968 // suppose to be logged, continue.
969 if (mSettings != null)
970 {
971 if(!shouldLog(level, DebugLogCategory.DATA,
972 mSettings))
973 {
974 continue;
975 }
976 else
977 {
978 activeSettings = mSettings;
979 }
980 }
981 }
982
983 String sl = callerFrame.getFileName() + ":" +
984 callerFrame.getLineNumber();
985
986 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
987 {
988 filteredStackTrace =
989 DebugStackTraceFormatter.SMART_FRAME_FILTER.
990 getFilteredStackTrace(stackTrace);
991 }
992
993 settings.debugPublisher.traceData(level, activeSettings, signature,
994 sl, data, filteredStackTrace);
995 }
996 }
997 }
998 }
999
1000 /**
1001 * Log a protocol element.
1002 *
1003 * @param level the level of the log message.
1004 * @param element the protocol element to dump.
1005 */
1006 public void debugProtocolElement(LogLevel level, ProtocolElement element)
1007 {
1008 if(DebugLogger.debugEnabled() && element != null)
1009 {
1010 StackTraceElement[] stackTrace = null;
1011 StackTraceElement[] filteredStackTrace = null;
1012 StackTraceElement callerFrame = null;
1013 for (PublisherSettings settings : publisherSettings)
1014 {
1015 TraceSettings activeSettings = settings.classSettings;
1016 Map<String, TraceSettings> methodSettings = settings.methodSettings;
1017
1018 if (shouldLog(level, DebugLogCategory.PROTOCOL,
1019 activeSettings) || methodSettings != null)
1020 {
1021 if(stackTrace == null)
1022 {
1023 stackTrace = Thread.currentThread().getStackTrace();
1024 }
1025 if (callerFrame == null)
1026 {
1027 callerFrame = getCallerFrame(stackTrace);
1028 }
1029
1030 String signature = callerFrame.getMethodName();
1031
1032 // Specific method settings still could exist. Try getting
1033 // the settings for this method.
1034 if(methodSettings != null)
1035 {
1036 TraceSettings mSettings = methodSettings.get(signature);
1037
1038 if (mSettings == null)
1039 {
1040 // Try looking for an undecorated method name
1041 int idx = signature.indexOf('(');
1042 if (idx != -1)
1043 {
1044 mSettings =
1045 methodSettings.get(signature.substring(0, idx));
1046 }
1047 }
1048
1049 // If this method does have a specific setting and it is not
1050 // suppose to be logged, continue.
1051 if (mSettings != null)
1052 {
1053 if(!shouldLog(level, DebugLogCategory.PROTOCOL,
1054 mSettings))
1055 {
1056 continue;
1057 }
1058 else
1059 {
1060 activeSettings = mSettings;
1061 }
1062 }
1063 }
1064
1065 String sl = callerFrame.getFileName() + ":" +
1066 callerFrame.getLineNumber();
1067
1068 if (filteredStackTrace == null && activeSettings.stackDepth > 0)
1069 {
1070 filteredStackTrace =
1071 DebugStackTraceFormatter.SMART_FRAME_FILTER.
1072 getFilteredStackTrace(stackTrace);
1073 }
1074
1075 settings.debugPublisher.traceProtocolElement(level, activeSettings,
1076 signature, sl, element,
1077 filteredStackTrace);
1078 }
1079 }
1080 }
1081 }
1082
1083 /**
1084 * Log raw data in the form of a ByteBuffer.
1085 *
1086 * @param level the level of the log message.
1087 * @param buffer the data to dump.
1088 */
1089 public void debugData(LogLevel level, ByteBuffer buffer)
1090 {
1091 debugData(level, buffer.array());
1092 }
1093
1094 /**
1095 * Gets the name of the class this tracer traces.
1096 *
1097 * @return The name of the class this tracer traces.
1098 */
1099 public String getTracedClassName()
1100 {
1101 return className;
1102 }
1103
1104 /**
1105 * Update the cached settings of the tracer with the settings from the
1106 * provided publishers.
1107 *
1108 * @param publishers The array of publishers to obtain the settings from.
1109 */
1110 @SuppressWarnings("unchecked")
1111 void updateSettings(DebugLogPublisher[] publishers)
1112 {
1113 PublisherSettings[] newSettings =
1114 new PublisherSettings[publishers.length];
1115
1116 // Get the settings from all publishers.
1117 for(int i = 0; i < publishers.length; i++)
1118 {
1119 DebugLogPublisher publisher = publishers[i];
1120 PublisherSettings settings = new PublisherSettings();
1121
1122 settings.debugPublisher = publisher;
1123 settings.classSettings = publisher.getClassSettings(className);
1124
1125 // For some reason, the compiler doesn't see that
1126 // debugLogPublihser.getMethodSettings returns a parameterized Map.
1127 // This problem goes away if a parameterized verson of DebugLogPublisher
1128 // is used. However, we can't not use reflection to instantiate a generic
1129 // DebugLogPublisher<? extends DebugLogPublisherCfg> type. The only thing
1130 // we can do is to just supress the compiler warnings.
1131 settings.methodSettings = publisher.getMethodSettings(className);
1132
1133 newSettings[i] = settings;
1134 }
1135
1136 publisherSettings = newSettings;
1137 }
1138
1139 /**
1140 * Return the caller stack frame.
1141 *
1142 * @param stackTrace The entrie stack trace frames.
1143 * @return the caller stack frame or null if none is found on the
1144 * stack trace.
1145 */
1146 private StackTraceElement getCallerFrame(StackTraceElement[] stackTrace)
1147 {
1148 if (stackTrace != null && stackTrace.length > 0)
1149 {
1150 // Skip leading frames debug logging classes and getStackTrace
1151 // method call frame if any.
1152 for (int i = 0; i < stackTrace.length; i++)
1153 {
1154 StackTraceElement aStackTrace = stackTrace[i];
1155 if(aStackTrace.getClassName().startsWith("java.lang.Thread"))
1156 {
1157 continue;
1158 }
1159
1160 if (!aStackTrace.getClassName().startsWith(
1161 "org.opends.server.loggers.debug"))
1162 {
1163 return aStackTrace;
1164 }
1165 }
1166 }
1167
1168 return null;
1169 }
1170
1171 private boolean shouldLog(LogLevel messageLevel, LogCategory messageCategory,
1172 TraceSettings activeSettings)
1173 {
1174 return !(activeSettings.includeCategories != null &&
1175 !activeSettings.includeCategories.contains(messageCategory)) &&
1176 messageLevel.intValue() >= activeSettings.level.intValue();
1177
1178 }
1179 }