mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[stats-collector] introduced DeserializationResult to fail early
This commit is contained in:
+5
-3
@@ -34,7 +34,9 @@ open class SessionsInputSeparator(input: InputStream,
|
||||
var line: String? = inputReader.readLine()
|
||||
|
||||
while (line != null) {
|
||||
val event: LogEvent? = LogEventSerializer.fromString(line)
|
||||
val event: LogEvent? = LogEventSerializer.fromString(line)?.event
|
||||
//if there is any unknown or absent fields we should fail here
|
||||
|
||||
if (event == null) {
|
||||
handleNullEvent(line)
|
||||
continue
|
||||
@@ -46,7 +48,7 @@ open class SessionsInputSeparator(input: InputStream,
|
||||
currentSessionUid = event.sessionUid
|
||||
}
|
||||
|
||||
session.add(com.intellij.stats.events.completion.EventLine(event, line))
|
||||
session.add(EventLine(event, line))
|
||||
line = inputReader.readLine()
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ open class SessionsInputSeparator(input: InputStream,
|
||||
|
||||
val initial = session.first()
|
||||
if (initial.event is CompletionStartedEvent) {
|
||||
val state = com.intellij.stats.events.completion.CompletionValidationState(initial.event)
|
||||
val state = CompletionValidationState(initial.event)
|
||||
session.drop(1).forEach { state.accept(it.event) }
|
||||
isValidSession = state.isFinished && state.isValid
|
||||
}
|
||||
|
||||
+42
-10
@@ -16,16 +16,32 @@
|
||||
package com.intellij.stats.events.completion
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.internal.LinkedTreeMap
|
||||
|
||||
object JsonSerializer {
|
||||
private val gson = Gson()
|
||||
fun toJson(obj: Any) = gson.toJson(obj)
|
||||
fun <T> fromJson(json: String, clazz: Class<T>) = gson.fromJson(json, clazz)
|
||||
|
||||
fun toJson(obj: Any): String = gson.toJson(obj)
|
||||
|
||||
fun <T> fromJson(json: String, clazz: Class<T>): DeserializationResult<T> {
|
||||
val declaredFields = clazz.declaredFields.map { it.name }.toSet()
|
||||
val jsonFields = gson.fromJson(json, LinkedTreeMap::class.java).keys.map { it.toString() }.toSet()
|
||||
val value = gson.fromJson(json, clazz)
|
||||
|
||||
val unknownFields = jsonFields.subtract(declaredFields)
|
||||
val absentFields = declaredFields.subtract(jsonFields)
|
||||
|
||||
return DeserializationResult(value, unknownFields, absentFields)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DeserializationResult<out T>(val value: T, val unknownFields: Set<String>, val absentFields: Set<String>)
|
||||
|
||||
|
||||
object LogEventSerializer {
|
||||
|
||||
|
||||
private val actionClassMap: Map<Action, Class<out LogEvent>> = mapOf(
|
||||
Action.COMPLETION_STARTED to CompletionStartedEvent::class.java,
|
||||
Action.TYPE to TypeEvent::class.java,
|
||||
@@ -38,11 +54,13 @@ object LogEventSerializer {
|
||||
Action.CUSTOM to CustomMessageEvent::class.java
|
||||
)
|
||||
|
||||
|
||||
fun toString(event: LogEvent): String {
|
||||
return "${event.timestamp}\t${event.recorderId}\t${event.userUid}\t${event.sessionUid}\t${event.actionType}\t${JsonSerializer.toJson(event)}"
|
||||
}
|
||||
|
||||
fun fromString(line: String): LogEvent? {
|
||||
|
||||
fun fromString(line: String): DeserializedLogEvent? {
|
||||
val items = mutableListOf<String>()
|
||||
|
||||
var start = -1
|
||||
@@ -62,15 +80,29 @@ object LogEventSerializer {
|
||||
val clazz = actionClassMap[actionType] ?: return null
|
||||
|
||||
val json = line.substring(start + 1)
|
||||
val obj = JsonSerializer.fromJson(json, clazz)
|
||||
val result = JsonSerializer.fromJson(json, clazz)
|
||||
|
||||
obj.userUid = userUid
|
||||
obj.timestamp = timestamp
|
||||
obj.recorderId = recorderId
|
||||
obj.sessionUid = sessionUid
|
||||
obj.actionType = actionType
|
||||
val event = result.value
|
||||
|
||||
return obj
|
||||
event.userUid = userUid
|
||||
event.timestamp = timestamp
|
||||
event.recorderId = recorderId
|
||||
event.sessionUid = sessionUid
|
||||
event.actionType = actionType
|
||||
|
||||
return DeserializedLogEvent(event, result.unknownFields, result.absentFields)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class DeserializedLogEvent(
|
||||
val event: LogEvent,
|
||||
val unknownEventFields: Set<String>,
|
||||
val absentEventFields: Set<String>
|
||||
) {
|
||||
|
||||
val isOk: Boolean
|
||||
get() = unknownEventFields.isEmpty() || absentEventFields.isEmpty()
|
||||
|
||||
}
|
||||
+29
-2
@@ -1,6 +1,7 @@
|
||||
package com.intellij.stats.events.completion
|
||||
|
||||
import junit.framework.Assert.assertEquals
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
|
||||
@@ -23,8 +24,8 @@ class EventSerializeDeserializeTest {
|
||||
|
||||
private fun serializeDeserializeAndCheck(event: LogEvent) {
|
||||
val logLine = LogEventSerializer.toString(event)
|
||||
val eventFromString = LogEventSerializer.fromString(logLine)
|
||||
assertEquals(logLine, LogEventSerializer.toString(eventFromString!!))
|
||||
val eventFromString = LogEventSerializer.fromString(logLine)!!.event
|
||||
assertEquals(logLine, LogEventSerializer.toString(eventFromString))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -84,5 +85,31 @@ class EventSerializeDeserializeTest {
|
||||
val event = TypeEvent(Fixtures.userId, "xx", listOf(1,2,3), Fixtures.lookupList, 1)
|
||||
serializeDeserializeAndCheck(event)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `deserialization with info`() {
|
||||
val json = JsonSerializer.toJson(First())
|
||||
val obj: DeserializationResult<Second> = JsonSerializer.fromJson(json, Second::class.java)
|
||||
|
||||
assertThat(obj.absentFields).hasSize(2)
|
||||
assertThat(obj.absentFields).contains("absent_field0").contains("absent_field1")
|
||||
|
||||
assertThat(obj.unknownFields).hasSize(1)
|
||||
assertThat(obj.unknownFields).contains("unknown_field")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class First {
|
||||
val just_field: String = ""
|
||||
val unknown_field: Int = 0
|
||||
}
|
||||
|
||||
|
||||
class Second {
|
||||
val just_field: String = ""
|
||||
val absent_field0: Double = 1.0
|
||||
val absent_field1: Double = 1.0
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user