392 lines
12 KiB
Kotlin
392 lines
12 KiB
Kotlin
package com.rosetta.messenger.utils
|
||
|
||
import android.util.Log
|
||
import com.rosetta.messenger.network.ProtocolManager
|
||
|
||
/**
|
||
* Утилита для логирования сообщений
|
||
* Безопасна для release сборки - логи не выводятся в production
|
||
*
|
||
* Логи отображаются:
|
||
* 1. В Logcat (всегда в debug)
|
||
* 2. В Debug Logs внутри чата (через ProtocolManager.debugLogs)
|
||
*/
|
||
object MessageLogger {
|
||
private const val TAG = "RosettaMsg"
|
||
|
||
// Всегда включён — вывод идёт только в ProtocolManager.addLog() (in-memory UI),
|
||
// не в logcat, безопасно для release
|
||
private val isEnabled: Boolean = true
|
||
|
||
/**
|
||
* Добавить лог в UI (Debug Logs в чате)
|
||
*/
|
||
private fun addToUI(message: String) {
|
||
ProtocolManager.addLog(message)
|
||
}
|
||
|
||
/**
|
||
* Логирование отправки сообщения
|
||
*/
|
||
fun logSendStart(
|
||
messageId: String,
|
||
toPublicKey: String,
|
||
textLength: Int,
|
||
attachmentsCount: Int,
|
||
isSavedMessages: Boolean,
|
||
replyToMessageId: String?
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val shortKey = toPublicKey.take(12)
|
||
val replyStr = replyToMessageId?.take(8) ?: "-"
|
||
val msg = "📤 SEND | id:$shortId to:$shortKey len:$textLength att:$attachmentsCount saved:$isSavedMessages reply:$replyStr"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование успешного шифрования
|
||
*/
|
||
fun logEncryptionSuccess(
|
||
messageId: String,
|
||
encryptedContentLength: Int,
|
||
encryptedKeyLength: Int
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val msg = "🔐 ENCRYPT | id:$shortId content:${encryptedContentLength}b key:${encryptedKeyLength}b"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование сохранения в БД
|
||
*/
|
||
fun logDbSave(
|
||
messageId: String,
|
||
dialogKey: String,
|
||
isNew: Boolean
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val shortDialog = dialogKey.take(12)
|
||
val msg = "💾 DB | id:$shortId dialog:$shortDialog new:$isNew"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование отправки пакета на сервер
|
||
*/
|
||
fun logPacketSend(
|
||
messageId: String,
|
||
toPublicKey: String,
|
||
timestamp: Long
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val shortKey = toPublicKey.take(12)
|
||
val msg = "📡 PACKET→ | id:$shortId to:$shortKey ts:$timestamp"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование успешной отправки
|
||
*/
|
||
fun logSendSuccess(messageId: String, duration: Long) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val msg = "✅ SENT | id:$shortId time:${duration}ms"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование ошибки отправки
|
||
*/
|
||
fun logSendError(messageId: String, error: Throwable) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val errMsg = error.message?.take(50) ?: "unknown"
|
||
val msg = "❌ SEND ERR | id:$shortId err:$errMsg"
|
||
Log.e(TAG, msg, error)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование входящего сообщения
|
||
*/
|
||
fun logReceiveStart(
|
||
messageId: String,
|
||
fromPublicKey: String,
|
||
toPublicKey: String,
|
||
contentLength: Int,
|
||
attachmentsCount: Int,
|
||
timestamp: Long
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val shortFrom = fromPublicKey.take(12)
|
||
val shortTo = toPublicKey.take(12)
|
||
val msg = "📥 RECV | id:$shortId from:$shortFrom to:$shortTo len:${contentLength}b att:$attachmentsCount ts:$timestamp"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование проверки на дубликат
|
||
*/
|
||
fun logDuplicateCheck(messageId: String, isDuplicate: Boolean) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val status = if (isDuplicate) "⚠️DUP" else "✓NEW"
|
||
val msg = "🔍 CHECK | id:$shortId $status"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование блокировки отправителя
|
||
*/
|
||
fun logBlockedSender(fromPublicKey: String) {
|
||
if (!isEnabled) return
|
||
val shortKey = fromPublicKey.take(12)
|
||
val msg = "🚫 BLOCKED | from:$shortKey"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование успешной расшифровки
|
||
*/
|
||
fun logDecryptionSuccess(
|
||
messageId: String,
|
||
plainTextLength: Int,
|
||
attachmentsCount: Int
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val msg = "🔓 DECRYPT | id:$shortId text:${plainTextLength}c att:$attachmentsCount"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование ошибки расшифровки
|
||
*/
|
||
fun logDecryptionError(messageId: String, error: Throwable) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val errMsg = error.message?.take(50) ?: "unknown"
|
||
val msg = "❌ DECRYPT ERR | id:$shortId err:$errMsg"
|
||
Log.e(TAG, msg, error)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование успешного получения
|
||
*/
|
||
fun logReceiveSuccess(messageId: String, duration: Long) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val msg = "✅ RECEIVED | id:$shortId time:${duration}ms"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование обновления статуса доставки
|
||
*/
|
||
fun logDeliveryStatus(
|
||
messageId: String,
|
||
toPublicKey: String,
|
||
status: String
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortId = messageId.take(8)
|
||
val shortKey = toPublicKey.take(12)
|
||
val msg = "📬 DELIVERY | id:$shortId to:$shortKey status:$status"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование прочтения сообщений
|
||
*/
|
||
fun logReadStatus(
|
||
fromPublicKey: String,
|
||
messagesCount: Int
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortKey = fromPublicKey.take(12)
|
||
val msg = "👁 READ | from:$shortKey count:$messagesCount"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование обновления диалога
|
||
*/
|
||
fun logDialogUpdate(
|
||
dialogKey: String,
|
||
lastMessage: String?,
|
||
unreadCount: Int
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortDialog = dialogKey.take(12)
|
||
val shortMsg = lastMessage?.take(20) ?: "-"
|
||
val msg = "📋 DIALOG | key:$shortDialog last:\"$shortMsg\" unread:$unreadCount"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование обновления кэша
|
||
*/
|
||
fun logCacheUpdate(dialogKey: String, totalMessages: Int) {
|
||
if (!isEnabled) return
|
||
val shortDialog = dialogKey.take(12)
|
||
val msg = "🗃 CACHE | dialog:$shortDialog total:$totalMessages"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование расшифровки фото (inline blob)
|
||
*/
|
||
fun logPhotoDecryptStart(
|
||
messageId: String,
|
||
attachmentId: String,
|
||
blobSize: Int
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortMsgId = messageId.take(8)
|
||
val shortAttId = attachmentId.take(8)
|
||
val msg = "🖼️ PHOTO DECRYPT | msg:$shortMsgId att:$shortAttId blob:${blobSize}b"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование успешной расшифровки фото
|
||
*/
|
||
fun logPhotoDecryptSuccess(
|
||
messageId: String,
|
||
attachmentId: String,
|
||
saved: Boolean
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortMsgId = messageId.take(8)
|
||
val shortAttId = attachmentId.take(8)
|
||
val msg = "✅ PHOTO OK | msg:$shortMsgId att:$shortAttId saved:$saved"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование ошибки расшифровки фото (blob null)
|
||
*/
|
||
fun logPhotoDecryptFailed(
|
||
messageId: String,
|
||
attachmentId: String
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortMsgId = messageId.take(8)
|
||
val shortAttId = attachmentId.take(8)
|
||
val msg = "❌ PHOTO DECRYPT FAIL | msg:$shortMsgId att:$shortAttId (decryptedBlob=null)"
|
||
Log.e(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование ошибки сохранения фото
|
||
*/
|
||
fun logPhotoSaveFailed(
|
||
messageId: String,
|
||
attachmentId: String
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortMsgId = messageId.take(8)
|
||
val shortAttId = attachmentId.take(8)
|
||
val msg = "⚠️ PHOTO SAVE FAIL | msg:$shortMsgId att:$shortAttId"
|
||
Log.e(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование исключения при расшифровке фото
|
||
*/
|
||
fun logPhotoDecryptError(
|
||
messageId: String,
|
||
attachmentId: String,
|
||
error: Throwable
|
||
) {
|
||
if (!isEnabled) return
|
||
val shortMsgId = messageId.take(8)
|
||
val shortAttId = attachmentId.take(8)
|
||
val errMsg = error.message?.take(80) ?: "unknown"
|
||
val msg = "❌ PHOTO ERR | msg:$shortMsgId att:$shortAttId err:$errMsg"
|
||
Log.e(TAG, msg, error)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование CDN загрузки фото
|
||
*/
|
||
fun logPhotoCdnDownload(message: String) {
|
||
if (!isEnabled) return
|
||
val msg = "🖼️ $message"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование успешной отправки read receipt
|
||
*/
|
||
fun logReadReceiptSent(opponentKey: String, retry: Boolean = false) {
|
||
if (!isEnabled) return
|
||
val shortKey = opponentKey.take(12)
|
||
val retryStr = if (retry) " (retry)" else ""
|
||
val msg = "👁 READ RECEIPT SENT$retryStr | to:$shortKey"
|
||
Log.d(TAG, msg)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Логирование ошибки отправки read receipt
|
||
*/
|
||
fun logReadReceiptFailed(opponentKey: String, error: Throwable, retry: Boolean = false) {
|
||
if (!isEnabled) return
|
||
val shortKey = opponentKey.take(12)
|
||
val errMsg = error.message?.take(50) ?: "unknown"
|
||
val retryStr = if (retry) " (retry)" else ""
|
||
val msg = "❌ READ RECEIPT FAIL$retryStr | to:$shortKey err:$errMsg"
|
||
Log.e(TAG, msg, error)
|
||
addToUI(msg)
|
||
}
|
||
|
||
/**
|
||
* Общий debug лог
|
||
*/
|
||
fun debug(message: String) {
|
||
if (!isEnabled) return
|
||
Log.d(TAG, message)
|
||
addToUI(message)
|
||
}
|
||
|
||
/**
|
||
* Общий error лог
|
||
*/
|
||
fun error(message: String, error: Throwable? = null) {
|
||
if (!isEnabled) return
|
||
if (error != null) {
|
||
Log.e(TAG, message, error)
|
||
} else {
|
||
Log.e(TAG, message)
|
||
}
|
||
addToUI("❌ $message")
|
||
}
|
||
}
|