Skip to content

Commit bf63add

Browse files
api: idiomatic kotlin changes to session api (#1673)
1 parent f95d9de commit bf63add

11 files changed

Lines changed: 84 additions & 72 deletions

File tree

android-agent/src/main/kotlin/io/opentelemetry/android/agent/session/InMemorySessionStorage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ package io.opentelemetry.android.agent.session
88
import io.opentelemetry.android.session.Session
99

1010
internal class InMemorySessionStorage(
11-
@Volatile var session: Session = Session.NONE,
11+
@Volatile var session: Session = invalidSession,
1212
) : SessionStorage {
1313
override fun get(): Session = session
1414

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.opentelemetry.android.agent.session
2+
3+
import io.opentelemetry.android.session.Session
4+
5+
internal class SessionImpl(
6+
override val id: String,
7+
override val startTimestamp: Long
8+
): Session
9+
10+
internal val invalidSession = SessionImpl("", -1)

android-agent/src/main/kotlin/io/opentelemetry/android/agent/session/SessionManager.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ internal class SessionManager(
2424
private val maxSessionLifetime: Duration,
2525
) : SessionProvider,
2626
SessionPublisher {
27-
private val session: AtomicReference<Session> = AtomicReference(Session.NONE)
27+
private val session: AtomicReference<Session> = AtomicReference(invalidSession)
2828
private val observers = synchronizedList(ArrayList<SessionObserver>())
2929

3030
init {
@@ -41,7 +41,7 @@ internal class SessionManager(
4141
// Check if we need to create a new session.
4242
return if (sessionHasExpired(currentSession) || timeoutHandler.hasTimedOut()) {
4343
val newId = idGenerator.generateSessionId()
44-
val newSession = Session.DefaultSession(newId, clock.now())
44+
val newSession = SessionImpl(newId, clock.now())
4545

4646
// Atomically update the session only if it hasn't been changed by another thread.
4747
if (session.compareAndSet(currentSession, newSession)) {
@@ -50,17 +50,17 @@ internal class SessionManager(
5050
// Observers need to be called after bumping the timer because it may create a new
5151
// span.
5252
notifyObserversOfSessionUpdate(currentSession, newSession)
53-
newSession.getId()
53+
newSession.id
5454
} else {
5555
// Another thread accessed this function prior to creating a new session. Use the
5656
// current session.
5757
timeoutHandler.bump()
58-
session.get().getId()
58+
session.get().id
5959
}
6060
} else {
6161
// No new session needed, just bump the timeout and return current session ID
6262
timeoutHandler.bump()
63-
currentSession.getId()
63+
currentSession.id
6464
}
6565
}
6666

@@ -75,7 +75,7 @@ internal class SessionManager(
7575
}
7676

7777
private fun sessionHasExpired(session: Session): Boolean {
78-
val elapsedTime = clock.now() - session.getStartTimestamp()
78+
val elapsedTime = clock.now() - session.startTimestamp
7979
return elapsedTime >= maxSessionLifetime.inWholeNanoseconds
8080
}
8181

@@ -93,4 +93,5 @@ internal class SessionManager(
9393
clock = clock,
9494
)
9595
}
96+
9697
}

android-agent/src/test/kotlin/io/opentelemetry/android/agent/session/SessionManagerTest.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ internal class SessionManagerTest {
120120
// Then
121121
verify(exactly = 1) { timeoutHandler.bump() }
122122
verify(exactly = 0) { timeoutHandler.hasTimedOut() }
123-
verify(exactly = 1) { observer.onSessionStarted(any<Session>(), eq(Session.NONE)) }
124-
verify(exactly = 1) { observer.onSessionEnded(eq(Session.NONE)) }
123+
verify(exactly = 1) { observer.onSessionStarted(any<Session>(), eq(invalidSession)) }
124+
verify(exactly = 1) { observer.onSessionEnded(eq(invalidSession)) }
125125

126126
// When
127127
clock.advance(3, TimeUnit.HOURS)
@@ -144,10 +144,10 @@ internal class SessionManagerTest {
144144
assertThat(thirdSessionId).isNotEqualTo(secondSessionId)
145145
verifyOrder {
146146
timeoutHandler.bump()
147-
observer.onSessionEnded(match { it.getId() == secondSessionId })
147+
observer.onSessionEnded(match { it.id == secondSessionId })
148148
observer.onSessionStarted(
149-
match { it.getId() == thirdSessionId },
150-
match { it.getId() == secondSessionId },
149+
match { it.id == thirdSessionId },
150+
match { it.id == secondSessionId },
151151
)
152152
}
153153
confirmVerified(observer)

instrumentation/sessions/src/main/kotlin/io/opentelemetry/android/instrumentation/sessions/SessionIdEventSender.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@ internal class SessionIdEventSender(
2828
eventLogger
2929
.logRecordBuilder()
3030
.setEventName(EVENT_SESSION_START)
31-
.setAttribute(SESSION_ID, newSession.getId())
32-
val previousSessionId = previousSession.getId()
31+
.setAttribute(SESSION_ID, newSession.id)
32+
val previousSessionId = previousSession.id
3333
if (previousSessionId.isNotEmpty()) {
3434
eventBuilder.setAttribute(SESSION_PREVIOUS_ID, previousSessionId)
3535
}
3636
eventBuilder.emit()
3737
}
3838

3939
override fun onSessionEnded(session: Session) {
40-
if (session.getId().isEmpty()) {
40+
if (session.id.isEmpty()) {
4141
return
4242
}
4343
eventLogger
4444
.logRecordBuilder()
4545
.setEventName(EVENT_SESSION_END)
46-
.setAttribute(SESSION_ID, session.getId())
46+
.setAttribute(SESSION_ID, session.id)
4747
.emit()
4848
}
4949
}

instrumentation/sessions/src/test/kotlin/io/opentelemetry/android/instrumentation/sessions/SessionIdEventSenderTest.kt

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,46 +39,51 @@ class SessionIdEventSenderTest {
3939
@Test
4040
fun `starts first session`() {
4141
val sender = SessionIdEventSender(logger)
42-
val newSession = Session.DefaultSession("123", 12L)
43-
val previousSession = Session.NONE
42+
val newSession = FakeSession("123", 12L)
43+
val previousSession = FakeSession("", -1)
4444
sender.onSessionStarted(newSession, previousSession)
4545
assertThat(otelTesting.logRecords).hasSize(1)
4646
val event = otelTesting.logRecords[0]
4747
assertThat(event.eventName).isEqualTo(EVENT_SESSION_START)
48-
assertThat(event.attributes.get(SESSION_ID)).isEqualTo(newSession.getId())
48+
assertThat(event.attributes.get(SESSION_ID)).isEqualTo(newSession.id)
4949
assertThat(event.attributes.get(SESSION_PREVIOUS_ID)).isNull()
5050
}
5151

5252
@Test
5353
fun `starts new second session`() {
5454
val sender = SessionIdEventSender(logger)
55-
val previousSession = Session.DefaultSession("abc", 12L)
56-
val newSession = Session.DefaultSession("124", 13L)
55+
val previousSession = FakeSession("abc", 12L)
56+
val newSession = FakeSession("124", 13L)
5757
sender.onSessionStarted(newSession, previousSession)
5858
assertThat(otelTesting.logRecords).hasSize(1)
5959
val event = otelTesting.logRecords[0]
6060
assertThat(event.eventName).isEqualTo(EVENT_SESSION_START)
61-
assertThat(event.attributes.get(SESSION_ID)).isEqualTo(newSession.getId())
62-
assertThat(event.attributes.get(SESSION_PREVIOUS_ID)).isEqualTo(previousSession.getId())
61+
assertThat(event.attributes.get(SESSION_ID)).isEqualTo(newSession.id)
62+
assertThat(event.attributes.get(SESSION_PREVIOUS_ID)).isEqualTo(previousSession.id)
6363
}
6464

6565
@Test
6666
fun `ends a session`() {
6767
val sender = SessionIdEventSender(logger)
68-
val session = Session.DefaultSession("booper", 99L)
68+
val session = FakeSession("booper", 99L)
6969
sender.onSessionEnded(session)
7070
assertThat(otelTesting.logRecords).hasSize(1)
7171
val event = otelTesting.logRecords[0]
7272
assertThat(event.eventName).isEqualTo(EVENT_SESSION_END)
73-
assertThat(event.attributes.get(SESSION_ID)).isEqualTo(session.getId())
73+
assertThat(event.attributes.get(SESSION_ID)).isEqualTo(session.id)
7474
assertThat(event.attributes.get(SESSION_PREVIOUS_ID)).isNull()
7575
}
7676

7777
@Test
7878
fun `ends an empty session`() {
7979
val sender = SessionIdEventSender(logger)
80-
val session = Session.NONE
80+
val session = FakeSession("", -1)
8181
sender.onSessionEnded(session)
8282
assertThat(otelTesting.logRecords).isEmpty()
8383
}
84+
85+
private class FakeSession(
86+
override val id: String,
87+
override val startTimestamp: Long,
88+
) : Session
8489
}

session/api/session.api

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,8 @@
11
public abstract interface class io/opentelemetry/android/session/Session {
2-
public static final field Companion Lio/opentelemetry/android/session/Session$Companion;
32
public abstract fun getId ()Ljava/lang/String;
43
public abstract fun getStartTimestamp ()J
54
}
65

7-
public final class io/opentelemetry/android/session/Session$Companion {
8-
public final fun getNONE ()Lio/opentelemetry/android/session/Session$DefaultSession;
9-
}
10-
11-
public final class io/opentelemetry/android/session/Session$DefaultSession : io/opentelemetry/android/session/Session {
12-
public fun <init> (Ljava/lang/String;J)V
13-
public final fun copy (Ljava/lang/String;J)Lio/opentelemetry/android/session/Session$DefaultSession;
14-
public static synthetic fun copy$default (Lio/opentelemetry/android/session/Session$DefaultSession;Ljava/lang/String;JILjava/lang/Object;)Lio/opentelemetry/android/session/Session$DefaultSession;
15-
public fun equals (Ljava/lang/Object;)Z
16-
public fun getId ()Ljava/lang/String;
17-
public fun getStartTimestamp ()J
18-
public fun hashCode ()I
19-
public fun toString ()Ljava/lang/String;
20-
}
21-
226
public abstract interface class io/opentelemetry/android/session/SessionObserver {
237
public abstract fun onSessionEnded (Lio/opentelemetry/android/session/Session;)V
248
public abstract fun onSessionStarted (Lio/opentelemetry/android/session/Session;Lio/opentelemetry/android/session/Session;)V

session/src/main/kotlin/io/opentelemetry/android/session/Session.kt

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,18 @@
55

66
package io.opentelemetry.android.session
77

8+
/**
9+
* Provides information about the current session.
10+
*/
811
interface Session {
9-
fun getId(): String
10-
11-
fun getStartTimestamp(): Long
12-
13-
companion object {
14-
val NONE = DefaultSession("", -1)
15-
}
16-
17-
data class DefaultSession(
18-
private val id: String,
19-
private val timestamp: Long,
20-
) : Session {
21-
override fun getId(): String = id
22-
23-
override fun getStartTimestamp(): Long = timestamp
24-
25-
override fun equals(other: Any?): Boolean {
26-
if (this === other) return true
27-
if (javaClass != other?.javaClass) return false
28-
29-
other as DefaultSession
3012

31-
return id == other.id
32-
}
13+
/**
14+
* The session ID.
15+
*/
16+
val id: String
3317

34-
override fun hashCode(): Int = id.hashCode()
35-
}
18+
/**
19+
* The timestamp at which the session was started.
20+
*/
21+
val startTimestamp: Long
3622
}

session/src/main/kotlin/io/opentelemetry/android/session/SessionObserver.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,21 @@
55

66
package io.opentelemetry.android.session
77

8+
/**
9+
* Callback that is invoked at different points in the session lifecycle.
10+
*/
811
interface SessionObserver {
12+
13+
/**
14+
* Called after a session has started.
15+
*/
916
fun onSessionStarted(
1017
newSession: Session,
1118
previousSession: Session,
1219
)
1320

21+
/**
22+
* Called after a session has ended.
23+
*/
1424
fun onSessionEnded(session: Session)
1525
}

session/src/main/kotlin/io/opentelemetry/android/session/SessionProvider.kt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,26 @@
55

66
package io.opentelemetry.android.session
77

8-
interface SessionProvider {
8+
/**
9+
* Provides information about the current session.
10+
*/
11+
fun interface SessionProvider {
12+
13+
/**
14+
* Retrieves the current session ID.
15+
*/
916
fun getSessionId(): String
1017

1118
companion object {
19+
20+
/**
21+
* A no-op implementation of [SessionProvider].
22+
*/
1223
@JvmStatic
1324
fun getNoop(): SessionProvider = NO_OP
1425

1526
private val NO_OP: SessionProvider by lazy {
16-
object : SessionProvider {
17-
override fun getSessionId(): String = ""
18-
}
27+
SessionProvider { "" }
1928
}
2029
}
2130
}

0 commit comments

Comments
 (0)