Skip to content

Commit da6eea7

Browse files
authored
Merge pull request #146 from oracle/Issue#129-online-stdout-console-issues
Issue#129 online stdout console issues
2 parents 3c03b0a + dacb456 commit da6eea7

23 files changed

+1031
-81
lines changed

core/pom.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@
4040
<artifactId>junit</artifactId>
4141
<scope>test</scope>
4242
</dependency>
43+
<dependency>
44+
<groupId>org.easymock</groupId>
45+
<artifactId>easymock</artifactId>
46+
<version>3.6</version>
47+
<scope>test</scope>
48+
</dependency>
49+
<dependency>
50+
<groupId>org.powermock</groupId>
51+
<artifactId>powermock-api-easymock</artifactId>
52+
<version>1.6.6</version>
53+
<scope>test</scope>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.powermock</groupId>
57+
<artifactId>powermock-module-junit4</artifactId>
58+
<version>1.6.6</version>
59+
<scope>test</scope>
60+
</dependency>
4361
</dependencies>
4462

4563
<build>

core/src/main/java/oracle/weblogic/deploy/logging/PlatformLogger.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
*/
55
package oracle.weblogic.deploy.logging;
66

7+
import java.util.ArrayList;
8+
import java.util.Enumeration;
9+
import java.util.List;
710
import java.util.logging.Level;
11+
import java.util.logging.LogManager;
812
import java.util.logging.LogRecord;
913
import java.util.logging.Logger;
1014

@@ -526,6 +530,23 @@ public void warning(String msg, Throwable thrown) {
526530
logger.logp(Level.WARNING, details.clazz, details.method, msg, thrown);
527531
}
528532

533+
/**
534+
* Return a list of the current loggers.
535+
*
536+
* @return List of Logger from the Log Manager
537+
*/
538+
public static List<Logger> getLoggers() {
539+
LogManager manager = LogManager.getLogManager();
540+
Enumeration<String> e = manager.getLoggerNames();
541+
List<Logger> topList = new ArrayList<>();
542+
while (e.hasMoreElements()) {
543+
String loggerName = e.nextElement();
544+
Logger logger = manager.getLogger(loggerName);
545+
topList.add(logger);
546+
}
547+
return topList;
548+
}
549+
529550
/**
530551
* Obtains caller details, class name and method, to be provided to the actual Logger. This
531552
* code is adapted from ODLLogRecord, which should yield consistency in reporting using
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* The Universal Permissive License (UPL), Version 1.0
4+
*/
5+
package oracle.weblogic.deploy.logging;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Properties;
10+
import java.util.logging.ConsoleHandler;
11+
import java.util.logging.Formatter;
12+
import java.util.logging.Handler;
13+
import java.util.logging.Level;
14+
import java.util.logging.LogManager;
15+
import java.util.logging.LogRecord;
16+
import java.util.logging.MemoryHandler;
17+
18+
import oracle.weblogic.deploy.util.WLSDeployContext;
19+
import oracle.weblogic.deploy.util.WLSDeployExit;
20+
21+
22+
/**
23+
* This class save the log records logged by the tool at Info level or greater. The WLSDeployExit exit method will
24+
* call this Handler to publish the messages, along with the total of the log records, by Level category.
25+
*
26+
* The WLSDeployCustomizeLoggingConfig adds the properties from this class' getHandlerProperties() to the
27+
* log manager logger properties and adds the handler to the root WLSDEPLOY Logger. See the class for information
28+
* on how to inject this handler into the wlsdeploy root logger.
29+
*
30+
* Before the tool exit, if specified by the caller, an activity summary of the saved logs is displayed to the console.
31+
* A final total of the records logged by the tool for the Level categories indicated above is displayed to the console.
32+
*
33+
* @see WLSDeployCustomizeLoggingConfig
34+
* @see oracle.weblogic.deploy.util.WLSDeployExit
35+
*/
36+
public class SummaryHandler extends Handler implements WLSDeployLogEndHandler {
37+
private static final String CLASS = SummaryHandler.class.getName();
38+
private static final String LEVEL_PROPERTY = "level";
39+
private static final String TARGET_PROPERTY = "target";
40+
private static final String FORMATTER_PROPERTY = "formatter";
41+
private static final String SIZE_PROPERTY = "size";
42+
private static final int DEFAULT_SIZE = 3000;
43+
44+
private PlatformLogger LOGGER = WLSDeployLogFactory.getLogger("wlsdeploy.exit");
45+
private int bufferSize;
46+
private WLSDeployContext context;
47+
48+
private Handler topTarget;
49+
private List<LevelHandler> handlers = new ArrayList<>();
50+
private boolean closed = false;
51+
52+
/**
53+
* This default constructor is populated with the handler properties loaded by the WLSDeployCustomizeLoggingConfig.
54+
*/
55+
public SummaryHandler() {
56+
super();
57+
configure();
58+
59+
LOGGER.setLevel(Level.INFO);
60+
addLevelHandler(Level.WARNING);
61+
addLevelHandler(Level.SEVERE);
62+
}
63+
64+
/**
65+
* Tally and save the log record if it matches one of the category Level handlers. Once the summary has completed,
66+
* all further log records will be ignored.
67+
*
68+
* @param record to tally and save in handler with matching Level category
69+
*/
70+
@Override
71+
public synchronized void publish(LogRecord record) {
72+
// after close, take yourself out of the mix. The stored up log messages are going to go to the
73+
// console handler anyway
74+
if (!closed) {
75+
for (Handler handler : handlers) {
76+
handler.publish(record);
77+
}
78+
}
79+
}
80+
81+
@Override
82+
public void flush() {
83+
topTarget.flush();
84+
}
85+
86+
@Override
87+
public void close() throws SecurityException {
88+
topTarget.close();
89+
}
90+
91+
/**
92+
* This method is called by the tool to complete the SummaryHandler, and display the recap and total information
93+
* to the console. The log records are only displayed to the console if the tool was run in online mode.
94+
* This compensates for wlst writing spurious blank lines to the console during online mode.
95+
*
96+
* @param modelContext contextual information about the tool
97+
*/
98+
@Override
99+
public synchronized void logEnd(WLSDeployContext modelContext) {
100+
closed = true;
101+
String METHOD = "push";
102+
LOGGER.entering(modelContext, CLASS, METHOD);
103+
this.context = modelContext;
104+
summaryHead(topTarget);
105+
for (LevelHandler handler : handlers) {
106+
handler.push();
107+
}
108+
summaryTail(topTarget);
109+
LOGGER.exiting(CLASS, METHOD);
110+
}
111+
112+
/**
113+
* The WLSDeployLoggingConfig will call this method to add to the logging.properties files.
114+
* If the logging.properties already contains the property, the property in this list will be ignored.
115+
*
116+
* @return properties to set in logging.properties
117+
*/
118+
public static Properties getHandlerProperties() {
119+
Properties properties = new Properties();
120+
properties.setProperty(LEVEL_PROPERTY, Level.INFO.getName());
121+
properties.setProperty(TARGET_PROPERTY, WLSDeployLoggingConsoleHandler.class.getName());
122+
properties.setProperty(FORMATTER_PROPERTY, WLSDeployLogFormatter.class.getName());
123+
return properties;
124+
}
125+
126+
private void addLevelHandler(Level level) {
127+
LevelHandler handler;
128+
Handler levelTarget = getConsoleHandler();
129+
levelTarget.setFormatter(new SummaryFormatter(level));
130+
handler = new LevelHandler(levelTarget, bufferSize, level);
131+
handler.setLevel(level);
132+
handler.setFilter(getFilter());
133+
handlers.add(handler);
134+
}
135+
136+
void summaryHead(Handler handler) {
137+
handler.publish(getLogRecord("WLSDPLY-21003", context.getProgramName(),
138+
context.getVersion(), context.getWlstMode()));
139+
}
140+
141+
void summaryTail(Handler handler) {
142+
StringBuffer buffer = new StringBuffer();
143+
java.util.Formatter fmt = new java.util.Formatter(buffer);
144+
for (LevelHandler levelHandler : handlers) {
145+
if (levelHandler.getTotalRecords() >= 0) {
146+
fmt.format(" %1$s : %2$,5d", levelHandler.getLevel().getName(), levelHandler.getTotalRecords());
147+
}
148+
}
149+
handler.publish(getLogRecord("WLSDPLY-21002", buffer));
150+
}
151+
152+
private class TotalFormatter extends Formatter {
153+
154+
@Override
155+
public synchronized String format(LogRecord record) {
156+
return System.lineSeparator() + formatMessage(record) + System.lineSeparator();
157+
}
158+
159+
}
160+
161+
private class SummaryFormatter extends Formatter {
162+
163+
private final String MSG_FORMAT = " %1$5d. %2$s: %3$s" + System.lineSeparator();
164+
private final String INTERNAL = System.lineSeparator() + "%s" + System.lineSeparator() + System.lineSeparator();
165+
private int sequence = 0;
166+
private Level level;
167+
168+
public SummaryFormatter(Level level) {
169+
this.level = level;
170+
}
171+
172+
@Override
173+
public synchronized String format(LogRecord record) {
174+
String message = "";
175+
String msgId = record.getMessage();
176+
if (msgId.indexOf('{') >= 0) {
177+
msgId = null;
178+
}
179+
String formatted = formatMessage(record);
180+
if (msgId != null && !msgId.equals(formatted)) {
181+
// this has a msg id. don't post any that don't have msg id.
182+
message = String.format(MSG_FORMAT, ++sequence, msgId, formatted);
183+
}
184+
return message;
185+
}
186+
187+
@Override
188+
public String getHead(Handler handler) {
189+
return String.format(INTERNAL, formatMessage(getLogRecord("WLSDPLY-21000", level.getLocalizedName())));
190+
}
191+
}
192+
193+
private class LevelHandler extends MemoryHandler {
194+
195+
private int totalRecords;
196+
197+
LevelHandler(Handler handler, int size, Level level) {
198+
super(handler, size, Level.OFF);
199+
setLevel(level);
200+
}
201+
202+
@Override
203+
public synchronized void publish(LogRecord record) {
204+
if (record.getLevel().intValue() == getLevel().intValue()) {
205+
++totalRecords;
206+
super.publish(record);
207+
}
208+
}
209+
210+
int getTotalRecords() {
211+
return totalRecords;
212+
}
213+
214+
}
215+
216+
private void configure() {
217+
LogManager manager = LogManager.getLogManager();
218+
topTarget = getConsoleHandler();
219+
topTarget.setFormatter(new TotalFormatter());
220+
bufferSize = getSize(manager.getProperty(getClass().getName() + "." + SIZE_PROPERTY));
221+
}
222+
223+
private int getSize(String propSize) {
224+
Integer handlerSize;
225+
try {
226+
handlerSize = new Integer(propSize);
227+
} catch (NumberFormatException nfe) {
228+
handlerSize = DEFAULT_SIZE;
229+
}
230+
return handlerSize;
231+
}
232+
233+
private ConsoleHandler getConsoleHandler() {
234+
ConsoleHandler handler = null;
235+
try {
236+
handler = (ConsoleHandler) Class.forName(WLSDeployLoggingConfig.getConsoleHandler()).newInstance();
237+
} catch (ClassNotFoundException | IllegalAccessException cne) {
238+
System.out.println("Class not found " + WLSDeployLoggingConfig.getConsoleHandler());
239+
} catch (InstantiationException ie) {
240+
handler = new ConsoleHandler();
241+
}
242+
return handler;
243+
}
244+
245+
246+
private LogRecord getLogRecord(String msg, Object... params) {
247+
LogRecord record = new LogRecord(Level.INFO, msg);
248+
record.setLoggerName(LOGGER.getName());
249+
if (params != null && params.length != 0) {
250+
record.setParameters(params);
251+
}
252+
record.setSourceClassName(CLASS);
253+
record.setSourceMethodName("");
254+
record.setResourceBundle(LOGGER.getUnderlyingLogger().getResourceBundle());
255+
return record;
256+
}
257+
258+
}

0 commit comments

Comments
 (0)