LoginSignup
1
0

More than 3 years have passed since last update.

Extend "Any" object for convenient log method e.g. this.log()

Posted at

It is convenient to use a logging function that automatically prints the object from which the log call was made. Here, we extend the native Any object (from which all objects in Kotlin derive).

e.g. Call the following function from someObject:

this.log(someString, someOtherObject)

will show the following in LogCat:

applicatioName => someObject => someString, someOtherObject
// we extract the name of this object (derived from Any) from its simpleName member, 
// or its fullName if simpleName is empty (or is equal to the object's Companion 
// name because we called in a static method)
val Any.logClassTag: String
    get() {
        val simpleName = this::class.java.getSimpleName()
        if(
                simpleName.isEmpty() ||
                simpleName.equals("Companion")
        ) {
            val fullName = this::class.java.getName()
            return fullName.split(".").lastOrNull() ?: fullName
        }
        return simpleName
    }


// This general purpose method takes a variable number of arguments, and adds the 
// name of the calling object. Note that it requires spread operator (*) to pass 
// the contents of the vararg  "values", not values itself
fun Any.log(vararg values: Any?) {
    globalLog(this.logClassTag, *values)
}


// define an identifying tag that can be used to filter LogCat for the current app
// e.g. use the current flavor name if it is defined
private val identifier
    get() = BuildConfig.FLAVOR


// we define a general log function that formats the variable number of arguments 
// together with the calling object tag and an application identifier
fun globalLog(tag: String, vararg values: Any?) {
    val identifierAndTag = identifier + " => " + tag + " => "

    when(values.size) {
        0 -> return
        else -> {
            Log.d(
                    identifierAndTag ,
                    values.mapNotNull {
                        if (it is String) {
                            when(it.isEmpty()) {
                                true -> "<EMPTY>"
                                false -> it
                            }
                        }
                        else
                            it.toString()
                    }.joinToString(" "))
        }
    }
}

// we can further extend Any with methods that include predefined tags, which 
// can be filtered in LogCat to show only "ERROR" or "EXCEPTION"
fun Any.error(vararg values: Any?) {
    globalLog(this.logClassTag + " " + "ERROR", *values)
}

fun Any.exception(e: Exception, vararg values: Any?) {
    globalLog(this.logClassTag + " " + "EXCEPTION", e.message, *values)
    e.printStackTrace()
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0