Add better logging for ovesized messages.

This commit is contained in:
Greyson Parrelli
2026-02-12 12:15:39 -05:00
committed by Alex Hart
parent caa743aba2
commit ae04749336
3 changed files with 249 additions and 98 deletions

View File

@@ -12,8 +12,10 @@ import com.squareup.wire.Message
import com.squareup.wire.ProtoAdapter
import com.squareup.wire.ProtoReader
import com.squareup.wire.ProtoWriter
import com.squareup.wire.WireField
import okio.Buffer
import okio.ByteString
import okio.utf8Size
import org.signal.core.util.logging.Log
import java.io.IOException
import java.util.LinkedList
@@ -87,6 +89,96 @@ fun writeUnknownEnumValue(tag: Int, enumValue: Int): ByteString {
return buffer.readByteString()
}
/**
* Builds a human-readable tree of serialized sizes for this proto message,
* recursively descending into all nested message fields. Useful for debugging
* oversized messages.
*
* Example output:
* ```
* Content(1234)
* dataMessage(1100)
* body(500)
* groupV2(400)
* groupChange(350)
* attachments[2](200)
* ```
*/
fun Message<*, *>.buildSizeTree(name: String): String {
val sb = StringBuilder()
appendSizeTree(name, 0, sb)
return sb.toString()
}
@Suppress("UNCHECKED_CAST")
private fun Message<*, *>.appendSizeTree(name: String, depth: Int, sb: StringBuilder) {
val totalSize = (adapter as ProtoAdapter<Message<*, *>>).encodedSize(this)
repeat(depth) { sb.append(" ") }
sb.append(name).append("(").append(totalSize).append(")")
for (field in this.javaClass.declaredFields) {
field.getAnnotation(WireField::class.java) ?: continue
val value = try {
field.get(this)
} catch (_: IllegalAccessException) {
continue
} ?: continue
val fieldName = field.name
when (value) {
is Message<*, *> -> {
sb.append("\n")
value.appendSizeTree(fieldName, depth + 1, sb)
}
is List<*> -> {
if (value.isNotEmpty()) {
var listTotalSize = 0
val isMessageList = value[0] is Message<*, *>
for (item in value) {
when (item) {
is Message<*, *> -> listTotalSize += (item.adapter as ProtoAdapter<Message<*, *>>).encodedSize(item)
is ByteString -> listTotalSize += item.size
is String -> listTotalSize += item.utf8Size().toInt()
}
}
sb.append("\n")
repeat(depth + 1) { sb.append(" ") }
sb.append(fieldName).append("[").append(value.size).append("](").append(listTotalSize).append(")")
if (isMessageList) {
for (i in value.indices) {
sb.append("\n")
(value[i] as Message<*, *>).appendSizeTree("${fieldName}[$i]", depth + 2, sb)
}
}
}
}
is ByteString -> {
if (value.size > 0) {
sb.append("\n")
repeat(depth + 1) { sb.append(" ") }
sb.append(fieldName).append("(").append(value.size).append(")")
}
}
is String -> {
if (value.isNotEmpty()) {
sb.append("\n")
repeat(depth + 1) { sb.append(" ") }
sb.append(fieldName).append("(").append(value.utf8Size().toInt()).append(")")
}
}
}
}
if (unknownFields.size > 0) {
sb.append("\n")
repeat(depth + 1) { sb.append(" ") }
sb.append("unknownFields(").append(unknownFields.size).append(")")
}
}
/**
* Recursively retrieves all inner complex proto types inside a given proto.
*/