com.android.ddmlib.logcat.LogCatFilter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ddmlib Show documentation
Show all versions of ddmlib Show documentation
Library providing APIs to talk to Android devices
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ddmlib.logcat;
import com.android.annotations.NonNull;
import com.android.ddmlib.Log.LogLevel;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* A Filter for logcat messages. A filter can be constructed to match
* different fields of a logcat message. It can then be queried to see if
* a message matches the filter's settings.
*/
public final class LogCatFilter {
private static final String PID_KEYWORD = "pid:"; //$NON-NLS-1$
private static final String APP_KEYWORD = "app:"; //$NON-NLS-1$
private static final String TAG_KEYWORD = "tag:"; //$NON-NLS-1$
private static final String TEXT_KEYWORD = "text:"; //$NON-NLS-1$
private final String mName;
private final String mTag;
private final String mText;
private final String mPid;
private final String mAppName;
private final LogLevel mLogLevel;
private boolean mCheckPid;
private boolean mCheckAppName;
private boolean mCheckTag;
private boolean mCheckText;
private Pattern mAppNamePattern;
private Pattern mTagPattern;
private Pattern mTextPattern;
/**
* Construct a filter with the provided restrictions for the logcat message. All the text
* fields accept Java regexes as input, but ignore invalid regexes.
* @param name name for the filter
* @param tag value for the logcat message's tag field.
* @param text value for the logcat message's text field.
* @param pid value for the logcat message's pid field.
* @param appName value for the logcat message's app name field.
* @param logLevel value for the logcat message's log level. Only messages of
* higher priority will be accepted by the filter.
*/
public LogCatFilter(@NonNull String name, @NonNull String tag, @NonNull String text,
@NonNull String pid, @NonNull String appName, @NonNull LogLevel logLevel) {
mName = name.trim();
mTag = tag.trim();
mText = text.trim();
mPid = pid.trim();
mAppName = appName.trim();
mLogLevel = logLevel;
mCheckPid = !mPid.isEmpty();
if (!mAppName.isEmpty()) {
try {
mAppNamePattern = Pattern.compile(mAppName, getPatternCompileFlags(mAppName));
mCheckAppName = true;
} catch (PatternSyntaxException e) {
mCheckAppName = false;
}
}
if (!mTag.isEmpty()) {
try {
mTagPattern = Pattern.compile(mTag, getPatternCompileFlags(mTag));
mCheckTag = true;
} catch (PatternSyntaxException e) {
mCheckTag = false;
}
}
if (!mText.isEmpty()) {
try {
mTextPattern = Pattern.compile(mText, getPatternCompileFlags(mText));
mCheckText = true;
} catch (PatternSyntaxException e) {
mCheckText = false;
}
}
}
/**
* Obtain the flags to pass to {@link Pattern#compile(String, int)}. This method
* tries to figure out whether case sensitive matching should be used. It is based on
* the following heuristic: if the regex has an upper case character, then the match
* will be case sensitive. Otherwise it will be case insensitive.
*/
private int getPatternCompileFlags(String regex) {
for (char c : regex.toCharArray()) {
if (Character.isUpperCase(c)) {
return 0;
}
}
return Pattern.CASE_INSENSITIVE;
}
/**
* Construct a list of {@link LogCatFilter} objects by decoding the query.
* @param query encoded search string. The query is simply a list of words (can be regexes)
* a user would type in a search bar. These words are searched for in the text field of
* each collected logcat message. To search in a different field, the word could be prefixed
* with a keyword corresponding to the field name. Currently, the following keywords are
* supported: "pid:", "tag:" and "text:". Invalid regexes are ignored.
* @param minLevel minimum log level to match
* @return list of filter settings that fully match the given query
*/
public static List fromString(String query, LogLevel minLevel) {
List filterSettings = new ArrayList();
for (String s : query.trim().split(" ")) {
String tag = "";
String text = "";
String pid = "";
String app = "";
if (s.startsWith(PID_KEYWORD)) {
pid = s.substring(PID_KEYWORD.length());
} else if (s.startsWith(APP_KEYWORD)) {
app = s.substring(APP_KEYWORD.length());
} else if (s.startsWith(TAG_KEYWORD)) {
tag = s.substring(TAG_KEYWORD.length());
} else {
if (s.startsWith(TEXT_KEYWORD)) {
text = s.substring(TEXT_KEYWORD.length());
} else {
text = s;
}
}
filterSettings.add(new LogCatFilter("livefilter-" + s,
tag, text, pid, app, minLevel));
}
return filterSettings;
}
@NonNull
public String getName() {
return mName;
}
@NonNull
public String getTag() {
return mTag;
}
@NonNull
public String getText() {
return mText;
}
@NonNull
public String getPid() {
return mPid;
}
@NonNull
public String getAppName() {
return mAppName;
}
@NonNull
public LogLevel getLogLevel() {
return mLogLevel;
}
/**
* Check whether a given message will make it through this filter.
* @param m message to check
* @return true if the message matches the filter's conditions.
*/
public boolean matches(LogCatMessage m) {
/* filter out messages of a lower priority */
if (m.getLogLevel().getPriority() < mLogLevel.getPriority()) {
return false;
}
/* if pid filter is enabled, filter out messages whose pid does not match
* the filter's pid */
if (mCheckPid && !Integer.toString(m.getPid()).equals(mPid)) {
return false;
}
/* if app name filter is enabled, filter out messages not matching the app name */
if (mCheckAppName) {
Matcher matcher = mAppNamePattern.matcher(m.getAppName());
if (!matcher.find()) {
return false;
}
}
/* if tag filter is enabled, filter out messages not matching the tag */
if (mCheckTag) {
Matcher matcher = mTagPattern.matcher(m.getTag());
if (!matcher.find()) {
return false;
}
}
if (mCheckText) {
Matcher matcher = mTextPattern.matcher(m.getMessage());
if (!matcher.find()) {
return false;
}
}
return true;
}
}