Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/custom logger #147

Merged
merged 14 commits into from
Sep 5, 2024
2 changes: 2 additions & 0 deletions backtrace-library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
BartoszLitwiniuk marked this conversation as resolved.
Show resolved Hide resolved
implementation 'com.squareup:tape:1.2.3'
testImplementation 'junit:junit:4.13.2'
testImplementation "org.mockito:mockito-core:5.12.0"
androidTestImplementation "org.mockito:mockito-android:5.12.0"
androidTestImplementation 'net.jodah:concurrentunit:0.4.4'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test:rules:1.6.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import backtraceio.library.common.BacktraceSerializeHelper;
import backtraceio.library.events.EventsOnServerResponseEventListener;
import backtraceio.library.events.EventsRequestHandler;
import backtraceio.library.logger.BacktraceInternalLogger;
import backtraceio.library.logger.BacktraceLogger;
import backtraceio.library.logger.LogLevel;
import backtraceio.library.models.BacktraceMetricsSettings;
Expand Down Expand Up @@ -52,13 +53,12 @@ public class BacktraceClientMetricsTest {

@Before
public void setUp() {
BacktraceLogger.setLogger(new BacktraceInternalLogger(LogLevel.DEBUG));
context = InstrumentationRegistry.getInstrumentation().getContext();
credentials = new BacktraceCredentials("https://universe.sp.backtrace.io:6098", token);
BacktraceDatabase database = new BacktraceDatabase(context, context.getFilesDir().getAbsolutePath());

backtraceClient = new BacktraceClient(context, credentials, database);

BacktraceLogger.setLevel(LogLevel.DEBUG);
}

public class MockRequestHandler implements EventsRequestHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import backtraceio.library.common.BacktraceSerializeHelper;
import backtraceio.library.events.EventsOnServerResponseEventListener;
import backtraceio.library.events.EventsRequestHandler;
import backtraceio.library.logger.BacktraceInternalLogger;
import backtraceio.library.logger.BacktraceLogger;
import backtraceio.library.logger.LogLevel;
import backtraceio.library.models.BacktraceMetricsSettings;
Expand All @@ -49,13 +50,12 @@ public class BacktraceClientSummedEventTest {

@Before
public void setUp() {
BacktraceLogger.setLogger(new BacktraceInternalLogger(LogLevel.DEBUG));
context = InstrumentationRegistry.getInstrumentation().getContext();
credentials = new BacktraceCredentials("https://universe.sp.backtrace.io:6098", token);
BacktraceDatabase database = new BacktraceDatabase(context, context.getFilesDir().getAbsolutePath());

backtraceClient = new BacktraceClient(context, credentials, database);

BacktraceLogger.setLevel(LogLevel.DEBUG);
}

public class MockRequestHandler implements EventsRequestHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import backtraceio.library.common.BacktraceSerializeHelper;
import backtraceio.library.events.EventsOnServerResponseEventListener;
import backtraceio.library.events.EventsRequestHandler;
import backtraceio.library.logger.BacktraceInternalLogger;
import backtraceio.library.logger.BacktraceLogger;
import backtraceio.library.logger.LogLevel;
import backtraceio.library.models.BacktraceMetricsSettings;
Expand Down Expand Up @@ -56,13 +57,12 @@ public class BacktraceClientUniqueEventTest {

@Before
public void setUp() {
BacktraceLogger.setLogger(new BacktraceInternalLogger(LogLevel.DEBUG));
context = InstrumentationRegistry.getInstrumentation().getContext();
credentials = new BacktraceCredentials("https://universe.sp.backtrace.io:6098", token);
BacktraceDatabase database = new BacktraceDatabase(context, context.getFilesDir().getAbsolutePath());

backtraceClient = new BacktraceClient(context, credentials, database);

BacktraceLogger.setLevel(LogLevel.DEBUG);
}

public class MockRequestHandler implements EventsRequestHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import backtraceio.library.BacktraceCredentials;
import backtraceio.library.BacktraceDatabase;
import backtraceio.library.common.BacktraceTimeHelper;
import backtraceio.library.logger.BacktraceInternalLogger;
import backtraceio.library.logger.BacktraceLogger;
import backtraceio.library.logger.LogLevel;
import backtraceio.library.models.BacktraceMetricsSettings;
Expand All @@ -45,13 +46,12 @@ public class BacktraceMetricsTest {

@Before
public void setUp() {
BacktraceLogger.setLogger(new BacktraceInternalLogger(LogLevel.DEBUG));
context = InstrumentationRegistry.getInstrumentation().getContext();
credentials = new BacktraceCredentials("https://universe.sp.backtrace.io:6098", token);
BacktraceDatabase database = new BacktraceDatabase(context, context.getFilesDir().getAbsolutePath());

backtraceClient = new BacktraceClient(context, credentials, database);

BacktraceLogger.setLevel(LogLevel.DEBUG);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import backtraceio.library.BacktraceClient;
import backtraceio.library.BacktraceCredentials;
import backtraceio.library.logger.BacktraceInternalLogger;
import backtraceio.library.logger.BacktraceLogger;
import backtraceio.library.logger.LogLevel;

Expand All @@ -29,6 +30,7 @@ public class BacktraceAnrTest {

@Before
public void setUp() {
BacktraceLogger.setLogger(new BacktraceInternalLogger(LogLevel.DEBUG));
this.context = InstrumentationRegistry.getInstrumentation().getContext();
this.backtraceClient = new BacktraceClient(this.context, credentials);
}
Expand All @@ -38,7 +40,6 @@ public void setUp() {
public void checkIfANRIsDetectedCorrectly() {
// GIVEN
final Waiter waiter = new Waiter();
BacktraceLogger.setLevel(LogLevel.DEBUG);
BacktraceANRWatchdog watchdog = new BacktraceANRWatchdog(this.backtraceClient, 500);
watchdog.setOnApplicationNotRespondingEvent(new OnApplicationNotRespondingEvent() {
@Override
Expand Down Expand Up @@ -67,7 +68,6 @@ public void onEvent(BacktraceWatchdogTimeoutException exception) {
public void checkIfANRIsDetectedCorrectlyWithBacktraceClient() {
// GIVEN
final Waiter waiter = new Waiter();
BacktraceLogger.setLevel(LogLevel.DEBUG);
this.backtraceClient.enableAnr(500, new OnApplicationNotRespondingEvent() {
@Override
public void onEvent(BacktraceWatchdogTimeoutException exception) {
Expand Down Expand Up @@ -96,7 +96,6 @@ public void checkIfANRIsNotDetected() {
// GIVEN
final int numberOfIterations = 5;
final Waiter waiter = new Waiter();
BacktraceLogger.setLevel(LogLevel.DEBUG);
BacktraceANRWatchdog watchdog = new BacktraceANRWatchdog(this.backtraceClient, 5000);
watchdog.setOnApplicationNotRespondingEvent(new OnApplicationNotRespondingEvent() {
@Override
Expand Down Expand Up @@ -128,7 +127,6 @@ public void onEvent(BacktraceWatchdogTimeoutException exception) {
public void checkIsDisableWorks() {
// GIVEN
final Waiter waiter = new Waiter();
BacktraceLogger.setLevel(LogLevel.DEBUG);

backtraceClient.enableAnr(1000, new OnApplicationNotRespondingEvent() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package backtraceio.library.logger;

import android.util.Log;

import org.jetbrains.annotations.NotNull;

/**
* Backtrace Logger implementation class for logging messages within the Backtrace library.
* <p>
* This class leverages the {@link android.util.Log} package to output log messages.
* It provides a standardized way to log information, warnings, errors, and debug messages
* from within the library, making it easier to track and diagnose issues.
* </p>
*/
public class BacktraceInternalLogger implements Logger {

private static final String BASE_TAG = "BacktraceLogger: ";

/**
* Level from which all information is logged
*/
private int logLevel;

public BacktraceInternalLogger() {
this(LogLevel.OFF);
}

public BacktraceInternalLogger(@NotNull LogLevel logLevel) {
this.logLevel = logLevel.ordinal();
}

public int getLogLevel() {
return logLevel;
}

/**
* set logging level from which all messages should be logged to the console
*
* @param level login level
*/
public void setLevel(@NotNull LogLevel level) {
this.logLevel = level.ordinal();
}

/**
* @param tag source of logs, usually identifies the class or activity
* @param message text information which should be logged
* @return the number of bytes written
*/
public int d(String tag, String message) {
if (this.logLevel <= LogLevel.DEBUG.ordinal()) {
return Log.d(this.getTag(tag), message);
}
return 0;
}

/**
* Log messages that suggest something unexpected or rare has happened, which isn't an error.
*
* @param tag source of logs, usually identifies the class or activity
* @param message text information which should be logged
* @return the number of bytes written
*/
public int w(String tag, String message) {
if (this.logLevel <= LogLevel.WARN.ordinal()) {
return Log.w(this.getTag(tag), message);
}
return 0;
}

/**
* Log messages that suggest error or something that should not happen
*
* @param tag source of logs, usually identifies the class or activity
* @param message text information which should be logged
* @return the number of bytes written
*/
public int e(String tag, String message) {
if (this.logLevel <= LogLevel.ERROR.ordinal()) {
return Log.e(this.getTag(tag), message);
}
return 0;
}

/**
* Log messages that suggest error or something that should not happen
*
* @param tag source of logs, usually identifies the class or activity
* @param message text information which should be logged
* @param tr an exception to log
* @return the number of bytes written
*/
public int e(String tag, String message, Throwable tr) {
if (this.logLevel <= LogLevel.ERROR.ordinal()) {
return Log.e(this.getTag(tag), message, tr);
}
return 0;
}

private String getTag(String tag) {
return BacktraceInternalLogger.BASE_TAG + tag;
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
package backtraceio.library.logger;

import android.util.Log;
import org.jetbrains.annotations.NotNull;

/**
* Backtrace Logger class for logging messages from inside library
* A global logging utility for the Backtrace library.
* <p>
* {@code BacktraceLogger} acts as a wrapper around a {@link Logger} implementation,
* providing a centralized logging mechanism throughout the library. By default, it uses
* the {@link BacktraceInternalLogger}, which relies on {@code android.util.Log} for logging.
* However, the logger can be replaced with a custom implementation by using the
* {@link #setLogger(Logger)} method.
* </p>
* <p>
* This allows for flexibility in logging strategies, enabling developers to integrate
* their preferred logging framework or customize log handling as needed.
* </p>
*/
public class BacktraceLogger {

private static final String BASE_TAG = "BacktraceLogger: ";
/**
* Level from which all information is logged
*/
private static LogLevel logLevel = LogLevel.OFF;
private static Logger logger = new BacktraceInternalLogger();

/**
* set logging level from which all messages should be logged to the console
*
* @param level login level
*/
public static void setLevel(LogLevel level) {
BartoszLitwiniuk marked this conversation as resolved.
Show resolved Hide resolved
BacktraceLogger.logLevel = level;
public static Logger getLogger() {
return logger;
}

public static void setLogger(@NotNull Logger logger) {
if (logger == null) {
throw new IllegalArgumentException("Passed custom logger implementation can`t be null");
}
BacktraceLogger.logger = logger;
}

/**
Expand All @@ -28,10 +37,7 @@ public static void setLevel(LogLevel level) {
* @return the number of bytes written
*/
public static int d(String tag, String message) {
if (BacktraceLogger.logLevel.ordinal() <= LogLevel.DEBUG.ordinal()) {
return Log.d(getTag(tag), message);
}
return 0;
return logger.d(tag, message);
}

/**
Expand All @@ -42,10 +48,7 @@ public static int d(String tag, String message) {
* @return the number of bytes written
*/
public static int w(String tag, String message) {
if (BacktraceLogger.logLevel.ordinal() <= LogLevel.WARN.ordinal()) {
return Log.w(getTag(tag), message);
}
return 0;
return logger.w(tag, message);
}

/**
Expand All @@ -56,10 +59,7 @@ public static int w(String tag, String message) {
* @return the number of bytes written
*/
public static int e(String tag, String message) {
if (BacktraceLogger.logLevel.ordinal() <= LogLevel.ERROR.ordinal()) {
return Log.e(getTag(tag), message);
}
return 0;
return logger.e(tag, message);
}

/**
Expand All @@ -71,13 +71,22 @@ public static int e(String tag, String message) {
* @return the number of bytes written
*/
public static int e(String tag, String message, Throwable tr) {
if (BacktraceLogger.logLevel.ordinal() <= LogLevel.ERROR.ordinal()) {
return Log.e(getTag(tag), message, tr);
}
return 0;
return logger.e(tag, message, tr);
}

private static String getTag(String tag) {
return BacktraceLogger.BASE_TAG + tag;
/**
* Set logging level from which all messages should be logged to the console
* @param level login level (debug, warn, error, off)
*
* @deprecated setting the logging level should be done directly in the passed custom logger
* implementation so as not to depend on the internal implementation of Backtrace internal
* LogLevel types.
*
*/
@Deprecated
public static void setLevel(@NotNull LogLevel level) {
if (logger instanceof BacktraceInternalLogger) {
((BacktraceInternalLogger) logger).setLevel(level);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package backtraceio.library.logger;

/**
* The class is intended to determine the available levels of login messages
* Defines the logging levels for the Backtrace library.
* <p>
* Controls the severity of log messages:
* <ul>
* <li>{@link #DEBUG} - Logs detailed debug messages.</li>
* <li>{@link #WARN} - Logs warnings indicating potential issues.</li>
* <li>{@link #ERROR} - Logs error messages for failures.</li>
* <li>{@link #OFF} - Disables all logging.</li>
* </ul>
*/
public enum LogLevel {
/**
Expand Down
Loading
Loading