Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add an accessor for the current session ID #1616

Merged
merged 4 commits into from
Jan 9, 2024

Conversation

fuzzybinary
Copy link
Member

What and why?

This adds a currentSessionID accessor onto the RUM Monitor. There are cases (usually support cases) where users want to be able to access the current session ID more easily than with the currently available "sessionStarted" notifications.

refs: RUM-1961

Review checklist

  • Feature or bugfix MUST have appropriate tests (unit, integration)
  • Make sure each commit and the PR mention the Issue number or JIRA reference
  • Add CHANGELOG entry for user facing changes

Custom CI job configuration (optional)

  • Run unit tests for Core, RUM, Trace, Logs, CR and WVT
  • Run unit tests for Session Replay
  • Run integration tests
  • Run smoke tests
  • Run tests for tools/

@fuzzybinary fuzzybinary requested review from a team as code owners January 5, 2024 21:26
@datadog-datadog-prod-us1
Copy link

datadog-datadog-prod-us1 bot commented Jan 5, 2024

Datadog Report

Branch report: jward/RUM-1961-session-id
Commit report: 1abd42e
Test service: dd-sdk-ios

✅ 0 Failed, 2483 Passed, 0 Skipped, 4m 34.95s Wall Time
⬇️ Test Sessions change in coverage: 7 decreased, 6 increased

⬇️ Code Coverage Decreases vs Default Branch (7)

This report shows up to 5 code coverage decreases.

  • test DatadogCrashReportingTests tvOS (-0.03%) - Details
  • test DatadogInternalTests tvOS (-0.01%) - Details
  • test DatadogTraceTests iOS (-0.01%) - Details
  • test DatadogLogsTests tvOS (-0.01%) - Details
  • test DatadogLogsTests iOS (-0.01%) - Details
  • test DatadogWebViewTrackingTests iOS (-0.00%) - Details
  • test DatadogCrashReportingTests iOS (-0.00%) - Details

Comment on lines 199 to 207
var currentSessionID: String? {
get {
guard let activeSession = self.scopes.activeSession else {
return nil
}

return activeSession.sessionUUID.rawValue.uuidString
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocker/ This isn't thread safe and suffers from race condition.

Both problems are not visible in tests this PR adds in MonitorTests, because it is using PassthroughCoreMock which is single-threaded and we end these tests by calling monitor.flush() to force-syncs monitor state. To surface these problems, try adding tests in RUMMonitorTests.swift where we use a real instance of the SDK core.

Solving thread-safety is simple as it may only require using queue.sync {}. The price would be on performance - it will block the caller thread for the duration of current RUM event processing.

Solving race condition would be more difficult, as it may require sync-ing on core context queue as well. This might be not a good idea, as it will block the caller thread for additional duration of pending core operations. For that reason there is no sync {} API provided by core and we may need to use semaphores to workaround it.

Compromise might be guaranteeing thread-safety but explicitly not promising sessionID integrity (in API comment). It would mean that following sequence might print the same sessionID twice:

print(monitor.currentSessionID)
monitor.stopSession()
monitor.startView(key: "Foo")
print(monitor.currentSessionID)

Alternatively, we can make this API asynchronous:

monitor.currentSessionID { sessionID in
   print(sessionID) // called asynchronously
}

and dispatch sessionID in the same model as we are processing RUM commands. This would be the correct solution, but it might be less convenient for users.

DatadogRUM/Tests/RUMMonitor/MonitorTests.swift Outdated Show resolved Hide resolved
@fuzzybinary
Copy link
Member Author

@ncreated Switched to the async callback. Let me know what you think.

@fuzzybinary fuzzybinary requested a review from ncreated January 8, 2024 17:05
Copy link
Member

@ncreated ncreated left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation looks fine 👍, although we need a change in tests. Also, as we're adding user-facing API:

  • please add CHANGELOG.md entry

Comment on lines 77 to 93
func testWhenEnabled_currentSessionStartsAsNil() {
// Given
let expectation = XCTestExpectation(description: "currentSessionID called")

// When
RUM.enable(with: config, in: core)
XCTAssertNotNil(core.get(feature: RUMFeature.self))

// Then
RUMMonitor.shared().getCurrentSessionID {
XCTAssertNil($0)
expectation.fulfill()
}

wait(for: [expectation], timeout: 0.1)
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking/ This test is false positive. There is no such behaviour as "current session starts as nil" after #1594

One problem is that RUMMonitor.shared() is missing the core:

RUMMonitor.shared(in: core)

However, if we pass the core reference this test will fail because we use FeatureRegistrationCoreMock in this file and that only offers feature registration capability, see:

/// Core mock that only allows registering and retrieving features.
///
/// Usage:
///
/// let core = FeatureRegistrationCoreMock()
/// let feature = MyCustomFeature()
///
/// try core.register(feature: feature)
///
/// core.get(feature: MyCustomFeature.self) === feature // true
/// core.get(feature: OtherFeature.self) // returns nil
///
/// **Note:** If you need different capabilities, check other available core mocks,
/// before you consider adding it here.
public class FeatureRegistrationCoreMock: DatadogCoreProtocol {

If we change it to PassthroughCoreMock as suggested, it will keep failing because that mock doesn't support get<T>(feature:) required in `RUMMonitor.shared(in:).

After all, I think the problem is because we try to test RUMMonitor in RUMTests.swift, which is only configured to test RUM.* configuration and no behaviours. My recommendation is to remove this test from here and cover this flow in RUMMonitorTests.swift, which depends on real instance of the core.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'll just delete this test then, and add a test to RUMMonitorTests that checks that the session is nil after a call to stopSession.

Thoughts?

DatadogCore/Tests/Datadog/RUM/RUMMonitorTests.swift Outdated Show resolved Hide resolved
@fuzzybinary fuzzybinary requested a review from ncreated January 9, 2024 14:36
Copy link
Member

@ncreated ncreated left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 💪

@fuzzybinary fuzzybinary merged commit 600aff7 into develop Jan 9, 2024
6 checks passed
@fuzzybinary fuzzybinary deleted the jward/RUM-1961-session-id branch January 9, 2024 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants