001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Delbosc Benoit 018 */ 019package org.nuxeo.common.logging; 020 021import org.apache.commons.logging.Log; 022import org.apache.commons.logging.LogFactory; 023 024/** 025 * Helper to log information that can be displayed using plantuml to render sequence UML diagram. 026 * 027 * @since 8.1 028 */ 029public class SequenceTracer { 030 031 private static final Log log = LogFactory.getLog(SequenceTracer.class); 032 private static final String PREFIX = "@@ "; 033 private static final String DEFAULT_COLOR = "#white"; 034 private static final int MESSAGE_MAX_LEN = 250; 035 036 // Utility class. 037 private SequenceTracer() { 038 } 039 040 /** 041 * Mark an event. 042 */ 043 public static void mark(String message) { 044 if (!log.isDebugEnabled()) { 045 return; 046 } 047 final String tn = getThreadName(); 048 log.debug(PREFIX + tn + " -> " + tn + ": " + message); 049 } 050 051 /** 052 * Mark the beginning of an action 053 */ 054 public static void start(String message) { 055 start(message, DEFAULT_COLOR); 056 } 057 058 /** 059 * Mark the beginning of an action 060 */ 061 public static void start(String message, String color) { 062 if (!log.isDebugEnabled()) { 063 return; 064 } 065 final String tn = getThreadName(); 066 log.debug(PREFIX + tn + " -> " + tn + ": " + format(message) + "\n" + PREFIX + "activate " + tn + " " + 067 color); 068 } 069 070 /** 071 * Mark the beginning of an action initiated by the caller. 072 */ 073 public static void startFrom(final String callerThread, final String message) { 074 startFrom(callerThread, message, DEFAULT_COLOR); 075 } 076 077 /** 078 * Mark the beginning of an action initiated by the caller. 079 */ 080 public static void startFrom(final String callerThread, final String message, final String color) { 081 if (!log.isDebugEnabled()) { 082 return; 083 } 084 final String tn = getThreadName(); 085 log.debug(PREFIX + sanitize(callerThread) + " o--> " + tn + ": Initiate\n" + PREFIX 086 + tn + " -> " + tn + ": " + format(message) + "\n" + PREFIX 087 + "activate " + tn + " " + color); 088 } 089 090 private static String format(String message) { 091 String ret = sanitize(message).replace(", ", ",\\n"); 092 ret = insertNewLine(ret); 093 return ret; 094 } 095 096 private static String sanitize(String message) { 097 String ret = message.replace("-", "_").replace(":", "_"); 098 if (ret.length() > MESSAGE_MAX_LEN) { 099 ret = ret.substring(0, MESSAGE_MAX_LEN) + "..."; 100 } 101 return ret; 102 } 103 104 private static String insertNewLine(String message) { 105 return String.join("\\n", message.split("(?<=\\G.{40})")); 106 } 107 108 /** 109 * Mark the end of the previous action. 110 */ 111 public static void stop(String message) { 112 if (!log.isDebugEnabled()) { 113 return; 114 } 115 final String tn = getThreadName(); 116 log.debug(PREFIX + tn + " -> " + tn + ": " + format(message) + "\n" + PREFIX + "deactivate " + tn); 117 } 118 119 /** 120 * Mark the last action as failure 121 */ 122 public static void destroy(String message) { 123 if (!log.isDebugEnabled()) { 124 return; 125 } 126 final String tn = getThreadName(); 127 log.debug(PREFIX + tn + " -> " + tn + ": " + format(message) + "\n" + PREFIX + "destroy " + tn); 128 } 129 130 /** 131 * Add a note on the current thread 132 */ 133 public static void addNote(String message) { 134 if (!log.isDebugEnabled()) { 135 return; 136 } 137 log.debug(PREFIX + "note right of " + getThreadName() + ": " + message); 138 } 139 140 /** 141 * Link from source to current thread. 142 */ 143 public static void addRelation(String source, String message) { 144 if (!log.isDebugEnabled()) { 145 return; 146 } 147 log.debug(PREFIX + source + " --> " + getThreadName() + ": " + format(message)); 148 } 149 150 /** 151 * Get the thread name sanitized for plantuml 152 */ 153 public static String getThreadName() { 154 return sanitize(Thread.currentThread().getName()); 155 } 156 157 public static boolean isEnabled() { 158 return log.isDebugEnabled(); 159 } 160}