Skip to content

Commit

Permalink
feat: index user ip field and define required properties
Browse files Browse the repository at this point in the history
- Added `user_ip` as an indexed field.
- Added required fields: indexing will fail if any of the required fields is missing.
  • Loading branch information
jboix committed Nov 11, 2024
1 parent 8bc9aa9 commit ddb75ef
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import org.springframework.data.elasticsearch.annotations.FieldType
* @property sessionId The ID of the session associated with the event.
* @property eventName The name of the event.
* @property timestamp The timestamp of the event in epoch milliseconds.
* @property ip The ip address of the client that generated the event.
* @property data Additional data associated with the event.
* @property session Session data associated with the event, potentially updated later.
*/
Expand All @@ -31,18 +32,24 @@ data class EventRequest(
@Id
@JsonIgnore
var id: String? = null,
@JsonProperty("session_id")
@JsonProperty("session_id", required = true)
@Field("session_id")
var sessionId: String,
@JsonProperty("event_name")
@JsonProperty("event_name", required = true)
@Field("event_name")
var eventName: String,
@Field(type = FieldType.Date, format = [DateFormat.epoch_millis], name = "@timestamp")
@JsonProperty(required = true)
var timestamp: Long,
@JsonProperty("user_ip")
@Field("user_ip")
var ip: String?,
@JsonProperty(required = true)
var version: Long,
@JsonDeserialize(using = DataDeserializer::class)
var data: Any? = null,
var session: Any? = null,
@JsonProperty(required = true)
var data: Any,
var session: Any?,
)

/**
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
spring:
threads.virtual.enabled: true
application.name: pillarbox-monitoring-transfer
jackson.deserialization:
fail-on-null-for-primitives: true


pillarbox.monitoring:
dispatch.uri: "http://localhost:8080/events"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package ch.srgssr.pillarbox.monitoring.event.model

import com.fasterxml.jackson.databind.JsonMappingException
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.ShouldSpec
import io.kotest.matchers.shouldBe
import org.springframework.boot.test.context.SpringBootTest
Expand All @@ -10,6 +12,68 @@ import org.springframework.boot.test.context.SpringBootTest
class EventRequestTest(
private val objectMapper: ObjectMapper,
) : ShouldSpec({
should("deserialize successfully if all required fields are present") {
// Given: an event as json
val jsonInput =
"""
{
"session_id": "12345",
"event_name": "START",
"timestamp": 1630000000000,
"user_ip": "127.0.0.1",
"version": 1,
"data": { }
}
}
""".trimIndent()

// When: the event is deserialized
val eventRequest = objectMapper.readValue<EventRequest>(jsonInput)

// Then: The data of the event should be correctly parsed.
eventRequest.sessionId shouldBe "12345"
eventRequest.eventName shouldBe "START"
eventRequest.timestamp shouldBe 1630000000000
eventRequest.ip shouldBe "127.0.0.1"
eventRequest.version shouldBe 1
}

context("fail to deserialize if missing any required field") {
val baseJson =
mapOf(
"session_id" to "\"12345\"",
"event_name" to "\"START\"",
"timestamp" to "1630000000000",
"version" to "1",
"data" to "{}",
)

baseJson.keys.forEach { missingField ->
should("should fail if $missingField is missing") {
val jsonInput =
baseJson
.filterKeys { it != missingField } // Exclude the current field
.map { (key, value) -> "\"$key\": $value" }
.joinToString(prefix = "{", postfix = "}")

shouldThrow<JsonMappingException> {
objectMapper.readValue<EventRequest>(jsonInput)
}
}
should("should fail if $missingField is null") {
val jsonInput =
baseJson
.map { (key, value) ->
"\"$key\": ${if (key == missingField) "null" else value}"
}.joinToString(prefix = "{", postfix = "}")

shouldThrow<JsonMappingException> {
objectMapper.readValue<EventRequest>(jsonInput)
}
}
}
}

should("deserialize an event and resolve user agent") {
// Given: an input with a user agent
val jsonInput =
Expand All @@ -18,6 +82,7 @@ class EventRequestTest(
"session_id": "12345",
"event_name": "START",
"timestamp": 1630000000000,
"user_ip": "127.0.0.1",
"version": 1,
"data": {
"browser": {
Expand Down Expand Up @@ -55,6 +120,7 @@ class EventRequestTest(
"session_id": "12345",
"event_name": "START",
"timestamp": 1630000000000,
"user_ip": "127.0.0.1",
"version": 1,
"data": {
"browser": {
Expand Down Expand Up @@ -92,6 +158,7 @@ class EventRequestTest(
"session_id": "12345",
"event_name": "START",
"timestamp": 1630000000000,
"user_ip": "127.0.0.1",
"version": 1,
"data": {
"browser": {
Expand Down

0 comments on commit ddb75ef

Please sign in to comment.