Improve logging
- Make sure logging of UnknownHostException indicates the failure reason - Indent stack traces inside event blocks in EventLogger - Don't log media URLs PiperOrigin-RevId: 302007601
This commit is contained in:
parent
c0d632936a
commit
429bdfb974
@ -223,7 +223,7 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
responseByteStream = responseBody.byteStream();
|
responseByteStream = responseBody.byteStream();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new HttpDataSourceException(
|
throw new HttpDataSourceException(
|
||||||
"Unable to connect to " + dataSpec.uri, e, dataSpec, HttpDataSourceException.TYPE_OPEN);
|
"Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
int responseCode = response.code();
|
int responseCode = response.code();
|
||||||
|
@ -21,6 +21,7 @@ import androidx.annotation.Nullable;
|
|||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
/** Wrapper around {@link android.util.Log} which allows to set the log level. */
|
/** Wrapper around {@link android.util.Log} which allows to set the log level. */
|
||||||
public final class Log {
|
public final class Log {
|
||||||
@ -69,7 +70,8 @@ public final class Log {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether stack traces of {@link Throwable}s will be logged to logcat.
|
* Sets whether stack traces of {@link Throwable}s will be logged to logcat. Stack trace logging
|
||||||
|
* is enabled by default.
|
||||||
*
|
*
|
||||||
* @param logStackTraces Whether stack traces will be logged.
|
* @param logStackTraces Whether stack traces will be logged.
|
||||||
*/
|
*/
|
||||||
@ -86,11 +88,7 @@ public final class Log {
|
|||||||
|
|
||||||
/** @see android.util.Log#d(String, String, Throwable) */
|
/** @see android.util.Log#d(String, String, Throwable) */
|
||||||
public static void d(String tag, String message, @Nullable Throwable throwable) {
|
public static void d(String tag, String message, @Nullable Throwable throwable) {
|
||||||
if (!logStackTraces) {
|
d(tag, appendThrowableString(message, throwable));
|
||||||
d(tag, appendThrowableMessage(message, throwable));
|
|
||||||
} else if (logLevel == LOG_LEVEL_ALL) {
|
|
||||||
android.util.Log.d(tag, message, throwable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @see android.util.Log#i(String, String) */
|
/** @see android.util.Log#i(String, String) */
|
||||||
@ -102,11 +100,7 @@ public final class Log {
|
|||||||
|
|
||||||
/** @see android.util.Log#i(String, String, Throwable) */
|
/** @see android.util.Log#i(String, String, Throwable) */
|
||||||
public static void i(String tag, String message, @Nullable Throwable throwable) {
|
public static void i(String tag, String message, @Nullable Throwable throwable) {
|
||||||
if (!logStackTraces) {
|
i(tag, appendThrowableString(message, throwable));
|
||||||
i(tag, appendThrowableMessage(message, throwable));
|
|
||||||
} else if (logLevel <= LOG_LEVEL_INFO) {
|
|
||||||
android.util.Log.i(tag, message, throwable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @see android.util.Log#w(String, String) */
|
/** @see android.util.Log#w(String, String) */
|
||||||
@ -118,11 +112,7 @@ public final class Log {
|
|||||||
|
|
||||||
/** @see android.util.Log#w(String, String, Throwable) */
|
/** @see android.util.Log#w(String, String, Throwable) */
|
||||||
public static void w(String tag, String message, @Nullable Throwable throwable) {
|
public static void w(String tag, String message, @Nullable Throwable throwable) {
|
||||||
if (!logStackTraces) {
|
w(tag, appendThrowableString(message, throwable));
|
||||||
w(tag, appendThrowableMessage(message, throwable));
|
|
||||||
} else if (logLevel <= LOG_LEVEL_WARNING) {
|
|
||||||
android.util.Log.w(tag, message, throwable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @see android.util.Log#e(String, String) */
|
/** @see android.util.Log#e(String, String) */
|
||||||
@ -134,18 +124,54 @@ public final class Log {
|
|||||||
|
|
||||||
/** @see android.util.Log#e(String, String, Throwable) */
|
/** @see android.util.Log#e(String, String, Throwable) */
|
||||||
public static void e(String tag, String message, @Nullable Throwable throwable) {
|
public static void e(String tag, String message, @Nullable Throwable throwable) {
|
||||||
if (!logStackTraces) {
|
e(tag, appendThrowableString(message, throwable));
|
||||||
e(tag, appendThrowableMessage(message, throwable));
|
}
|
||||||
} else if (logLevel <= LOG_LEVEL_ERROR) {
|
|
||||||
android.util.Log.e(tag, message, throwable);
|
/**
|
||||||
|
* Returns a string representation of a {@link Throwable} suitable for logging, taking into
|
||||||
|
* account whether {@link #setLogStackTraces(boolean)} stack trace logging} is enabled.
|
||||||
|
*
|
||||||
|
* <p>Stack trace logging may be unconditionally suppressed for some expected failure modes (e.g.,
|
||||||
|
* {@link Throwable Throwables} that are expected if the device doesn't have network connectivity)
|
||||||
|
* to avoid log spam.
|
||||||
|
*
|
||||||
|
* @param throwable The {@link Throwable}.
|
||||||
|
* @return The string representation of the {@link Throwable}.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static String getThrowableString(@Nullable Throwable throwable) {
|
||||||
|
if (throwable == null) {
|
||||||
|
return null;
|
||||||
|
} else if (isCausedByUnknownHostException(throwable)) {
|
||||||
|
// UnknownHostException implies the device doesn't have network connectivity.
|
||||||
|
// UnknownHostException.getMessage() may return a string that's more verbose than desired for
|
||||||
|
// logging an expected failure mode. Conversely, android.util.Log.getStackTraceString has
|
||||||
|
// special handling to return the empty string, which can result in logging that doesn't
|
||||||
|
// indicate the failure mode at all. Hence we special case this exception to always return a
|
||||||
|
// concise but useful message.
|
||||||
|
return "UnknownHostException (no network)";
|
||||||
|
} else if (!logStackTraces) {
|
||||||
|
return throwable.getMessage();
|
||||||
|
} else {
|
||||||
|
return android.util.Log.getStackTraceString(throwable).trim().replace("\t", " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String appendThrowableMessage(String message, @Nullable Throwable throwable) {
|
private static String appendThrowableString(String message, @Nullable Throwable throwable) {
|
||||||
if (throwable == null) {
|
@Nullable String throwableString = getThrowableString(throwable);
|
||||||
|
if (!TextUtils.isEmpty(throwableString)) {
|
||||||
|
message += "\n " + throwableString.replace("\n", "\n ") + '\n';
|
||||||
|
}
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
String throwableMessage = throwable.getMessage();
|
|
||||||
return TextUtils.isEmpty(throwableMessage) ? message : message + " - " + throwableMessage;
|
private static boolean isCausedByUnknownHostException(@Nullable Throwable throwable) {
|
||||||
|
while (throwable != null) {
|
||||||
|
if (throwable instanceof UnknownHostException) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
throwable = throwable.getCause();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,7 +477,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
playbackInfo = playbackInfo.copyWithPlaybackError(e);
|
playbackInfo = playbackInfo.copyWithPlaybackError(e);
|
||||||
maybeNotifyPlaybackInfoChanged();
|
maybeNotifyPlaybackInfoChanged();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Source error.", e);
|
Log.e(TAG, "Source error", e);
|
||||||
stopInternal(
|
stopInternal(
|
||||||
/* forceResetRenderers= */ false,
|
/* forceResetRenderers= */ false,
|
||||||
/* resetPositionAndState= */ false,
|
/* resetPositionAndState= */ false,
|
||||||
@ -485,7 +485,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
playbackInfo = playbackInfo.copyWithPlaybackError(ExoPlaybackException.createForSource(e));
|
playbackInfo = playbackInfo.copyWithPlaybackError(ExoPlaybackException.createForSource(e));
|
||||||
maybeNotifyPlaybackInfoChanged();
|
maybeNotifyPlaybackInfoChanged();
|
||||||
} catch (RuntimeException | OutOfMemoryError e) {
|
} catch (RuntimeException | OutOfMemoryError e) {
|
||||||
Log.e(TAG, "Internal runtime error.", e);
|
Log.e(TAG, "Internal runtime error", e);
|
||||||
ExoPlaybackException error =
|
ExoPlaybackException error =
|
||||||
e instanceof OutOfMemoryError
|
e instanceof OutOfMemoryError
|
||||||
? ExoPlaybackException.createForOutOfMemoryError((OutOfMemoryError) e)
|
? ExoPlaybackException.createForOutOfMemoryError((OutOfMemoryError) e)
|
||||||
|
@ -279,8 +279,8 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
|
|||||||
try {
|
try {
|
||||||
connection = makeConnection(dataSpec);
|
connection = makeConnection(dataSpec);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new HttpDataSourceException("Unable to connect to " + dataSpec.uri.toString(), e,
|
throw new HttpDataSourceException(
|
||||||
dataSpec, HttpDataSourceException.TYPE_OPEN);
|
"Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
String responseMessage;
|
String responseMessage;
|
||||||
@ -289,8 +289,8 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
|
|||||||
responseMessage = connection.getResponseMessage();
|
responseMessage = connection.getResponseMessage();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
closeConnectionQuietly();
|
closeConnectionQuietly();
|
||||||
throw new HttpDataSourceException("Unable to connect to " + dataSpec.uri.toString(), e,
|
throw new HttpDataSourceException(
|
||||||
dataSpec, HttpDataSourceException.TYPE_OPEN);
|
"Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a valid response code.
|
// Check for a valid response code.
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
@ -209,7 +210,7 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
logd(eventTime, "tracks", "[]");
|
logd(eventTime, "tracks", "[]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logd("tracks [" + getEventTimeString(eventTime) + ", ");
|
logd("tracks [" + getEventTimeString(eventTime));
|
||||||
// Log tracks associated to renderers.
|
// Log tracks associated to renderers.
|
||||||
int rendererCount = mappedTrackInfo.getRendererCount();
|
int rendererCount = mappedTrackInfo.getRendererCount();
|
||||||
for (int rendererIndex = 0; rendererIndex < rendererCount; rendererIndex++) {
|
for (int rendererIndex = 0; rendererIndex < rendererCount; rendererIndex++) {
|
||||||
@ -293,7 +294,7 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMetadata(EventTime eventTime, Metadata metadata) {
|
public void onMetadata(EventTime eventTime, Metadata metadata) {
|
||||||
logd("metadata [" + getEventTimeString(eventTime) + ", ");
|
logd("metadata [" + getEventTimeString(eventTime));
|
||||||
printMetadata(metadata, " ");
|
printMetadata(metadata, " ");
|
||||||
logd("]");
|
logd("]");
|
||||||
}
|
}
|
||||||
@ -485,27 +486,26 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs an error message and exception.
|
* Logs an error message.
|
||||||
*
|
*
|
||||||
* @param msg The message to log.
|
* @param msg The message to log.
|
||||||
* @param tr The exception to log.
|
|
||||||
*/
|
*/
|
||||||
protected void loge(String msg, @Nullable Throwable tr) {
|
protected void loge(String msg) {
|
||||||
Log.e(tag, msg, tr);
|
Log.e(tag, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal methods
|
// Internal methods
|
||||||
|
|
||||||
private void logd(EventTime eventTime, String eventName) {
|
private void logd(EventTime eventTime, String eventName) {
|
||||||
logd(getEventString(eventTime, eventName));
|
logd(getEventString(eventTime, eventName, /* eventDescription= */ null, /* throwable= */ null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logd(EventTime eventTime, String eventName, String eventDescription) {
|
private void logd(EventTime eventTime, String eventName, String eventDescription) {
|
||||||
logd(getEventString(eventTime, eventName, eventDescription));
|
logd(getEventString(eventTime, eventName, eventDescription, /* throwable= */ null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loge(EventTime eventTime, String eventName, @Nullable Throwable throwable) {
|
private void loge(EventTime eventTime, String eventName, @Nullable Throwable throwable) {
|
||||||
loge(getEventString(eventTime, eventName), throwable);
|
loge(getEventString(eventTime, eventName, /* eventDescription= */ null, throwable));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loge(
|
private void loge(
|
||||||
@ -513,7 +513,7 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
String eventName,
|
String eventName,
|
||||||
String eventDescription,
|
String eventDescription,
|
||||||
@Nullable Throwable throwable) {
|
@Nullable Throwable throwable) {
|
||||||
loge(getEventString(eventTime, eventName, eventDescription), throwable);
|
loge(getEventString(eventTime, eventName, eventDescription, throwable));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printInternalError(EventTime eventTime, String type, Exception e) {
|
private void printInternalError(EventTime eventTime, String type, Exception e) {
|
||||||
@ -526,12 +526,21 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getEventString(EventTime eventTime, String eventName) {
|
private String getEventString(
|
||||||
return eventName + " [" + getEventTimeString(eventTime) + "]";
|
EventTime eventTime,
|
||||||
|
String eventName,
|
||||||
|
@Nullable String eventDescription,
|
||||||
|
@Nullable Throwable throwable) {
|
||||||
|
String eventString = eventName + " [" + getEventTimeString(eventTime);
|
||||||
|
if (eventDescription != null) {
|
||||||
|
eventString += ", " + eventDescription;
|
||||||
}
|
}
|
||||||
|
@Nullable String throwableString = Log.getThrowableString(throwable);
|
||||||
private String getEventString(EventTime eventTime, String eventName, String eventDescription) {
|
if (!TextUtils.isEmpty(throwableString)) {
|
||||||
return eventName + " [" + getEventTimeString(eventTime) + ", " + eventDescription + "]";
|
eventString += "\n " + throwableString.replace("\n", "\n ") + '\n';
|
||||||
|
}
|
||||||
|
eventString += "]";
|
||||||
|
return eventString;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getEventTimeString(EventTime eventTime) {
|
private String getEventTimeString(EventTime eventTime) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user