diff --git a/.circleci/config.yml b/.circleci/config.yml
index 22c2c9f..8881b36 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -4,7 +4,7 @@ commands:
steps:
- restore_cache:
keys:
- - v1-dependencies-{{ checksum "build.gradle.kts" }}-{{ checksum "annotations/build.gradle.kts" }}-{{ checksum "annotations-processor/build.gradle.kts" }}-{{ checksum "common/build.gradle.kts" }}
+ - v1-dependencies-{{ checksum "build.gradle.kts" }}-{{ checksum "annotations/build.gradle.kts" }}-{{ checksum "annotations-processor/build.gradle.kts" }}-{{ checksum "common/build.gradle.kts" }}-{{ checksum "liblogger/build.gradle.kts" }}
- v1-dependencies-
- run:
name: Download dependencies
@@ -12,7 +12,7 @@ commands:
- save_cache:
paths:
- ~/.gradle
- key: v1-dependencies-{{ checksum "build.gradle.kts" }}-{{ checksum "annotations/build.gradle.kts" }}-{{ checksum "annotations-processor/build.gradle.kts" }}-{{ checksum "common/build.gradle.kts" }}
+ key: v1-dependencies-{{ checksum "build.gradle.kts" }}-{{ checksum "annotations/build.gradle.kts" }}-{{ checksum "annotations-processor/build.gradle.kts" }}-{{ checksum "common/build.gradle.kts" }}-{{ checksum "liblogger/build.gradle.kts" }}
run-unit-tests:
steps:
diff --git a/Makefile b/Makefile
index 940fb31..716faf9 100644
--- a/Makefile
+++ b/Makefile
@@ -8,26 +8,30 @@ check:
buildDebug:
./gradlew annotations:assemble && \
./gradlew annotations-processor:assemble && \
- ./gradlew common:assembleDebug
+ ./gradlew common:assembleDebug && \
+ ./gradlew liblogger:assembleDebug
.PHONY: buildRelease
buildRelease:
./gradlew annotations:assemble && \
./gradlew annotations-processor:assemble && \
- ./gradlew common:assembleRelease
+ ./gradlew common:assembleRelease && \
+ ./gradlew liblogger:assembleRelease
.PHONY: bintrayPublish
bintrayPublish:
./gradlew :annotations:bintrayUpload ; \
./gradlew :annotations-processor:bintrayUpload ; \
./gradlew :common:bintrayUpload ; \
+ ./gradlew :liblogger:bintrayUpload ; \
.PHONY: artifactoryPublish
artifactoryPublish:
./gradlew :annotations:artifactoryPublish ; \
./gradlew :annotations-processor:artifactoryPublish ; \
./gradlew :common:artifactoryPublish ; \
+ ./gradlew :liblogger:artifactoryPublish ; \
.PHONY: runUnitTests
runUnitTests:
- ./gradlew examples:test
\ No newline at end of file
+ ./gradlew test
\ No newline at end of file
diff --git a/annotations-processor/gradle.properties b/annotations-processor/gradle.properties
index 88b07ae..b7f3857 100644
--- a/annotations-processor/gradle.properties
+++ b/annotations-processor/gradle.properties
@@ -1,4 +1,5 @@
IS_ANDROID_PROJECT=false
POM_ARTIFACT_ID=annotations-processor
+POM_ARTIFACT_GROUP_ID=com.mapbox.base
POM_ARTIFACT_TITLE=Mapbox Annotations Processor
POM_DESCRIPTION=Artifact that provides Mapbox module and plugin generators
\ No newline at end of file
diff --git a/annotations/gradle.properties b/annotations/gradle.properties
index 08879e2..7d6b885 100644
--- a/annotations/gradle.properties
+++ b/annotations/gradle.properties
@@ -1,4 +1,5 @@
IS_ANDROID_PROJECT=false
POM_ARTIFACT_ID=annotations
+POM_ARTIFACT_GROUP_ID=com.mapbox.base
POM_ARTIFACT_TITLE=Mapbox Annotations
POM_DESCRIPTION=Artifact that provides Mapbox module and plugin annotations
\ No newline at end of file
diff --git a/common/gradle.properties b/common/gradle.properties
index 6a25434..030215c 100644
--- a/common/gradle.properties
+++ b/common/gradle.properties
@@ -1,4 +1,5 @@
IS_ANDROID_PROJECT=true
POM_ARTIFACT_ID=common
+POM_ARTIFACT_GROUP_ID=com.mapbox.base
POM_ARTIFACT_TITLE=Mapbox Common
POM_DESCRIPTION=Artifact that provides Mapbox module and plugin contracts
\ No newline at end of file
diff --git a/common/src/main/java/com/mapbox/base/common/logger/Logger.kt b/common/src/main/java/com/mapbox/base/common/logger/Logger.kt
new file mode 100644
index 0000000..3fe9590
--- /dev/null
+++ b/common/src/main/java/com/mapbox/base/common/logger/Logger.kt
@@ -0,0 +1,59 @@
+package com.mapbox.base.common.logger
+
+import com.mapbox.base.common.logger.model.Message
+import com.mapbox.base.common.logger.model.Tag
+
+/**
+ * Logger definition
+ */
+interface Logger {
+ /**
+ * Send a verbose log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun v(tag: Tag? = null, msg: Message, tr: Throwable? = null)
+
+ /**
+ * Send a debug log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun d(tag: Tag? = null, msg: Message, tr: Throwable? = null)
+
+ /**
+ * Send an info log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun i(tag: Tag? = null, msg: Message, tr: Throwable? = null)
+
+ /**
+ * Send a warning log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun w(tag: Tag? = null, msg: Message, tr: Throwable? = null)
+
+ /**
+ * Send an error log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun e(tag: Tag? = null, msg: Message, tr: Throwable? = null)
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/mapbox/base/common/logger/model/Message.kt b/common/src/main/java/com/mapbox/base/common/logger/model/Message.kt
new file mode 100644
index 0000000..21509f2
--- /dev/null
+++ b/common/src/main/java/com/mapbox/base/common/logger/model/Message.kt
@@ -0,0 +1,8 @@
+package com.mapbox.base.common.logger.model
+
+/**
+ * Wrapper class for loggers message.
+ *
+ * @param message The message you would like logged.
+ */
+data class Message(val message: String)
\ No newline at end of file
diff --git a/common/src/main/java/com/mapbox/base/common/logger/model/Tag.kt b/common/src/main/java/com/mapbox/base/common/logger/model/Tag.kt
new file mode 100644
index 0000000..441bd62
--- /dev/null
+++ b/common/src/main/java/com/mapbox/base/common/logger/model/Tag.kt
@@ -0,0 +1,9 @@
+package com.mapbox.base.common.logger.model
+
+/**
+ * Wrapper class for loggers tag.
+ *
+ * @param tag used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ */
+data class Tag(val tag: String)
\ No newline at end of file
diff --git a/gradle/artifact-settings.gradle b/gradle/artifact-settings.gradle
index 9ecde3b..5a94839 100644
--- a/gradle/artifact-settings.gradle
+++ b/gradle/artifact-settings.gradle
@@ -1,5 +1,5 @@
ext {
- mapboxArtifactGroupId = 'com.mapbox.base'
+ mapboxArtifactGroupId = project.property('POM_ARTIFACT_GROUP_ID')
mapboxArtifactId = project.property('POM_ARTIFACT_ID')
mapboxArtifactTitle = project.property('POM_ARTIFACT_TITLE')
mapboxArtifactDescription = project.property('POM_DESCRIPTION')
diff --git a/gradle/bintray-publish.gradle b/gradle/bintray-publish.gradle
index b690332..31b4e62 100644
--- a/gradle/bintray-publish.gradle
+++ b/gradle/bintray-publish.gradle
@@ -55,7 +55,7 @@ bintray {
publications('MapboxBasePublication')
pkg {
repo = project.ext.mapboxBintrayRepoName
- name = project.ext.mapboxArtifactId
+ name = group + ':' + project.ext.mapboxArtifactId
userOrg = project.ext.mapboxBintrayUserOrg
licenses = [project.ext.mapboxArtifactLicenseName]
vcsUrl = project.ext.mapboxArtifactVcsUrl
diff --git a/liblogger/.gitignore b/liblogger/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/liblogger/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/liblogger/build.gradle.kts b/liblogger/build.gradle.kts
new file mode 100644
index 0000000..daa9c54
--- /dev/null
+++ b/liblogger/build.gradle.kts
@@ -0,0 +1,39 @@
+plugins {
+ id("com.android.library")
+ kotlin("android")
+ kotlin("kapt")
+ id("com.jaredsburrows.license")
+ id("org.jetbrains.dokka-android")
+}
+
+android {
+ compileSdkVersion(AndroidVersions.compileSdkVersion)
+
+ defaultConfig {
+ minSdkVersion(AndroidVersions.minSdkVersion)
+ targetSdkVersion(AndroidVersions.targetSdkVersion)
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ }
+}
+
+dependencies {
+ compileOnly(project(":annotations"))
+ kapt(project(":annotations-processor"))
+ implementation(project(":common"))
+ implementation(Dependencies.kotlin)
+
+ /**
+ * Required for @Keep annotation by the annotation-processor and the resulting generated code
+ */
+ implementation(Dependencies.annotations)
+
+ testImplementation(Dependencies.junit)
+ testImplementation(Dependencies.mockk)
+}
+
+project.apply {
+ from("$rootDir/gradle/ktlint.gradle")
+ from("$rootDir/gradle/lint.gradle")
+ from("$rootDir/gradle/android-artifacts.gradle")
+ from("$rootDir/gradle/bintray-publish.gradle")
+}
\ No newline at end of file
diff --git a/liblogger/gradle.properties b/liblogger/gradle.properties
new file mode 100644
index 0000000..c22fe5d
--- /dev/null
+++ b/liblogger/gradle.properties
@@ -0,0 +1,5 @@
+IS_ANDROID_PROJECT=true
+POM_ARTIFACT_ID=logger
+POM_ARTIFACT_GROUP_ID=com.mapbox.common
+POM_ARTIFACT_TITLE=Mapbox Logger
+POM_DESCRIPTION=Artifact that provides Mapbox Logger module implementation
\ No newline at end of file
diff --git a/liblogger/src/main/AndroidManifest.xml b/liblogger/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..dc15cd5
--- /dev/null
+++ b/liblogger/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
diff --git a/liblogger/src/main/java/com/mapbox/common/logger/LogEntry.kt b/liblogger/src/main/java/com/mapbox/common/logger/LogEntry.kt
new file mode 100644
index 0000000..7557066
--- /dev/null
+++ b/liblogger/src/main/java/com/mapbox/common/logger/LogEntry.kt
@@ -0,0 +1,15 @@
+package com.mapbox.common.logger
+
+/**
+ * Model of Log entry.
+ *
+ * @property tag The tag you would like your message will marked.
+ * @property message The message you would like logged.
+ * @property throwable The throwable you would like to log.
+ * @constructor Creates an [LogEntry]
+ */
+data class LogEntry(
+ val tag: String?,
+ val message: String,
+ val throwable: Throwable?
+)
\ No newline at end of file
diff --git a/liblogger/src/main/java/com/mapbox/common/logger/LogPriority.kt b/liblogger/src/main/java/com/mapbox/common/logger/LogPriority.kt
new file mode 100644
index 0000000..8df4b34
--- /dev/null
+++ b/liblogger/src/main/java/com/mapbox/common/logger/LogPriority.kt
@@ -0,0 +1,49 @@
+@file:JvmName("LogPriority")
+
+package com.mapbox.common.logger
+
+import android.util.Log
+
+/**
+ * Priority constant for the println method; use Logger.v
+ *
+ * This log priority will print all logs.
+ */
+const val VERBOSE = Log.VERBOSE
+
+/**
+ * Priority constant for the println method; use Logger.d.
+ *
+ * This log priority will print all logs except verbose.
+ */
+const val DEBUG = Log.DEBUG
+
+/**
+ * Priority constant for the println method; use Logger.i.
+ *
+ * This log priority will print all logs except verbose and debug.
+ *
+ */
+const val INFO = Log.INFO
+
+/**
+ * Priority constant for the println method; use Logger.w.
+ *
+ * This log priority will print only warn and error logs.
+ *
+ */
+const val WARN = Log.WARN
+
+/**
+ * Priority constant for the println method; use Logger.e.
+ *
+ * This log priority will print only error logs.
+ */
+const val ERROR = Log.ERROR
+
+/**
+ * Priority constant for the println method.
+ *
+ * This log priority won't print any logs.
+ */
+const val NONE = 99
\ No newline at end of file
diff --git a/liblogger/src/main/java/com/mapbox/common/logger/LoggerObserver.kt b/liblogger/src/main/java/com/mapbox/common/logger/LoggerObserver.kt
new file mode 100644
index 0000000..a60e2f8
--- /dev/null
+++ b/liblogger/src/main/java/com/mapbox/common/logger/LoggerObserver.kt
@@ -0,0 +1,17 @@
+package com.mapbox.common.logger
+
+import com.mapbox.common.logger.annotations.LogLevel
+
+/**
+ * Interface for observe logs we want to catch
+ */
+interface LoggerObserver {
+
+ /**
+ * Calls when [MapboxLogger] was log any [LogEntry].
+ *
+ * @param level is [LogLevel] used to identify the level of logged [LogEntry]
+ * @param entry is logged [LogEntry].
+ */
+ fun log(@LogLevel level: Int, entry: LogEntry)
+}
\ No newline at end of file
diff --git a/liblogger/src/main/java/com/mapbox/common/logger/MapboxLogger.kt b/liblogger/src/main/java/com/mapbox/common/logger/MapboxLogger.kt
new file mode 100644
index 0000000..db193f6
--- /dev/null
+++ b/liblogger/src/main/java/com/mapbox/common/logger/MapboxLogger.kt
@@ -0,0 +1,294 @@
+package com.mapbox.common.logger
+
+import android.util.Log
+import com.mapbox.annotation.module.MapboxModule
+import com.mapbox.annotation.module.MapboxModuleType
+import com.mapbox.base.common.logger.Logger
+import com.mapbox.base.common.logger.model.Message
+import com.mapbox.base.common.logger.model.Tag
+import com.mapbox.common.logger.annotations.LogLevel
+import java.util.concurrent.atomic.AtomicReference
+
+/**
+ * Mapbox implementation of [Logger] interface to log some messages with possibility to observe them
+ * via [LoggerObserver].
+ */
+@MapboxModule(MapboxModuleType.CommonLogger)
+object MapboxLogger : Logger {
+
+ private const val DEFAULT_TAG = "MapboxLogger"
+
+ /**
+ * [LogLevel] you want to log
+ */
+ @LogLevel
+ @Volatile
+ var logLevel: Int = VERBOSE
+
+ /**
+ * [LoggerObserver] for observe any log events
+ */
+ private val observer: AtomicReference = AtomicReference()
+
+ /**
+ * Set [LoggerObserver] to [MapboxLogger] to observe any log events
+ *
+ * @param observer is [LoggerObserver] you set to [MapboxLogger]
+ */
+ fun setObserver(observer: LoggerObserver) {
+ MapboxLogger.observer.set(observer)
+ }
+
+ /**
+ * Set [LoggerObserver] to [MapboxLogger] to observe any log events
+ *
+ * @param observer is [LoggerObserver] you set to [MapboxLogger]
+ */
+ fun removeObserver() {
+ observer.set(null)
+ }
+
+ /**
+ * Send a verbose log message.
+ *
+ * @param msg is [Message] you would like logged.
+ */
+ fun v(msg: Message) {
+ v(null, msg, null)
+ }
+
+ /**
+ * Send a verbose log message and log the exception.
+ *
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun v(msg: Message, tr: Throwable) {
+ v(null, msg, tr)
+ }
+
+ /**
+ * Send a tagged verbose log message
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ */
+ fun v(tag: Tag, msg: Message) {
+ v(tag, msg, null)
+ }
+
+ /**
+ * Send a tagged verbose log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ override fun v(tag: Tag?, msg: Message, tr: Throwable?) {
+ log(VERBOSE, tag?.tag, msg.message, tr) {
+ Log.v(tag?.tag ?: DEFAULT_TAG, msg.message, tr)
+ }
+ }
+
+ /**
+ * Send a debug log message.
+ *
+ * @param msg is [Message] you would like logged.
+ */
+ fun d(msg: Message) {
+ d(null, msg, null)
+ }
+
+ /**
+ * Send a debug log message and log the exception.
+ *
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun d(msg: Message, tr: Throwable) {
+ d(null, msg, tr)
+ }
+
+ /**
+ * Send a tagged debug log message.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ */
+ fun d(tag: Tag, msg: Message) {
+ d(tag, msg, null)
+ }
+
+ /**
+ * Send a tagged debug log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ override fun d(tag: Tag?, msg: Message, tr: Throwable?) {
+ log(DEBUG, tag?.tag, msg.message, tr) {
+ Log.d(tag?.tag ?: DEFAULT_TAG, msg.message, tr)
+ }
+ }
+
+ /**
+ * Send a info log message.
+ *
+ * @param msg is [Message] you would like logged.
+ */
+ fun i(msg: Message) {
+ i(null, msg, null)
+ }
+
+ /**
+ * Send a info log message and log the exception.
+ *
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun i(msg: Message, tr: Throwable) {
+ i(null, msg, tr)
+ }
+
+ /**
+ * Send a tagged info log message.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ */
+ fun i(tag: Tag, msg: Message) {
+ i(tag, msg, null)
+ }
+
+ /**
+ * Send a tagged info log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ override fun i(tag: Tag?, msg: Message, tr: Throwable?) {
+ log(INFO, tag?.tag, msg.message, tr) {
+ Log.i(tag?.tag ?: DEFAULT_TAG, msg.message, tr)
+ }
+ }
+
+ /**
+ * Send a warning log message.
+ *
+ * @param msg is [Message] you would like logged.
+ */
+ fun w(msg: Message) {
+ w(null, msg, null)
+ }
+
+ /**
+ * Send a warning log message and log the exception.
+ *
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun w(msg: Message, tr: Throwable) {
+ w(null, msg, tr)
+ }
+
+ /**
+ * Send a tagged warning log message.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ */
+ fun w(tag: Tag, msg: Message) {
+ w(tag, msg, null)
+ }
+
+ /**
+ * Send a tagged warning log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ override fun w(tag: Tag?, msg: Message, tr: Throwable?) {
+ log(WARN, tag?.tag, msg.message, tr) {
+ Log.w(tag?.tag ?: DEFAULT_TAG, msg.message, tr)
+ }
+ }
+
+ /**
+ * Send a error log message.
+ *
+ * @param msg is [Message] you would like logged.
+ */
+ fun e(msg: Message) {
+ e(null, msg, null)
+ }
+
+ /**
+ * Send a error log message and log the exception.
+ *
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ fun e(msg: Message, tr: Throwable) {
+ e(null, msg, tr)
+ }
+
+ /**
+ * Send a tagged error log message.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ */
+ fun e(tag: Tag, msg: Message) {
+ e(tag, msg, null)
+ }
+
+ /**
+ * Send a tagged error log message and log the exception.
+ *
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ */
+ override fun e(tag: Tag?, msg: Message, tr: Throwable?) {
+ log(ERROR, tag?.tag, msg.message, tr) {
+ Log.e(tag?.tag ?: DEFAULT_TAG, msg.message, tr)
+ }
+ }
+
+ /**
+ * Checks if [requiredLogLevel] enough for log, and if yes, set tag, log message and throwable and
+ * notice [observer] about log event
+ *
+ * @param requiredLogLevel is [LogLevel] use to define level of logged event
+ * @param tag is [Tag] used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg is [Message] you would like logged.
+ * @param tr An exception to log
+ * @param logBlock is block of directly logging
+ */
+ private fun log(
+ @LogLevel requiredLogLevel: Int,
+ tag: String?,
+ msg: String,
+ tr: Throwable?,
+ logBlock: () -> Unit
+ ) {
+ if (logLevel <= requiredLogLevel) {
+ logBlock()
+ observer.get()?.log(requiredLogLevel, LogEntry(tag, msg, tr))
+ }
+ }
+}
\ No newline at end of file
diff --git a/liblogger/src/main/java/com/mapbox/common/logger/annotations/LogLevel.kt b/liblogger/src/main/java/com/mapbox/common/logger/annotations/LogLevel.kt
new file mode 100644
index 0000000..8800f92
--- /dev/null
+++ b/liblogger/src/main/java/com/mapbox/common/logger/annotations/LogLevel.kt
@@ -0,0 +1,16 @@
+package com.mapbox.common.logger.annotations
+
+import androidx.annotation.IntDef
+import com.mapbox.common.logger.DEBUG
+import com.mapbox.common.logger.ERROR
+import com.mapbox.common.logger.INFO
+import com.mapbox.common.logger.NONE
+import com.mapbox.common.logger.VERBOSE
+import com.mapbox.common.logger.WARN
+
+/**
+ * Log level indicates which logs are allowed to be emitted by the Mapbox Maps SDK for Android.
+ */
+@IntDef(VERBOSE, DEBUG, INFO, WARN, ERROR, NONE)
+@Retention(AnnotationRetention.SOURCE)
+internal annotation class LogLevel
\ No newline at end of file
diff --git a/liblogger/src/test/java/com/mapbox/common/logger/MapboxLoggerTest.kt b/liblogger/src/test/java/com/mapbox/common/logger/MapboxLoggerTest.kt
new file mode 100644
index 0000000..0902f5a
--- /dev/null
+++ b/liblogger/src/test/java/com/mapbox/common/logger/MapboxLoggerTest.kt
@@ -0,0 +1,151 @@
+package com.mapbox.common.logger
+
+import android.util.Log
+import com.mapbox.base.common.logger.model.Message
+import com.mapbox.base.common.logger.model.Tag
+import io.mockk.*
+import org.junit.Before
+import org.junit.Test
+
+class MapboxLoggerTest {
+
+ @Before
+ fun setUp() {
+ mockkStatic(Log::class)
+ every { Log.v(any(), any(), any()) } returns 0
+ every { Log.d(any(), any(), any()) } returns 0
+ every { Log.i(any(), any(), any()) } returns 0
+ every { Log.w(any(), any(), any()) } returns 0
+ every { Log.e(any(), any(), any()) } returns 0
+ }
+
+ @Test
+ fun verboseTestSuccessful() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = VERBOSE
+
+ MapboxLogger.v(Tag("TAG"), Message("some message"), throwable)
+
+ verify { Log.v("TAG", "some message", throwable) }
+ verify { loggerObserver.log(VERBOSE, LogEntry("TAG", "some message", throwable)) }
+ }
+
+ @Test
+ fun verboseTestIncorrectLogLevel() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = DEBUG
+
+ MapboxLogger.v(Tag("TAG"), Message("some message"), throwable)
+
+ verify(exactly = 0) { Log.v(any(), any(), any()) }
+ verify(exactly = 0) { loggerObserver.log(any(), any()) }
+ }
+
+ @Test
+ fun debugTestSuccessful() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = DEBUG
+
+ MapboxLogger.d(Tag("TAG"), Message("some message"), throwable)
+
+ verify { Log.d("TAG", "some message", throwable) }
+ verify { loggerObserver.log(DEBUG, LogEntry("TAG", "some message", throwable)) }
+ }
+
+ @Test
+ fun debugTestIncorrectLogLevel() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = INFO
+
+ MapboxLogger.d(Tag("TAG"), Message("some message"), throwable)
+
+ verify(exactly = 0) { Log.d(any(), any(), any()) }
+ verify(exactly = 0) { loggerObserver.log(any(), any()) }
+ }
+
+ @Test
+ fun infoTestSuccessful() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = INFO
+
+ MapboxLogger.i(Tag("TAG"), Message("some message"), throwable)
+
+ verify { Log.i("TAG", "some message", throwable) }
+ verify { loggerObserver.log(INFO, LogEntry("TAG", "some message", throwable)) }
+ }
+
+ @Test
+ fun infoTestIncorrectLogLevel() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = WARN
+
+ MapboxLogger.i(Tag("TAG"), Message("some message"), throwable)
+
+ verify(exactly = 0) { Log.i(any(), any(), any()) }
+ verify(exactly = 0) { loggerObserver.log(any(), any()) }
+ }
+
+ @Test
+ fun warningTestSuccessful() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = WARN
+
+ MapboxLogger.w(Tag("TAG"), Message("some message"), throwable)
+
+ verify { Log.w("TAG", "some message", throwable) }
+ verify { loggerObserver.log(WARN, LogEntry("TAG", "some message", throwable)) }
+ }
+
+ @Test
+ fun warningTestIncorrectLogLevel() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = ERROR
+
+ MapboxLogger.w(Tag("TAG"), Message("some message"), throwable)
+
+ verify(exactly = 0) { Log.w(any(), any(), any()) }
+ verify(exactly = 0) { loggerObserver.log(any(), any()) }
+ }
+
+ @Test
+ fun errorTestSuccessful() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = ERROR
+
+ MapboxLogger.e(Tag("TAG"), Message("some message"), throwable)
+
+ verify { Log.e("TAG", "some message", throwable) }
+ verify { loggerObserver.log(ERROR, LogEntry("TAG", "some message", throwable)) }
+ }
+
+ @Test
+ fun errorTestIncorrectLogLevel() {
+ val throwable = mockk()
+ val loggerObserver = mockk(relaxed = true)
+ MapboxLogger.setObserver(loggerObserver)
+ MapboxLogger.logLevel = NONE
+
+ MapboxLogger.e(Tag("TAG"), Message("some message"), throwable)
+
+ verify(exactly = 0) { Log.e(any(), any(), any()) }
+ verify(exactly = 0) { loggerObserver.log(any(), any()) }
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index feb62b3..d450803 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,2 +1,2 @@
-include(":common", ":annotations", ":annotations-processor", ":examples")
+include(":common", ":annotations", ":annotations-processor", ":liblogger", ":examples")
rootProject.name = "Mapbox Base Android"
\ No newline at end of file