From 77f29fc343c96c42f1a3ea22a70c2b5d9572203c Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Thu, 26 Dec 2024 15:35:08 +0900 Subject: [PATCH] Log and report terrible errors for improved debugging and tracking When a terrible error occurs, this change ensures that it is both logged using Log.wtf() and reported via a dedicated metric. This dual approach provides comprehensive error information for debugging in dogfood environments (Log.wtf()) and tracks the occurrence of these errors in production (via metrics). Test: TH Change-Id: Ic376f3789ab0cc9b094e79301849492143ed777c --- .../net/module/util/TerribleErrorLog.java | 41 +++++++++++++++ .../net/module/util/TerribleErrorLogTest.kt | 50 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 staticlibs/framework/com/android/net/module/util/TerribleErrorLog.java create mode 100644 staticlibs/tests/unit/src/com/android/net/module/util/TerribleErrorLogTest.kt diff --git a/staticlibs/framework/com/android/net/module/util/TerribleErrorLog.java b/staticlibs/framework/com/android/net/module/util/TerribleErrorLog.java new file mode 100644 index 0000000000..b4f7642b62 --- /dev/null +++ b/staticlibs/framework/com/android/net/module/util/TerribleErrorLog.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.net.module.util; + +import android.annotation.NonNull; +import android.util.Log; + +import java.util.function.BiConsumer; + +/** + * Utility class for logging terrible errors and reporting them for tracking. + * + * @hide + */ +public class TerribleErrorLog { + + private static final String TAG = TerribleErrorLog.class.getSimpleName(); + + /** + * Logs a terrible error and reports metrics through a provided statsLog. + */ + public static void logTerribleError(@NonNull BiConsumer statsLog, + @NonNull String message, int protoType, int errorType) { + statsLog.accept(protoType, errorType); + Log.wtf(TAG, message); + } +} diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/TerribleErrorLogTest.kt b/staticlibs/tests/unit/src/com/android/net/module/util/TerribleErrorLogTest.kt new file mode 100644 index 0000000000..5fd634e210 --- /dev/null +++ b/staticlibs/tests/unit/src/com/android/net/module/util/TerribleErrorLogTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.net.module.util + +import android.util.Log +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.testutils.tryTest +import kotlin.test.assertContentEquals +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +@SmallTest +class TerribleErrorLogTest { + @Test + fun testLogTerribleError() { + val wtfCaptures = mutableListOf() + val prevHandler = Log.setWtfHandler { tag, what, system -> + wtfCaptures.add("$tag,${what.message}") + } + val statsLogCapture = mutableListOf>() + val testStatsLog = object { + fun write(protoType: Int, errorType: Int) { + statsLogCapture.add(protoType to errorType) + } + } + tryTest { + TerribleErrorLog.logTerribleError(testStatsLog::write, "error", 1, 2) + assertContentEquals(listOf(1 to 2), statsLogCapture) + assertContentEquals(listOf("TerribleErrorLog,error"), wtfCaptures) + } cleanup { + Log.setWtfHandler(prevHandler) + } + } +}