1 /*
2  * Copyright (C) 2018 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.ddmlib.Log.LogLevel;
19 import com.android.tradefed.config.IConfiguration;
20 import com.android.tradefed.config.Option;
21 import com.android.tradefed.log.LogUtil.CLog;
22 
23 import com.google.common.collect.ImmutableMap;
24 
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Set;
30 
31 /**
32  * A base implementation for {@link ILeveledLogOutput} that allows to filtering some tags based on
33  * their name or components.
34  */
35 public abstract class BaseLeveledLogOutput implements ILeveledLogOutput {
36 
37     @Option(
38         name = "include-log-tag",
39         description = "List of tags that should be included in the display"
40     )
41     private Set<String> mIncludeTag = new HashSet<>();
42 
43     @Option(
44         name = "class-verbosity",
45         description = "Sets the verbosity of a particular class tag. For example: StubTest INFO."
46     )
47     private Map<String, LogLevel> mClassVerbosity = new HashMap<>();
48 
49     @Option(
50         name = "component-verbosity",
51         description =
52                 "Sets the verbosity of a group of Tradefed components."
53                         + "For example: target_preparer WARN."
54     )
55     private Map<String, LogLevel> mComponentVerbosity = new HashMap<>();
56 
57     @Option(
58             name = "force-verbosity-map",
59             description = "Enforce a pre-set verbosity of some component to avoid extreme logging.")
60     private boolean mEnableForcedVerbosity = true;
61 
62     // Add components we have less control over (ddmlib for example) to ensure they don't flood
63     // us. This will still write to the log.
64     private Map<String, LogLevel> mForcedVerbosity = ImmutableMap.of("ddms", LogLevel.WARN);
65 
66     private Map<String, LogLevel> mVerbosityMap = new HashMap<>();
67 
68     /** Initialize the components filters based on the invocation {@link IConfiguration}. */
initFilters(IConfiguration config)69     public final void initFilters(IConfiguration config) {
70         initComponentVerbosity(mComponentVerbosity, mVerbosityMap, config);
71         mVerbosityMap.putAll(mClassVerbosity);
72     }
73 
74     /**
75      * Whether or not a particular statement should be displayed base on its tag.
76      *
77      * @param forceStdout Whether or not to force the output to stdout.
78      * @param invocationLogLevel The current logLevel for the information.
79      * @param messageLogLevel The message evaluated log level.
80      * @param tag The logging tag of the message considered.
81      * @return True if it should be displayed, false otherwise.
82      */
shouldDisplay( boolean forceStdout, LogLevel invocationLogLevel, LogLevel messageLogLevel, String tag)83     public final boolean shouldDisplay(
84             boolean forceStdout,
85             LogLevel invocationLogLevel,
86             LogLevel messageLogLevel,
87             String tag) {
88         if (forceStdout) {
89             return true;
90         }
91         // If we have a specific verbosity use it. Otherwise use the invocation verbosity.
92         if (mVerbosityMap.get(tag) != null) {
93             if (messageLogLevel.getPriority() >= mVerbosityMap.get(tag).getPriority()) {
94                 return true;
95             }
96         } else if (messageLogLevel.getPriority() >= invocationLogLevel.getPriority()) {
97             return true;
98         }
99         return false;
100     }
101 
initComponentVerbosity( Map<String, LogLevel> components, Map<String, LogLevel> receiver, IConfiguration config)102     private void initComponentVerbosity(
103             Map<String, LogLevel> components,
104             Map<String, LogLevel> receiver,
105             IConfiguration config) {
106         for (String component : components.keySet()) {
107             Collection<Object> objs = config.getAllConfigurationObjectsOfType(component);
108             if (objs == null) {
109                 continue;
110             }
111             for (Object o : objs) {
112                 String objTag = CLog.parseClassName(o.getClass().getName());
113                 receiver.put(objTag, components.get(component));
114             }
115         }
116         if (shouldForceVerbosity()) {
117             mVerbosityMap.putAll(mForcedVerbosity);
118         }
119     }
120 
121     /** {@inheritDoc} */
122     @Override
clone()123     public abstract ILeveledLogOutput clone();
124 
125     /** Whether or not to enforce the verbosity map. */
shouldForceVerbosity()126     public boolean shouldForceVerbosity() {
127         return mEnableForcedVerbosity;
128     }
129 
130     /** Returns the map of the forced verbosity. */
getForcedVerbosityMap()131     public Map<String, LogLevel> getForcedVerbosityMap() {
132         return mForcedVerbosity;
133     }
134 }
135