Skip to content

Commit 8acde15

Browse files
authored
Add JSON encoder for SessionEvents (#4778)
1 parent 2cdfd4e commit 8acde15

File tree

6 files changed

+186
-21
lines changed

6 files changed

+186
-21
lines changed

firebase-sessions/firebase-sessions.gradle.kts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,16 @@ android {
4242
}
4343

4444
dependencies {
45-
implementation(project(":firebase-common"))
46-
implementation(project(":firebase-common:ktx"))
47-
implementation(project(":firebase-components"))
45+
implementation("com.google.firebase:firebase-encoders:17.0.0")
46+
implementation(project(":encoders:firebase-encoders-json"))
47+
implementation("com.google.firebase:firebase-common-ktx:20.3.1")
48+
implementation("com.google.firebase:firebase-components:17.1.0")
4849
implementation(libs.androidx.annotation)
4950

51+
testImplementation(libs.androidx.test.junit)
52+
testImplementation(libs.androidx.test.runner)
5053
testImplementation(libs.junit)
54+
testImplementation(libs.robolectric)
5155
testImplementation(libs.truth)
5256

5357
androidTestImplementation(libs.androidx.test.junit)

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/FirebaseSessions.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class FirebaseSessions internal constructor(firebaseApp: FirebaseApp) {
4040
fun greeting(): String = "Matt says hi!"
4141

4242
private fun initiateSessionStart() {
43-
val sessionState = sessionGenerator.generateNewSession()
44-
val sessionEvent = SessionEvent.sessionStart(sessionState)
43+
val sessionDetails = sessionGenerator.generateNewSession()
44+
val sessionEvent = SessionEvents.startSession(sessionDetails)
4545

4646
Log.i(TAG, "Initiate session start: $sessionEvent")
4747
}

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SessionEvent.kt

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package com.google.firebase.sessions
1818

19+
import com.google.firebase.encoders.json.NumberedEnum
20+
1921
/**
2022
* Contains the relevant information around a Firebase Session Event.
2123
*
@@ -29,23 +31,10 @@ internal data class SessionEvent(
2931

3032
/** Information about the session triggering the event. */
3133
val sessionData: SessionInfo,
32-
) {
33-
companion object {
34-
fun sessionStart(sessionDetails: SessionDetails) =
35-
SessionEvent(
36-
eventType = EventType.SESSION_START,
37-
sessionData =
38-
SessionInfo(
39-
sessionDetails.sessionId,
40-
sessionDetails.firstSessionId,
41-
sessionDetails.sessionIndex,
42-
),
43-
)
44-
}
45-
}
34+
)
4635

4736
/** Enum denoting all possible session event types. */
48-
internal enum class EventType(val number: Int) {
37+
internal enum class EventType(override val number: Int) : NumberedEnum {
4938
EVENT_TYPE_UNKNOWN(0),
5039

5140
/** This event type is fired as soon as a new session begins. */
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.sessions
18+
19+
import com.google.firebase.encoders.DataEncoder
20+
import com.google.firebase.encoders.FieldDescriptor
21+
import com.google.firebase.encoders.ObjectEncoderContext
22+
import com.google.firebase.encoders.json.JsonDataEncoderBuilder
23+
24+
/**
25+
* Contains functions for [SessionEvent]s.
26+
*
27+
* @hide
28+
*/
29+
internal object SessionEvents {
30+
/** JSON [DataEncoder] for [SessionEvent]s. */
31+
// TODO(mrober): Replace with firebase-encoders-processor when it can encode Kotlin data classes.
32+
internal val SESSION_EVENT_ENCODER: DataEncoder =
33+
JsonDataEncoderBuilder()
34+
.configureWith {
35+
it.registerEncoder(SessionEvent::class.java) {
36+
sessionEvent: SessionEvent,
37+
ctx: ObjectEncoderContext ->
38+
run {
39+
ctx.add(FieldDescriptor.of("event_type"), sessionEvent.eventType)
40+
ctx.add(FieldDescriptor.of("session_data"), sessionEvent.sessionData)
41+
}
42+
}
43+
44+
it.registerEncoder(SessionInfo::class.java) {
45+
sessionInfo: SessionInfo,
46+
ctx: ObjectEncoderContext ->
47+
run {
48+
ctx.add(FieldDescriptor.of("session_id"), sessionInfo.sessionId)
49+
ctx.add(FieldDescriptor.of("first_session_id"), sessionInfo.firstSessionId)
50+
ctx.add(FieldDescriptor.of("session_index"), sessionInfo.sessionIndex)
51+
}
52+
}
53+
}
54+
.build()
55+
56+
/** Construct a Session Start event */
57+
fun startSession(sessionDetails: SessionDetails) =
58+
SessionEvent(
59+
eventType = EventType.SESSION_START,
60+
sessionData =
61+
SessionInfo(
62+
sessionDetails.sessionId,
63+
sessionDetails.firstSessionId,
64+
sessionDetails.sessionIndex,
65+
),
66+
)
67+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.sessions
18+
19+
import androidx.test.ext.junit.runners.AndroidJUnit4
20+
import com.google.common.truth.Truth.assertThat
21+
import com.google.firebase.sessions.SessionEvents.SESSION_EVENT_ENCODER
22+
import org.junit.Test
23+
import org.junit.runner.RunWith
24+
25+
@RunWith(AndroidJUnit4::class)
26+
class SessionEventEncoderTest {
27+
@Test
28+
fun sessionEvent_encodesToJson() {
29+
val sessionEvent =
30+
SessionEvent(
31+
eventType = EventType.SESSION_START,
32+
sessionData =
33+
SessionInfo(
34+
sessionId = "id",
35+
firstSessionId = "first",
36+
sessionIndex = 9,
37+
),
38+
)
39+
40+
val json = SESSION_EVENT_ENCODER.encode(sessionEvent)
41+
42+
assertThat(json)
43+
.isEqualTo(
44+
"""
45+
{
46+
"event_type":1,
47+
"session_data":{
48+
"session_id":"id",
49+
"first_session_id":"first",
50+
"session_index":9
51+
}
52+
}
53+
"""
54+
.lines()
55+
.joinToString("") { it.trim() }
56+
)
57+
}
58+
59+
@Test
60+
fun sessionEvent_emptyValues_encodesToJson() {
61+
val sessionEvent =
62+
SessionEvent(
63+
eventType = EventType.EVENT_TYPE_UNKNOWN,
64+
sessionData =
65+
SessionInfo(
66+
sessionId = "",
67+
firstSessionId = "",
68+
sessionIndex = 0,
69+
),
70+
)
71+
72+
val json = SESSION_EVENT_ENCODER.encode(sessionEvent)
73+
74+
assertThat(json)
75+
.isEqualTo(
76+
"""
77+
{
78+
"event_type":0,
79+
"session_data":{
80+
"session_id":"",
81+
"first_session_id":"",
82+
"session_index":0
83+
}
84+
}
85+
"""
86+
.lines()
87+
.joinToString("") { it.trim() }
88+
)
89+
}
90+
91+
@Test
92+
fun eventType_numberedEnum_encodesToJson() {
93+
val json =
94+
SESSION_EVENT_ENCODER.encode(
95+
arrayOf(
96+
EventType.SESSION_START,
97+
EventType.EVENT_TYPE_UNKNOWN,
98+
EventType.SESSION_START,
99+
EventType.SESSION_START
100+
)
101+
)
102+
103+
assertThat(json).isEqualTo("[1,0,1,1]")
104+
}
105+
}

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/SessionEventTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class SessionEventTest {
3030
sessionIndex = 3,
3131
)
3232

33-
val sessionEvent = SessionEvent.sessionStart(sessionDetails)
33+
val sessionEvent = SessionEvents.startSession(sessionDetails)
3434

3535
assertThat(sessionEvent)
3636
.isEqualTo(

0 commit comments

Comments
 (0)