Skip to content

Commit 073bebb

Browse files
committed
Added some cleanup for IPs and memory addresses in telemetry errors
1 parent 03ef036 commit 073bebb

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

core/src/main/java/com/segment/analytics/kotlin/core/Telemetry.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,22 @@ object Telemetry: Subscriber {
170170
addRemoteMetric(metric, tags)
171171
}
172172

173+
fun cleanErrorValue(value: String): String {
174+
var cleanedValue = value
175+
// Remove IPs
176+
cleanedValue = cleanedValue.replace(Regex("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}[\\d._:port]*"), "_IP")
177+
// Remove IPv6
178+
cleanedValue = cleanedValue.replace(Regex("[0-9a-fA-F]{2,4}(:[0-9a-fA-F]{0,4}){2,8}[\\d._:port]*"), "_IP")
179+
// Remove hex values
180+
cleanedValue = cleanedValue.replace(Regex("0x[0-9a-fA-F]+"), "0x00")
181+
// Remove hex values that don't have 0x of at least 6 characters
182+
cleanedValue = cleanedValue.replace(Regex("[0-9a-fA-F]{6,}"), "0x00")
183+
// What even? Mangled library names probably, e.g. a5.b:_some_error_etc
184+
cleanedValue = cleanedValue.replace(Regex("^[a-z][a-z0-9]\\.[a-z]:"), "")
185+
186+
return cleanedValue
187+
}
188+
173189
/**
174190
* Logs an error metric with the specified tags and log data.
175191
*
@@ -186,6 +202,10 @@ object Telemetry: Subscriber {
186202
if (tags.isEmpty()) return
187203
if (Math.random() > sampleRate) return
188204

205+
if (tags.containsKey("error")) {
206+
tags["error"] = cleanErrorValue(tags["error"]!!)
207+
}
208+
189209
var filteredTags = if(sendWriteKeyOnError) {
190210
tags.toMap()
191211
} else {

core/src/test/kotlin/com/segment/analytics/kotlin/core/TelemetryTest.kt

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,79 @@ class TelemetryTest {
239239
}
240240
assertTrue(TelemetryQueueSize() == Telemetry.maxQueueSize)
241241
}
242-
}
242+
243+
@Test
244+
fun `Test error tags are cleaned`() {
245+
Telemetry.enable = true
246+
Telemetry.start()
247+
Telemetry.error(Telemetry.INVOKE_ERROR_METRIC, "error log") {
248+
it["error"] = "foo_192.168.0.1:8080"
249+
}
250+
assertEquals(1, TelemetryQueueSize())
251+
val queueField: Field = Telemetry::class.java.getDeclaredField("queue")
252+
queueField.isAccessible = true
253+
val queueValue: ConcurrentLinkedQueue<*> = queueField.get(Telemetry) as ConcurrentLinkedQueue<*>
254+
val metric = queueValue.peek() as RemoteMetric
255+
assertEquals("foo__IP", metric.tags["error"])
256+
}
257+
258+
@Test
259+
fun `Test error tags are cleaned for IPv6`() {
260+
Telemetry.enable = true
261+
Telemetry.start()
262+
Telemetry.error(Telemetry.INVOKE_ERROR_METRIC, "error log") {
263+
it["error"] = "foo_2001:0db8:85a3:0000:0000:8a2e:0370:7334"
264+
}
265+
assertEquals(1, TelemetryQueueSize())
266+
val queueField: Field = Telemetry::class.java.getDeclaredField("queue")
267+
queueField.isAccessible = true
268+
val queueValue: ConcurrentLinkedQueue<*> = queueField.get(Telemetry) as ConcurrentLinkedQueue<*>
269+
val metric = queueValue.peek() as RemoteMetric
270+
assertEquals("foo__IP", metric.tags["error"])
271+
}
272+
273+
@Test
274+
fun `Test error tags are cleaned for hex values`() {
275+
Telemetry.enable = true
276+
Telemetry.start()
277+
Telemetry.error(Telemetry.INVOKE_ERROR_METRIC, "error log") {
278+
it["error"] = "foo_0x1234567890abcdef_bar"
279+
}
280+
assertEquals(1, TelemetryQueueSize())
281+
val queueField: Field = Telemetry::class.java.getDeclaredField("queue")
282+
queueField.isAccessible = true
283+
val queueValue: ConcurrentLinkedQueue<*> = queueField.get(Telemetry) as ConcurrentLinkedQueue<*>
284+
val metric = queueValue.peek() as RemoteMetric
285+
assertEquals("foo_0x00_bar", metric.tags["error"])
286+
}
287+
288+
@Test
289+
fun `Test error tags are cleaned for sneaky hex values`() {
290+
Telemetry.enable = true
291+
Telemetry.start()
292+
Telemetry.error(Telemetry.INVOKE_ERROR_METRIC, "error log") {
293+
it["error"] = "address_deadbeef_face"
294+
}
295+
assertEquals(1, TelemetryQueueSize())
296+
val queueField: Field = Telemetry::class.java.getDeclaredField("queue")
297+
queueField.isAccessible = true
298+
val queueValue: ConcurrentLinkedQueue<*> = queueField.get(Telemetry) as ConcurrentLinkedQueue<*>
299+
val metric = queueValue.peek() as RemoteMetric
300+
assertEquals("address_0x00_face", metric.tags["error"])
301+
}
302+
303+
@Test
304+
fun `Test error tags are cleaned for mangled library names`() {
305+
Telemetry.enable = true
306+
Telemetry.start()
307+
Telemetry.error(Telemetry.INVOKE_ERROR_METRIC, "error log") {
308+
it["error"] = "a5.b:_some_error_etc"
309+
}
310+
assertEquals(1, TelemetryQueueSize())
311+
val queueField: Field = Telemetry::class.java.getDeclaredField("queue")
312+
queueField.isAccessible = true
313+
val queueValue: ConcurrentLinkedQueue<*> = queueField.get(Telemetry) as ConcurrentLinkedQueue<*>
314+
val metric = queueValue.peek() as RemoteMetric
315+
assertEquals("_some_error_etc", metric.tags["error"])
316+
}
317+
}

0 commit comments

Comments
 (0)