• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.tradefed.log;
17 
18 import com.android.tradefed.config.Option;
19 import com.android.tradefed.config.Option.Importance;
20 import com.android.tradefed.log.Log.LogLevel;
21 import com.android.tradefed.util.StreamUtil;
22 
23 import java.io.IOException;
24 import java.io.OutputStream;
25 
26 /** A {@link ILeveledLogOutput} that directs log messages to an output stream and to stdout. */
27 public abstract class BaseStreamLogger<OS extends OutputStream> extends BaseLeveledLogOutput {
28 
29     @Option(name = "log-level", description = "the minimum log level to log.")
30     private LogLevel mLogLevel = LogLevel.DEBUG;
31 
32     @Option(
33         name = "log-level-display",
34         shortName = 'l',
35         description = "the minimum log level to display on stdout.",
36         importance = Importance.ALWAYS
37     )
38     private LogLevel mLogLevelDisplay = LogLevel.ERROR;
39 
40     // output stream to print logs to, exposed to subclasses
41     protected OS mOutputStream;
42 
43     @Override
getLogLevel()44     public LogLevel getLogLevel() {
45         return mLogLevel;
46     }
47 
48     @Override
setLogLevel(LogLevel logLevel)49     public void setLogLevel(LogLevel logLevel) {
50         mLogLevel = logLevel;
51     }
52 
53     /** Sets the minimum {@link LogLevel} to display on stdout. */
setLogLevelDisplay(LogLevel logLevel)54     public void setLogLevelDisplay(LogLevel logLevel) {
55         mLogLevelDisplay = logLevel;
56     }
57 
58     /** For compatibility */
setLogLevelDisplay(com.android.ddmlib.Log.LogLevel logLevel)59     public void setLogLevelDisplay(com.android.ddmlib.Log.LogLevel logLevel) {
60         mLogLevelDisplay = LogLevel.convertFromDdmlib(logLevel);
61     }
62 
63     /** @return current minimum {@link LogLevel} to display on stdout. */
getLogLevelDisplay()64     public LogLevel getLogLevelDisplay() {
65         return mLogLevelDisplay;
66     }
67 
68     @Override
closeLog()69     public void closeLog() {
70         StreamUtil.flushAndCloseStream(mOutputStream);
71         mOutputStream = null;
72     }
73 
74     @Override
printAndPromptLog(LogLevel logLevel, String tag, String message)75     public void printAndPromptLog(LogLevel logLevel, String tag, String message) {
76         internalPrintLog(logLevel, tag, message, true /* force print to stdout */);
77     }
78 
79     @Override
printLog(LogLevel logLevel, String tag, String message)80     public void printLog(LogLevel logLevel, String tag, String message) {
81         internalPrintLog(logLevel, tag, message, false /* don't force stdout */);
82     }
83 
84     /**
85      * A version of printLog(...) which can be forced to print to stdout, even if the log level
86      * isn't above the urgency threshold.
87      */
internalPrintLog( LogLevel logLevel, String tag, String message, boolean forceStdout)88     private void internalPrintLog(
89             LogLevel logLevel, String tag, String message, boolean forceStdout) {
90         String outMessage = Log.getLogFormatString(logLevel, tag, message);
91         if (shouldDisplay(forceStdout, mLogLevelDisplay, logLevel, tag)) {
92             System.out.print(outMessage);
93         }
94         if (shouldWrite(tag, logLevel, mLogLevel)) {
95             try {
96                 writeToLog(outMessage);
97             } catch (IOException e) {
98                 e.printStackTrace();
99             }
100         }
101     }
102 
103     // Determines whether a message should be written to the output stream.
shouldWrite(String tag, LogLevel messageLogLevel, LogLevel invocationLogLevel)104     private boolean shouldWrite(String tag, LogLevel messageLogLevel, LogLevel invocationLogLevel) {
105         LogLevel forcedLevel = getForcedVerbosityMap().get(tag);
106         if (forcedLevel == null || !shouldForceVerbosity()) {
107             return true;
108         }
109         // Use the highest level of our forced and invocation to decide if we should log the
110         // particular tag.
111         int minWriteLevel = Math.max(forcedLevel.getPriority(), invocationLogLevel.getPriority());
112         return messageLogLevel.getPriority() >= minWriteLevel;
113     }
114 
115     /**
116      * Writes a message to the output stream.
117      *
118      * @param message the entry to write to log
119      * @throws IOException if an I/O error occurs
120      */
writeToLog(String message)121     protected void writeToLog(String message) throws IOException {
122         if (mOutputStream != null) {
123             mOutputStream.write(message.getBytes());
124         }
125     }
126 }
127