Skip to content

[iOS] Pre-init DdLogs calls cache NOPLogger in lazy var, breaking all subsequent logs #1162

@Brian-Yeh

Description

@Brian-Yeh

Describe the bug

After upgrading from @datadog/mobile-react-native v2 to v3, all iOS logs are permanently lost if any DdLogs call occurs before DdSdkReactNative.initialize() completes.

In v2, DdLogsImplementation.swift had an isSDKInitialized() guard that rejected pre-init log calls early, preventing the lazy var logger from being accessed. This meant the lazy logger was only created after init, producing a real Logger.

In v3, commit f7d9af0 removed this guard. It's unclear why this was deemed not necessary anymore though. Now, pre-init log calls access the lazy var logger, which calls Logger.create() before Logs.enable() has run. The native iOS SDK returns a NOPLogger (empty no-op implementation). Because it's a lazy var, this NOPLogger is cached permanently — all subsequent log calls for the lifetime of the app are silently dropped, even after the SDK initializes.

This was actually an issue that was fixed before: #468, the v3 change essentially re-introduces it.

Reproduction steps

import { DdSdkReactNative, DdLogs } from '@datadog/mobile-react-native';

// Any log call before initialize completes triggers the bug on iOS
DdLogs.info('app starting');

// Even after init completes, all logs are silently dropped
await DdSdkReactNative.initialize(config);
DdLogs.info('this will never appear in Datadog on iOS');

This is common in React Native apps where logging happens during module initialization or early component mounts before the async SDK init resolves.

SDK logs

[DATADOG SDK] 🐶 → 12:12:14.101 ⛔️ Failed to build `Logger`.

Error details:
→ type: ProgrammerError
→ message: 🔥 Datadog SDK usage error: `Datadog.initialize()` must be called prior to `Logger.create()`.
→ stack: 🔥 Datadog SDK usage error: `Datadog.initialize()` must be called prior to `Logger.create()`.

Expected behavior

Pre-init log calls should either:

  1. Be rejected with an error (as in v2) so the lazy var logger is not accessed until post-init. Ideally, this would surface in the JS logs as well
  2. Be buffered and replayed after initialization (like DdRum/DdTrace)
  3. The lazy var should be reset/re-created after SDK initialization so it picks up a real Logger instead of caching the NOPLogger permanently

Affected SDK versions

3.1.0

Latest working SDK version

2.13.2

Did you confirm if the latest SDK version fixes the bug?

Yes

Integration Methods

NPM

React Native Version

0.81.5

Package.json Contents

No response

iOS Setup

No response

Android Setup

No response

Device Information

No response

Other relevant information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions