@@ -11,48 +11,225 @@ import timber.log.Timber
11
11
/* *
12
12
* Sentry Timber tree which is responsible to capture events via Timber
13
13
*/
14
+ @Suppress(" TooManyFunctions" ) // we have to override all methods to be able to tweak logging
14
15
class SentryTimberTree (
15
16
private val hub : IHub ,
16
17
private val minEventLevel : SentryLevel ,
17
18
private val minBreadcrumbLevel : SentryLevel
18
19
) : Timber.Tree() {
19
20
20
- /* *
21
- * do not log if it's lower than min. required level.
22
- */
23
- private fun isLoggable (level : SentryLevel , minLevel : SentryLevel ): Boolean = level.ordinal >= minLevel.ordinal
21
+ /* * Log a verbose message with optional format args. */
22
+ override fun v (
23
+ message : String? ,
24
+ vararg args : Any?
25
+ ) {
26
+ logWithSentry(Log .VERBOSE , null , message, * args)
27
+ }
28
+
29
+ /* * Log a verbose exception and a message with optional format args. */
30
+ override fun v (
31
+ t : Throwable ? ,
32
+ message : String? ,
33
+ vararg args : Any?
34
+ ) {
35
+ logWithSentry(Log .VERBOSE , t, message, * args)
36
+ }
37
+
38
+ /* * Log a verbose exception. */
39
+ override fun v (t : Throwable ? ) {
40
+ logWithSentry(Log .VERBOSE , t, null )
41
+ }
42
+
43
+ /* * Log a debug message with optional format args. */
44
+ override fun d (
45
+ message : String? ,
46
+ vararg args : Any?
47
+ ) {
48
+ logWithSentry(Log .DEBUG , null , message, * args)
49
+ }
50
+
51
+ /* * Log a debug exception and a message with optional format args. */
52
+ override fun d (
53
+ t : Throwable ? ,
54
+ message : String? ,
55
+ vararg args : Any?
56
+ ) {
57
+ logWithSentry(Log .DEBUG , t, message, * args)
58
+ }
59
+
60
+ /* * Log a debug exception. */
61
+ override fun d (t : Throwable ? ) {
62
+ logWithSentry(Log .DEBUG , t, null )
63
+ }
64
+
65
+ /* * Log an info message with optional format args. */
66
+ override fun i (
67
+ message : String? ,
68
+ vararg args : Any?
69
+ ) {
70
+ logWithSentry(Log .INFO , null , message, * args)
71
+ }
72
+
73
+ /* * Log an info exception and a message with optional format args. */
74
+ override fun i (
75
+ t : Throwable ? ,
76
+ message : String? ,
77
+ vararg args : Any?
78
+ ) {
79
+ logWithSentry(Log .INFO , t, message, * args)
80
+ }
81
+
82
+ /* * Log an info exception. */
83
+ override fun i (t : Throwable ? ) {
84
+ logWithSentry(Log .INFO , t, null )
85
+ }
86
+
87
+ /* * Log a warning message with optional format args. */
88
+ override fun w (
89
+ message : String? ,
90
+ vararg args : Any?
91
+ ) {
92
+ logWithSentry(Log .WARN , null , message, * args)
93
+ }
94
+
95
+ /* * Log a warning exception and a message with optional format args. */
96
+ override fun w (
97
+ t : Throwable ? ,
98
+ message : String? ,
99
+ vararg args : Any?
100
+ ) {
101
+ logWithSentry(Log .WARN , t, message, * args)
102
+ }
103
+
104
+ /* * Log a warning exception. */
105
+ override fun w (t : Throwable ? ) {
106
+ logWithSentry(Log .WARN , t, null )
107
+ }
108
+
109
+ /* * Log an error message with optional format args. */
110
+ override fun e (
111
+ message : String? ,
112
+ vararg args : Any?
113
+ ) {
114
+ logWithSentry(Log .ERROR , null , message, * args)
115
+ }
116
+
117
+ /* * Log an error exception and a message with optional format args. */
118
+ override fun e (
119
+ t : Throwable ? ,
120
+ message : String? ,
121
+ vararg args : Any?
122
+ ) {
123
+ logWithSentry(Log .ERROR , t, message, * args)
124
+ }
125
+
126
+ /* * Log an error exception. */
127
+ override fun e (t : Throwable ? ) {
128
+ logWithSentry(Log .ERROR , t, null )
129
+ }
130
+
131
+ /* * Log an assert message with optional format args. */
132
+ override fun wtf (
133
+ message : String? ,
134
+ vararg args : Any?
135
+ ) {
136
+ logWithSentry(Log .ASSERT , null , message, * args)
137
+ }
138
+
139
+ /* * Log an assert exception and a message with optional format args. */
140
+ override fun wtf (
141
+ t : Throwable ? ,
142
+ message : String? ,
143
+ vararg args : Any?
144
+ ) {
145
+ logWithSentry(Log .ASSERT , t, message, * args)
146
+ }
147
+
148
+ /* * Log an assert exception. */
149
+ override fun wtf (t : Throwable ? ) {
150
+ logWithSentry(Log .ASSERT , t, null )
151
+ }
152
+
153
+ /* * Log at `priority` a message with optional format args. */
154
+ override fun log (
155
+ priority : Int ,
156
+ message : String? ,
157
+ vararg args : Any?
158
+ ) {
159
+ logWithSentry(priority, null , message, * args)
160
+ }
161
+
162
+ /* * Log at `priority` an exception and a message with optional format args. */
163
+ override fun log (
164
+ priority : Int ,
165
+ t : Throwable ? ,
166
+ message : String? ,
167
+ vararg args : Any?
168
+ ) {
169
+ logWithSentry(priority, t, message, * args)
170
+ }
171
+
172
+ /* * Log at `priority` an exception. */
173
+ override fun log (
174
+ priority : Int ,
175
+ t : Throwable ?
176
+ ) {
177
+ logWithSentry(priority, t, null )
178
+ }
179
+
180
+ override fun log (
181
+ priority : Int ,
182
+ tag : String? ,
183
+ message : String ,
184
+ t : Throwable ?
185
+ ) {
186
+ // no-op as we've overridden all the methods
187
+ }
188
+
189
+ private fun logWithSentry (
190
+ priority : Int ,
191
+ throwable : Throwable ? ,
192
+ message : String? ,
193
+ vararg args : Any?
194
+ ) {
195
+ if (message.isNullOrEmpty() && throwable == null ) {
196
+ return // Swallow message if it's null and there's no throwable
197
+ }
24
198
25
- /* *
26
- * Captures a Sentry Event if the min. level is equal or higher than the min. required level.
27
- */
28
- override fun log (priority : Int , tag : String? , message : String , throwable : Throwable ? ) {
29
199
val level = getSentryLevel(priority)
200
+ val sentryMessage = Message ().apply {
201
+ this .message = message
202
+ if (! message.isNullOrEmpty() && args.isNotEmpty()) {
203
+ this .formatted = message?.format(* args)
204
+ }
205
+ this .params = args.map { it.toString() }
206
+ }
30
207
31
- captureEvent(level, tag, message , throwable)
32
- addBreadcrumb(level, message )
208
+ captureEvent(level, sentryMessage , throwable)
209
+ addBreadcrumb(level, sentryMessage, throwable )
33
210
}
34
211
212
+ /* *
213
+ * do not log if it's lower than min. required level.
214
+ */
215
+ private fun isLoggable (
216
+ level : SentryLevel ,
217
+ minLevel : SentryLevel
218
+ ): Boolean = level.ordinal >= minLevel.ordinal
219
+
35
220
/* *
36
221
* Captures an event with the given attributes
37
222
*/
38
- private fun captureEvent (sentryLevel : SentryLevel , tag : String? , msg : String , throwable : Throwable ? ) {
223
+ private fun captureEvent (
224
+ sentryLevel : SentryLevel ,
225
+ msg : Message ,
226
+ throwable : Throwable ?
227
+ ) {
39
228
if (isLoggable(sentryLevel, minEventLevel)) {
40
229
val sentryEvent = SentryEvent ().apply {
41
-
42
230
level = sentryLevel
43
-
44
- throwable?.let {
45
- setThrowable(it)
46
- }
47
-
48
- message = Message ().apply {
49
- formatted = msg
50
- }
51
-
52
- tag?.let {
53
- setTag(" TimberTag" , it)
54
- }
55
-
231
+ throwable?.let { setThrowable(it) }
232
+ message = msg
56
233
logger = " Timber"
57
234
}
58
235
@@ -63,16 +240,27 @@ class SentryTimberTree(
63
240
/* *
64
241
* Adds a breadcrumb
65
242
*/
66
- private fun addBreadcrumb (sentryLevel : SentryLevel , msg : String ) {
243
+ private fun addBreadcrumb (
244
+ sentryLevel : SentryLevel ,
245
+ msg : Message ,
246
+ throwable : Throwable ?
247
+ ) {
67
248
// checks the breadcrumb level
68
249
if (isLoggable(sentryLevel, minBreadcrumbLevel)) {
69
- val breadCrumb = Breadcrumb ().apply {
70
- level = sentryLevel
71
- category = " Timber"
72
- message = msg
250
+ val throwableMsg = throwable?.message
251
+ val breadCrumb = when {
252
+ msg.message != null -> Breadcrumb ().apply {
253
+ level = sentryLevel
254
+ category = " Timber"
255
+ message = msg.message
256
+ }
257
+ throwableMsg != null -> Breadcrumb .error(throwableMsg).apply {
258
+ category = " exception"
259
+ }
260
+ else -> null
73
261
}
74
262
75
- hub.addBreadcrumb(breadCrumb)
263
+ breadCrumb?. let { hub.addBreadcrumb(it) }
76
264
}
77
265
}
78
266
0 commit comments