Skip to content

Commit 7416763

Browse files
committed
add public log listener methods
Adds the following new public methods: * OneSignal.Debug.addLogListener * OneSignal.Debug.removeLogListener These new methods provide a way to capture all SDK log entires at runtime, allowing the app developer to store these and/or send them to their server. The log listener is independent of logLevel, all message are always sent to listeners.
1 parent d1b274a commit 7416763

File tree

6 files changed

+175
-6
lines changed

6 files changed

+175
-6
lines changed

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/debug/IDebugManager.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,29 @@ package com.onesignal.debug
33
/**
44
* Access to debug the SDK in the event additional information is required to diagnose any
55
* SDK-related issues.
6-
*
7-
* WARNING: This should not be used in a production setting.
86
*/
97
interface IDebugManager {
108
/**
119
* The log level the OneSignal SDK should be writing to the Android log. Defaults to [LogLevel.WARN].
10+
* WARNING: This should not be set higher than LogLevel.WARN in a production setting.
1211
*/
1312
var logLevel: LogLevel
1413

1514
/**
1615
* The log level the OneSignal SDK should be showing as a modal. Defaults to [LogLevel.NONE].
16+
* WARNING: This should not be used in a production setting.
1717
*/
1818
var alertLevel: LogLevel
19+
20+
/**
21+
* Add a listener to receive all logging messages the SDK produces.
22+
* Useful to capture and send logs to your server.
23+
* NOTE: All log messages are always passed, logLevel has no effect on this.
24+
*/
25+
fun addLogListener(listener: ILogListener)
26+
27+
/**
28+
* Removes a listener added by addLogListener
29+
*/
30+
fun removeLogListener(listener: ILogListener)
1931
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.onesignal.debug
2+
3+
fun interface ILogListener {
4+
fun onLogEvent(event: OneSignalLogEvent)
5+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.onesignal.debug
2+
3+
data class OneSignalLogEvent(
4+
val level: LogLevel,
5+
val entry: String,
6+
)

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/debug/internal/DebugManager.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.onesignal.debug.internal
22

33
import com.onesignal.debug.IDebugManager
4+
import com.onesignal.debug.ILogListener
45
import com.onesignal.debug.LogLevel
56
import com.onesignal.debug.internal.logging.Logging
67

@@ -21,4 +22,12 @@ internal class DebugManager() : IDebugManager {
2122
logLevel = LogLevel.WARN
2223
alertLevel = LogLevel.NONE
2324
}
25+
26+
override fun addLogListener(listener: ILogListener) {
27+
Logging.addListener(listener)
28+
}
29+
30+
override fun removeLogListener(listener: ILogListener) {
31+
Logging.removeListener(listener)
32+
}
2433
}

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/debug/internal/logging/Logging.kt

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,28 @@ package com.onesignal.debug.internal.logging
33
import android.app.AlertDialog
44
import com.onesignal.common.threading.suspendifyOnMain
55
import com.onesignal.core.internal.application.IApplicationService
6+
import com.onesignal.debug.ILogListener
67
import com.onesignal.debug.LogLevel
8+
import com.onesignal.debug.OneSignalLogEvent
79
import java.io.PrintWriter
810
import java.io.StringWriter
11+
import java.util.concurrent.CopyOnWriteArraySet
912

1013
object Logging {
1114
private const val TAG = "OneSignal"
1215

1316
var applicationService: IApplicationService? = null
1417

18+
private val logListeners = CopyOnWriteArraySet<ILogListener>()
19+
1520
@JvmStatic
1621
var logLevel = LogLevel.WARN
1722

1823
@JvmStatic
1924
var visualLogLevel = LogLevel.NONE
2025

2126
@JvmStatic
22-
fun atLogLevel(level: LogLevel): Boolean {
23-
return level.compareTo(visualLogLevel) < 1 || level.compareTo(logLevel) < 1
24-
}
27+
fun atLogLevel(level: LogLevel): Boolean = level.compareTo(visualLogLevel) < 1 || level.compareTo(logLevel) < 1
2528

2629
@JvmStatic
2730
fun verbose(
@@ -112,7 +115,8 @@ object Logging {
112115
suspendifyOnMain {
113116
val currentActivity = applicationService?.current
114117
if (currentActivity != null) {
115-
AlertDialog.Builder(currentActivity)
118+
AlertDialog
119+
.Builder(currentActivity)
116120
.setTitle(level.toString())
117121
.setMessage(finalFullMessage)
118122
.show()
@@ -122,5 +126,31 @@ object Logging {
122126
android.util.Log.e(TAG, "Error showing logging message.", t)
123127
}
124128
}
129+
130+
callLogListeners(level, message, throwable)
131+
}
132+
133+
private fun callLogListeners(
134+
level: LogLevel,
135+
message: String,
136+
throwable: Throwable?,
137+
) {
138+
if (logListeners.isEmpty()) return
139+
140+
var logEntry = message
141+
if (throwable != null) {
142+
logEntry += "\n" + android.util.Log.getStackTraceString(throwable)
143+
}
144+
for (listener in logListeners) {
145+
listener.onLogEvent(OneSignalLogEvent(level, logEntry))
146+
}
147+
}
148+
149+
fun addListener(listener: ILogListener) {
150+
logListeners.add(listener)
151+
}
152+
153+
fun removeListener(listener: ILogListener) {
154+
logListeners.remove(listener)
125155
}
126156
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.onesignal.debug.internal
2+
3+
import com.onesignal.debug.ILogListener
4+
import com.onesignal.debug.LogLevel
5+
import com.onesignal.debug.OneSignalLogEvent
6+
import com.onesignal.debug.internal.logging.Logging
7+
import io.kotest.core.spec.style.FunSpec
8+
import io.kotest.matchers.shouldBe
9+
10+
class TestLogLister : ILogListener {
11+
val calls = ArrayList<String>()
12+
13+
override fun onLogEvent(event: OneSignalLogEvent) {
14+
calls += event.entry
15+
}
16+
}
17+
18+
class LoggingTests : FunSpec({
19+
beforeAny {
20+
Logging.logLevel = LogLevel.NONE
21+
}
22+
23+
test("addListener") {
24+
// Given
25+
val listener = TestLogLister()
26+
Logging.addListener(listener)
27+
28+
// When
29+
Logging.debug("test")
30+
31+
// Then
32+
listener.calls shouldBe arrayOf("test")
33+
}
34+
35+
test("addListener twice") {
36+
// Given
37+
val listener = TestLogLister()
38+
Logging.addListener(listener)
39+
Logging.addListener(listener)
40+
41+
// When
42+
Logging.debug("test")
43+
44+
// Then
45+
listener.calls shouldBe arrayOf("test")
46+
}
47+
48+
test("removeListener") {
49+
// Given
50+
val listener = TestLogLister()
51+
Logging.addListener(listener)
52+
Logging.removeListener(listener)
53+
54+
// When
55+
Logging.debug("test")
56+
57+
// Then
58+
listener.calls shouldBe arrayOf<String>()
59+
}
60+
61+
test("removeListener twice") {
62+
// Given
63+
val listener = TestLogLister()
64+
Logging.addListener(listener)
65+
Logging.removeListener(listener)
66+
Logging.removeListener(listener)
67+
68+
// When
69+
Logging.debug("test")
70+
71+
// Then
72+
listener.calls shouldBe arrayOf<String>()
73+
}
74+
75+
test("addListener nested") {
76+
// Given
77+
val nestedListener = TestLogLister()
78+
Logging.addListener { Logging.addListener(nestedListener) }
79+
80+
// When
81+
Logging.debug("test")
82+
Logging.debug("test2")
83+
Logging.debug("test3")
84+
85+
// Then
86+
nestedListener.calls shouldBe arrayOf("test2", "test3")
87+
}
88+
89+
test("removeListener nested") {
90+
// Given
91+
val calls = ArrayList<String>()
92+
var listener: ILogListener? = null
93+
listener =
94+
ILogListener {
95+
calls += it.entry
96+
Logging.removeListener(listener!!)
97+
}
98+
Logging.addListener(listener!!)
99+
100+
// When
101+
Logging.debug("test")
102+
Logging.debug("test2")
103+
104+
// Then
105+
calls shouldBe arrayOf("test")
106+
}
107+
})

0 commit comments

Comments
 (0)