1 /* 2 * Copyright (C) 2022 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.libraries.pcc.chronicle.util 18 19 import android.util.Log 20 import android.util.Log.DEBUG 21 import android.util.Log.ERROR 22 import android.util.Log.INFO 23 import android.util.Log.VERBOSE 24 import android.util.Log.WARN 25 26 /** Container for Chronicle's loggers. */ 27 object Logcat { 28 private const val DEFAULT_TAG: String = "Chronicle" 29 private const val CLIENT_TAG: String = "ChronicleClient" 30 private const val SERVER_TAG: String = "ChronicleServer" 31 32 /** 33 * [TaggedLogger] intended for use by implementations of the Chronicle interface and as a 34 * catch-all in situations where it doesn't make sense to implement a new logger. 35 */ 36 val default: TaggedLogger = TaggedLogger(DEFAULT_TAG) 37 38 /** [TaggedLogger] intended for use by client-side API components. */ 39 val clientSide: TaggedLogger = TaggedLogger(CLIENT_TAG) 40 41 /** [TaggedLogger] intended for use by server-side API components. */ 42 val serverSide: TaggedLogger = TaggedLogger(SERVER_TAG) 43 } 44 45 /** 46 * Helper class to associate a tag with logging calls. Each method simply calls the corresponding 47 * method in Android's native logger with the given tag. 48 */ 49 class TaggedLogger(val tag: String) { 50 51 /** 52 * Send a [VERBOSE] log message. 53 * @param msg The message you would like logged. 54 */ vnull55 fun v(msg: String, vararg args: Any) { 56 if (Log.isLoggable(tag, VERBOSE)) { 57 Log.v(tag, String.format(msg, *args)) 58 } 59 } 60 61 /** 62 * Send a [VERBOSE] log message and log the exception. 63 * @param tr An exception to log 64 * @param msg The message you would like logged. 65 */ vnull66 fun v(tr: Throwable, msg: String, vararg args: Any) { 67 if (Log.isLoggable(tag, VERBOSE)) { 68 Log.v(tag, String.format(msg, *args), tr) 69 } 70 } 71 72 /** 73 * Send a [DEBUG] log message. 74 * @param msg The message you would like logged. 75 */ dnull76 fun d(msg: String, vararg args: Any) { 77 if (Log.isLoggable(tag, DEBUG)) { 78 Log.d(tag, String.format(msg, *args)) 79 } 80 } 81 82 /** 83 * Send a [DEBUG] log message and log the exception. 84 * @param tr An exception to log 85 * @param msg The message you would like logged. 86 */ dnull87 fun d(tr: Throwable, msg: String, vararg args: Any) { 88 if (Log.isLoggable(tag, DEBUG)) { 89 Log.d(tag, String.format(msg, *args), tr) 90 } 91 } 92 93 /** 94 * Send an [INFO] log message. 95 * @param msg The message you would like logged. 96 */ inull97 fun i(msg: String, vararg args: Any) { 98 if (Log.isLoggable(tag, INFO)) { 99 Log.i(tag, String.format(msg, *args)) 100 } 101 } 102 103 /** 104 * Send a [INFO] log message and log the exception. 105 * @param tr An exception to log 106 * @param msg The message you would like logged. 107 */ inull108 fun i(tr: Throwable, msg: String, vararg args: Any) { 109 if (Log.isLoggable(tag, INFO)) { 110 Log.i(tag, String.format(msg, *args), tr) 111 } 112 } 113 114 /** 115 * Send a [WARN] log message. 116 * @param msg The message you would like logged. 117 */ wnull118 fun w(msg: String, vararg args: Any) { 119 if (Log.isLoggable(tag, WARN)) { 120 Log.w(tag, String.format(msg, *args)) 121 } 122 } 123 124 /** 125 * Send a [WARN] log message and log the exception. 126 * @param tr An exception to log 127 * @param msg The message you would like logged. 128 */ wnull129 fun w(tr: Throwable, msg: String, vararg args: Any) { 130 if (Log.isLoggable(tag, WARN)) { 131 Log.w(tag, String.format(msg, *args), tr) 132 } 133 } 134 135 /** 136 * Send a [WARN] log message and log the exception. 137 * @param tr An exception to log 138 */ wnull139 fun w(tr: Throwable) { 140 if (Log.isLoggable(tag, WARN)) { 141 Log.w(tag, tr) 142 } 143 } 144 145 /** 146 * Send an [ERROR] log message. 147 * @param msg The message you would like logged. 148 */ enull149 fun e(msg: String, vararg args: Any) { 150 if (Log.isLoggable(tag, ERROR)) { 151 Log.e(tag, String.format(msg, *args)) 152 } 153 } 154 155 /** 156 * Send a [ERROR] log message and log the exception. 157 * @param tr An exception to log 158 * @param msg The message you would like logged. 159 */ enull160 fun e(tr: Throwable, msg: String, vararg args: Any) { 161 if (Log.isLoggable(tag, ERROR)) { 162 Log.e(tag, String.format(msg, *args), tr) 163 } 164 } 165 166 /** 167 * Handy function to get a loggable stack trace from a Throwable 168 * @param tr An exception to log 169 */ getStackTraceStringnull170 fun getStackTraceString(tr: Throwable): String { 171 return Log.getStackTraceString(tr) 172 } 173 174 /** 175 * Low-level logging call. 176 * @param priority The priority/type of this log message 177 * @param msg The message you would like logged. 178 * @return The number of bytes written. 179 */ printlnnull180 fun println(priority: Int, msg: String, vararg args: Any) { 181 if (Log.isLoggable(tag, priority)) { 182 Log.println(priority, tag, String.format(msg, *args)) 183 } 184 } 185 186 /** 187 * Times the duration of the [block] and logs the provided [message] along with the duration at 188 * [VERBOSE] level. 189 */ timeVerbosenull190 inline fun <T> timeVerbose(message: String, block: () -> T): T { 191 val start = System.nanoTime() 192 return try { 193 block() 194 } finally { 195 val duration = System.nanoTime() - start 196 v("%s [duration: %.3f ms]", message, duration / 1000000.0) 197 } 198 } 199 } 200