1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.log
18 
19 import android.os.Build
20 import android.util.Log
21 import android.util.Log.LOG_ID_MAIN
22 
23 /**
24  * A simplified debug logger built as a wrapper around Android's [Log]. Internal for development.
25  *
26  * The main advantages are:
27  * - Sensible defaults, automatically retrieving the class name from the call-site (i.e., tag);
28  * - The messages are purged from source on release builds (keep in mind they are visible on AOSP);
29  * - Lazily evaluate Strings for zero impact in production builds or when disabled;
30  *
31  * Usage example:
32  * ```kotlin
33  * // Logging a message:
34  * debugLog { "message" }
35  *
36  * // Logging an error:
37  * debugLog(error = exception) { "message" }
38  *
39  * // Logging the current stack trace, for debugging:
40  * debugLog(error = Throwable()) { "message" }
41  * ```
42  */
43 object DebugLogger {
44 
45     /**
46      * Log a debug message, with sensible defaults.
47      *
48      * For example:
49      * ```kotlin
50      * val one = 1
51      * debugLog { "message#$one" }
52      * ```
53      *
54      * The output will be: `D/NoteTaskController: message#1`
55      *
56      * Beware, the [debugLog] content is **REMOVED FROM SOURCE AND BINARY** in Release builds.
57      *
58      * @param enabled: whether or not the message should be logged. By default, it is
59      *   [Build.IS_DEBUGGABLE].
60      * @param priority: type of this log. By default, it is [Log.DEBUG].
61      * @param tag: identifies the source of a log. By default, it is the receiver's simple name.
62      * @param error: a [Throwable] to log.
63      * @param message: a lazily evaluated message you wish to log.
64      */
65     inline fun Any.debugLog(
66         enabled: Boolean = Build.IS_DEBUGGABLE,
67         priority: Int = Log.DEBUG,
68         tag: String = this::class.simpleName.orEmpty(),
69         error: Throwable? = null,
70         message: () -> String,
71     ) {
72         if (enabled) {
73             if (error == null) {
74                 Log.println(priority, tag, message())
75             } else {
76                 Log.printlns(LOG_ID_MAIN, priority, tag, message(), error)
77             }
78         }
79     }
80 }
81