diff --git a/README.md b/README.md index 8f2d6f5..33a205e 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,16 @@ interface ChatSDKLogger { fun logDebug(message: () -> String) fun logWarn(message: () -> String) fun logError(message: () -> String) + fun setLoggingEnabled(enabled: Boolean) +} +``` + +#### `SDKLogger.setLoggingEnabled` +This API will allow you to enable and disable logging. + +``` +fun setLoggingEnabled(enabled: Boolean) { + this.logger.setLoggingEnabled(enabled) } ``` diff --git a/app/src/main/java/com/amazon/connect/chat/androidchatexample/utils/CustomLogger.kt b/app/src/main/java/com/amazon/connect/chat/androidchatexample/utils/CustomLogger.kt index 5eca7bd..58f3350 100644 --- a/app/src/main/java/com/amazon/connect/chat/androidchatexample/utils/CustomLogger.kt +++ b/app/src/main/java/com/amazon/connect/chat/androidchatexample/utils/CustomLogger.kt @@ -7,7 +7,6 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File -import java.io.FileNotFoundException import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -25,8 +24,16 @@ class CustomLogger : ChatSDKLogger { private val currentTimeMillis = System.currentTimeMillis() private val loggerCreationDateAndTime = CommonUtils.formatDate(currentTimeMillis, false) + private var loggingEnabled: Boolean = true + + //Custom logging logic + override fun setLoggingEnabled(enabled: Boolean) { + this.loggingEnabled = enabled + } + override fun logVerbose(message: () -> String) { // Custom logging logic + if (!loggingEnabled) return val logMessage = "VERBOSE: ${message()}" println(logMessage) coroutineScope.launch { @@ -36,6 +43,7 @@ class CustomLogger : ChatSDKLogger { override fun logInfo(message: () -> String) { // Custom logging logic + if (!loggingEnabled) return val logMessage = "INFO: ${message()}" println(logMessage) coroutineScope.launch { @@ -45,16 +53,17 @@ class CustomLogger : ChatSDKLogger { override fun logDebug(message: () -> String) { // Custom logging logic + if (!loggingEnabled) return val logMessage = "DEBUG: ${message()}" println(logMessage) coroutineScope.launch { writeToAppTempFile(logMessage) } - } override fun logWarn(message: () -> String) { // Custom logging logic + if (!loggingEnabled) return val logMessage = "WARN: ${message()}" println(logMessage) coroutineScope.launch { @@ -64,6 +73,7 @@ class CustomLogger : ChatSDKLogger { override fun logError(message: () -> String) { // Custom logging logic + if (!loggingEnabled) return val logMessage = "ERROR: ${message()}" println(logMessage) coroutineScope.launch { @@ -94,4 +104,4 @@ class CustomLogger : ChatSDKLogger { } } } -} +} \ No newline at end of file diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/model/MessageContent.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/model/MessageContent.kt index 009b433..2cfbdac 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/model/MessageContent.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/model/MessageContent.kt @@ -4,6 +4,7 @@ package com.amazon.connect.chat.sdk.model import com.amazon.connect.chat.sdk.utils.Constants +import com.amazon.connect.chat.sdk.utils.logger.SDKLogger import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json @@ -72,7 +73,7 @@ data class QuickReplyContent( val subtitle = quickReply.data.content.subtitle ?: "" // Fallback to empty string if null QuickReplyContent(title, subtitle, options) } catch (e: Exception) { - println("Error decoding QuickReplyContent: ${e.message}") + SDKLogger.logger.logError{"MessageContent: Error decoding QuickReplyContent: ${e.message}"} null } } @@ -130,14 +131,13 @@ data class ListPickerContent( val imageUrl = listPicker.data.content.imageData ?: "" ListPickerContent(title, subtitle, imageUrl, options) } catch (e: Exception) { - println("Error decoding ListPickerContent: ${e.message}") + SDKLogger.logger.logError{"MessageContent: Error decoding ListPickerContent: ${e.message}"} null } } } } - // Time Picker @Serializable data class TimeSlot( @@ -202,7 +202,7 @@ data class TimePickerContent( timeslots = contentData.timeslots ) } catch (e: SerializationException) { - println("Error decoding TimePickerContent: ${e.localizedMessage}") + SDKLogger.logger.logError{"MessageContent: Error decoding TimePickerContent: ${e.localizedMessage}"} null } } @@ -251,7 +251,7 @@ data class CarouselContent( elements = contentData.elements ) } catch (e: SerializationException) { - println("Error decoding CarouselContent: ${e.localizedMessage}") + SDKLogger.logger.logError{"MessageContent: Error decoding CarouselContent: ${e.localizedMessage}"} null } } @@ -314,9 +314,9 @@ data class PanelContent( options = contentData.elements ) } catch (e: SerializationException) { - println("Error decoding PanelContent: ${e.localizedMessage}") + SDKLogger.logger.logError{"MessageContent: Error decoding PanelContent: ${e.localizedMessage}"} null } } } -} \ No newline at end of file +} diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/network/WebSocketManager.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/network/WebSocketManager.kt index 5e21a19..127dc60 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/network/WebSocketManager.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/network/WebSocketManager.kt @@ -3,7 +3,6 @@ package com.amazon.connect.chat.sdk.network -import android.util.Log import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.ProcessLifecycleOwner @@ -82,7 +81,6 @@ class WebSocketManagerImpl @Inject constructor( _isReconnecting.value = value.value } - private var heartbeatManager: HeartbeatManager = HeartbeatManager( sendHeartbeatCallback = ::sendHeartbeat, missedHeartbeatCallback = ::onHeartbeatMissed @@ -120,7 +118,7 @@ class WebSocketManagerImpl @Inject constructor( reestablishConnectionIfChatActive() } else { isConnectedToNetwork = false - Log.d("WebSocketManager", "Network connection lost") + SDKLogger.logger.logInfo{"WebSocket: Network connection lost"} } } } @@ -129,11 +127,11 @@ class WebSocketManagerImpl @Inject constructor( val lifecycleObserver = LifecycleEventObserver { _, event -> when (event) { Lifecycle.Event.ON_RESUME -> { - Log.d("AppLifecycleObserver", "App in Foreground") + SDKLogger.logger.logInfo{"WebSocket: App in Foreground"} reestablishConnectionIfChatActive() } Lifecycle.Event.ON_STOP -> { - Log.d("AppLifecycleObserver", "App in Background") + SDKLogger.logger.logInfo{"WebSocket: App in Background"} if (isChatActive) { CoroutineScope(Dispatchers.IO).launch { closeWebSocket("App Backgrounded", 4000) @@ -149,7 +147,6 @@ class WebSocketManagerImpl @Inject constructor( ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleObserver) } - // --- Initialization and Connection Management --- override suspend fun connect(wsUrl: String, isReconnectFlow: Boolean) { @@ -199,16 +196,16 @@ class WebSocketManagerImpl @Inject constructor( } override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { - Log.i("WebSocket", "WebSocket is closing with code: $code, reason: $reason") + SDKLogger.logger.logInfo{"WebSocket: WebSocket is closing with code: $code, reason: $reason"} } override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { - Log.i("WebSocket", "WebSocket is closed with code: $code, reason: $reason") + SDKLogger.logger.logInfo{"WebSocket: WebSocket is closed with code: $code, reason: $reason"} handleWebSocketClosed(code, reason) } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - Log.e("WebSocket", "WebSocket failure: ${t.message}") + SDKLogger.logger.logError{"WebSocket: WebSocket failure: ${t.message}"} handleWebSocketFailure(t) } } @@ -226,7 +223,7 @@ class WebSocketManagerImpl @Inject constructor( } private fun handleWebSocketClosed(code: Int, reason: String) { - Log.i("WebSocket", "WebSocket closed with code: $code, reason: $reason") + SDKLogger.logger.logInfo{"WebSocket: WebSocket closed with code: $code, reason: $reason"} if (code == 1000) { isChatActive = false } else if (code != 4000) { @@ -235,7 +232,7 @@ class WebSocketManagerImpl @Inject constructor( } private fun handleWebSocketFailure(t: Throwable) { - Log.e("WebSocket", "WebSocket failure: ${t.message}") + SDKLogger.logger.logError{"WebSocket: WebSocket failure: ${t.message}"} if (t is IOException && t.message == "Software caused connection abort") { reestablishConnectionIfChatActive() } @@ -247,17 +244,15 @@ class WebSocketManagerImpl @Inject constructor( if (statusCode == 200 && statusContent == "OK") { deepHeartbeatManager.heartbeatReceived() } else { - Log.w("WebSocket", "Deep heartbeat failed. Status: $statusCode, StatusContent: $statusContent") + SDKLogger.logger.logWarn{"WebSocket: Deep heartbeat failed. Status: $statusCode, StatusContent: $statusContent"} } } - // --- Message Processing --- - private suspend fun processJsonContent(text: String) { val json = try { JSONObject(text) } catch (e: JSONException) { - Log.e("WebSocket", "Failed to parse JSON message: $text", e) + SDKLogger.logger.logError{"WebSocket: Failed to parse JSON message: $text and error $e"} return } @@ -266,10 +261,10 @@ class WebSocketManagerImpl @Inject constructor( "aws/ping" -> handlePing(json) "aws/heartbeat" -> handleHeartbeat() "aws/chat" -> { - SDKLogger.logger.logDebug { "Received chat message from websocket $json" } + SDKLogger.logger.logDebug{"WebSocket: Received chat message from websocket $json"} handleWebsocketMessage(json.optString("content")) } - else -> Log.i("WebSocket", "Unhandled topic: $topic") + else -> SDKLogger.logger.logInfo{"WebSocket: Unhandled topic: $topic"} } } @@ -279,10 +274,10 @@ class WebSocketManagerImpl @Inject constructor( if (transcriptItem != null) { this._transcriptPublisher.emit(transcriptItem) } else { - Log.i("WebSocket", "Received unrecognized or unsupported content.") + SDKLogger.logger.logInfo{"WebSocket: Received unrecognized or unsupported content."} } } ?: run { - Log.w("WebSocket", "Received null or empty content in chat message") + SDKLogger.logger.logWarn{"WebSocket: Received null or empty content in chat message"} } } @@ -290,7 +285,7 @@ class WebSocketManagerImpl @Inject constructor( val json = try { JSONObject(jsonString) } catch (e: JSONException) { - Log.e("WebSocket", "Failed to parse inner JSON content: $jsonString", e) + SDKLogger.logger.logError{"WebSocket: Failed to parse inner JSON content: $jsonString: ${e.message}"} return null } @@ -308,7 +303,7 @@ class WebSocketManagerImpl @Inject constructor( ContentType.TYPING -> handleTyping(jsonObject, jsonString) ContentType.ENDED -> handleChatEnded(jsonObject, jsonString) else -> { - Log.w("WebSocket", "Unknown event: $eventType") + SDKLogger.logger.logWarn{"WebSocket: Unknown event: $eventType"} null } } @@ -316,7 +311,7 @@ class WebSocketManagerImpl @Inject constructor( WebSocketMessageType.ATTACHMENT -> handleAttachment(jsonObject, jsonString) WebSocketMessageType.MESSAGE_METADATA -> handleMetadata(jsonObject, jsonString) else -> { - Log.w("WebSocket", "Unknown websocket message type: $type") + SDKLogger.logger.logWarn{"WebSocket: Unknown websocket message type: $type"} null } } @@ -350,9 +345,9 @@ class WebSocketManagerImpl @Inject constructor( private fun onHeartbeatMissed() { if (isConnectedToNetwork) { - Log.w("WebSocket", "Heartbeat missed") - }else { - Log.w("WebSocket", "Heartbeat missed, no internet connection") + SDKLogger.logger.logWarn{"WebSocket: Heartbeat missed"} + } else { + SDKLogger.logger.logWarn{"WebSocket: Heartbeat missed, no internet connection"} } } @@ -360,33 +355,31 @@ class WebSocketManagerImpl @Inject constructor( this._eventPublisher.emit(ChatEvent.DeepHeartBeatFailure) if (isConnectedToNetwork) { reestablishConnectionIfChatActive() - Log.w("WebSocket", "Deep Heartbeat missed, retrying connection") + SDKLogger.logger.logWarn{"WebSocket: Deep Heartbeat missed, retrying connection"} } else { - Log.w("WebSocket", "Deep Heartbeat missed, no internet connection") + SDKLogger.logger.logWarn{"WebSocket: Deep Heartbeat missed, no internet connection"} } val success = this._eventPublisher.tryEmit(ChatEvent.ConnectionBroken) if (!success) { - Log.d("WebSocket", "Failed to emit ConnectionBroken event, " + - "no subscribers and no buffer capacity") + SDKLogger.logger.logDebug{"WebSocket: Failed to emit ConnectionBroken event, no subscribers and no buffer capacity"} } } - // --- Helper Methods --- private fun reestablishConnectionIfChatActive() { if (!isChatActive) { - Log.d("WebSocket", "Re-connection aborted due to inactive chat session") + SDKLogger.logger.logDebug{"WebSocket: Re-connection aborted due to inactive chat session"} return } if (!isConnectedToNetwork) { - Log.d("WebSocket", "Re-connection aborted due to missing network connectivity") + SDKLogger.logger.logDebug{"WebSocket: Re-connection aborted due to missing network connectivity"} return } if (isChatSuspended) { - Log.d("WebSocket", "Re-connection aborted due to suspended chat session.") + SDKLogger.logger.logDebug{"WebSocket: Re-connection aborted due to suspended chat session."} return } if (_isReconnecting.value) { - Log.d("WebSocket", "Re-connection aborted due to ongoing reconnection attempt.") + SDKLogger.logger.logDebug{"WebSocket: Re-connection aborted due to ongoing reconnection attempt."} return } @@ -456,7 +449,7 @@ class WebSocketManagerImpl @Inject constructor( val event = Event( timeStamp = time, - contentType = innerJson.getString("ContentType"), + contentType = innerJson.getString("ContentType"), id = eventId, displayName = displayName, participant = participantRole, @@ -469,9 +462,8 @@ class WebSocketManagerImpl @Inject constructor( val time = innerJson.getString("AbsoluteTime") val eventId = innerJson.getString("Id") val isFromPastSession = innerJson.optBoolean("isFromPastSession", false) - + // Current session event: Reset state and update session if (!isFromPastSession) { - // Current session event: Reset state and update session resetHeartbeatManagers() this._eventPublisher.emit(ChatEvent.ChatEnded) connectionDetailsProvider.setChatSessionState(false) @@ -479,7 +471,7 @@ class WebSocketManagerImpl @Inject constructor( val event = Event( timeStamp = time, - contentType = innerJson.getString("ContentType"), + contentType = innerJson.getString("ContentType"), id = eventId, eventDirection = MessageDirection.COMMON, serializedContent = rawData @@ -519,10 +511,9 @@ class WebSocketManagerImpl @Inject constructor( val displayName = innerJson.getString("DisplayName") val messageId = innerJson.getString("Id") - // Access the attachments array using getJSONArray and safely convert it to a list of JSONObjects val attachmentsArray = innerJson.optJSONArray("Attachments") ?: return null if (attachmentsArray.length() == 0) { - println("No attachments found") + SDKLogger.logger.logInfo{"WebSocket: No attachments found"} return null } @@ -534,9 +525,8 @@ class WebSocketManagerImpl @Inject constructor( val contentType = firstAttachment.optString("ContentType") val attachmentId = firstAttachment.optString("AttachmentId") - // Check if any required fields are missing if (attachmentName == null || contentType == null || attachmentId == null) { - println("Failed to access attachments") + SDKLogger.logger.logError{"WebSocket: Failed to access attachments"} return null } diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/repository/AttachmentsManager.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/repository/AttachmentsManager.kt index 9c9a1d8..07706cb 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/repository/AttachmentsManager.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/repository/AttachmentsManager.kt @@ -6,12 +6,12 @@ package com.amazon.connect.chat.sdk.repository import android.content.Context import android.net.Uri import android.provider.OpenableColumns -import android.util.Log import com.amazon.connect.chat.sdk.network.api.APIClient import com.amazon.connect.chat.sdk.network.AWSClient import javax.inject.Inject import java.util.* import com.amazon.connect.chat.sdk.utils.Constants +import com.amazon.connect.chat.sdk.utils.logger.SDKLogger import com.amazonaws.services.connectparticipant.model.CompleteAttachmentUploadRequest import com.amazonaws.services.connectparticipant.model.StartAttachmentUploadRequest import kotlinx.coroutines.CoroutineScope @@ -38,7 +38,7 @@ class AttachmentsManager @Inject constructor( createStartAttachmentUploadRequest(connectionToken, fileUri) val fileExtension = getFileExtension(startAttachmentUploadRequest.attachmentName) if (!Constants.attachmentTypeMap.containsKey(fileExtension)) { - Log.d("AttachmentsManager", "Unsupported file type: $fileExtension") + SDKLogger.logger.logDebug{"AttachmentsManager: Unsupported file type: $fileExtension"} throw Exception("Unsupported file type") } @@ -62,7 +62,7 @@ class AttachmentsManager @Inject constructor( completeAttachmentUpload(connectionToken, attachmentId) } else { val exception = response?.message() - println("Error occurred: $exception") + SDKLogger.logger.logError{"AttachmentsManager: Error occurred: $exception"} } file.deleteRecursively() } @@ -82,7 +82,7 @@ class AttachmentsManager @Inject constructor( val completeAttachmentUploadResponse = completeAttachmentUploadResult.getOrNull() if (completeAttachmentUploadResponse == null) { val exception = completeAttachmentUploadResult.exceptionOrNull() - println("Error occurred: ${exception?.message}") + SDKLogger.logger.logError{"AttachmentsManager: Error occurred: ${exception?.message}"} return } } @@ -122,7 +122,7 @@ class AttachmentsManager @Inject constructor( return getAttachmentDownloadUrl(connectionToken, attachmentId).mapCatching { url -> downloadFile(url, fileName).getOrThrow() }.onFailure { - Log.e("AttachmentsManager", "Error occurred during downloadAttachment: ${it.message}") + SDKLogger.logger.logError{"AttachmentsManager: Error occurred during downloadAttachment: ${it.message}"} } } @@ -131,7 +131,7 @@ class AttachmentsManager @Inject constructor( val response = awsClient.getAttachment(connectionToken, attachmentId) URL(response.getOrNull()?.url ?: throw IOException("Invalid URL")) }.onFailure { - Log.e("AttachmentsManager", "Error occurred during getAttachmentDownloadUrl: ${it.message}") + SDKLogger.logger.logError{"AttachmentsManager: Error occurred during getAttachmentDownloadUrl: ${it.message}"} } } @@ -163,15 +163,14 @@ class AttachmentsManager @Inject constructor( } tempFilePath.also { - Log.d("AttachmentsManager", "File successfully downloaded to: ${it.absolutePath}") + SDKLogger.logger.logDebug{"AttachmentsManager: File successfully downloaded to: ${it.absolutePath}"} }.toURI().toURL() }.onFailure { - Log.e("AttachmentsManager", "Error occurred during downloadFile: ${it.message}") + SDKLogger.logger.logError{"AttachmentsManager: Error occurred during downloadFile: ${it.message}"} } } fun fileFromContentUri(contentUri: Uri, fileExtension: String?): File { - val fileName = "temp_file" + if (fileExtension != null) ".$fileExtension" else "" val tempFile = File(context.cacheDir, fileName) diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/TranscriptItemUtils.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/TranscriptItemUtils.kt index a25279a..eba926c 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/TranscriptItemUtils.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/TranscriptItemUtils.kt @@ -3,7 +3,6 @@ package com.amazon.connect.chat.sdk.utils -import android.util.Log import com.amazon.connect.chat.sdk.model.ContentType import com.amazon.connect.chat.sdk.model.Event import com.amazon.connect.chat.sdk.model.Message @@ -11,6 +10,7 @@ import com.amazon.connect.chat.sdk.model.MessageDirection import com.amazon.connect.chat.sdk.model.MessageMetadata import com.amazon.connect.chat.sdk.model.MessageStatus import com.amazonaws.services.connectparticipant.model.Item +import com.amazon.connect.chat.sdk.utils.logger.SDKLogger import org.json.JSONObject import java.util.UUID @@ -115,7 +115,7 @@ object TranscriptItemUtils { json.optString("content") } catch (e: Exception) { - Log.e("TranscriptItemUtils", "Failed to process transcript item: ${e.message}") + SDKLogger.logger.logError{"TranscriptItemUtils: Failed to process transcript item: ${e.message}"} null } } diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/ChatSDKLogger.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/ChatSDKLogger.kt index de1c699..d3bdbfb 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/ChatSDKLogger.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/ChatSDKLogger.kt @@ -11,4 +11,5 @@ interface ChatSDKLogger { fun logDebug(message: () -> String) fun logWarn(message: () -> String) fun logError(message: () -> String) + fun setLoggingEnabled(enabled: Boolean) } \ No newline at end of file diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/SDKLogger.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/SDKLogger.kt index d67741f..854ce41 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/SDKLogger.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/SDKLogger.kt @@ -9,4 +9,8 @@ object SDKLogger { fun configureLogger(logger: ChatSDKLogger) { this.logger = logger } + + fun setLoggingEnabled(enabled: Boolean) { + this.logger.setLoggingEnabled(enabled) + } } \ No newline at end of file diff --git a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/SDKLoggerImpl.kt b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/SDKLoggerImpl.kt index c089723..6e4e73f 100644 --- a/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/SDKLoggerImpl.kt +++ b/chat-sdk/src/main/java/com/amazon/connect/chat/sdk/utils/logger/SDKLoggerImpl.kt @@ -5,24 +5,46 @@ package com.amazon.connect.chat.sdk.utils.logger import android.util.Log -class SDKLoggerImpl (private val tag: String = "ChatSDK"): ChatSDKLogger { +class SDKLoggerImpl( + private val tag: String = "ChatSDK", + ) : ChatSDKLogger { + private var loggingEnabled: Boolean = true + + /** + * Sets whether logging is enabled for this logger instance. + * @param enabled true to enable logging, false to disable. + */ + override fun setLoggingEnabled(enabled: Boolean) { + this.loggingEnabled = enabled + } + override fun logVerbose(message: () -> String) { - Log.v(tag, message()) + if (loggingEnabled) { + Log.v(tag, message()) + } } override fun logInfo(message: () -> String) { - Log.i(tag, message()) + if (loggingEnabled) { + Log.i(tag, message()) + } } override fun logDebug(message: () -> String) { - Log.d(tag, message()) + if (loggingEnabled) { + Log.d(tag, message()) + } } override fun logWarn(message: () -> String) { - Log.w(tag, message()) + if (loggingEnabled) { + Log.w(tag, message()) + } } override fun logError(message: () -> String) { - Log.e(tag, message()) + if (loggingEnabled) { + Log.e(tag, message()) + } } } \ No newline at end of file