diff --git a/.github/scripts/run-simulator-tests.sh b/.github/scripts/run-simulator-tests.sh
index d63d9f9..6ecb2a2 100755
--- a/.github/scripts/run-simulator-tests.sh
+++ b/.github/scripts/run-simulator-tests.sh
@@ -46,6 +46,15 @@ for package in objc core internal logs rum sessionreplay trace webviewtracking c
rm -rf "${HOME}/.nuget/packages/datadognet.${package}.ios/${VERSION}"
done
+# The app's own intermediate output has to go too, not just the NuGet cache. The native payload
+# is extracted out of the package into obj/ and copied into the .app, and neither step re-runs
+# when the package version string is unchanged - so a rebuilt package of the same version leaves
+# the *previous* build's xcframeworks embedded in the app. That produced a genuinely baffling
+# failure once: the frameworks were present and loaded, but every Objective-C class lookup missed,
+# because the app was running the previous release's binaries.
+rm -rf "${REPO_ROOT}/tests/DatadogNet.iOS.DeviceTests/obj" \
+ "${REPO_ROOT}/tests/DatadogNet.iOS.DeviceTests/bin"
+
echo "==> building device tests (version=${VERSION}, tfm=${TARGET_FRAMEWORK}, sdk=${sdk_version})"
( cd "${SDK_DIR}" && dotnet build "${PROJECT}" \
--configuration Release \
diff --git a/Directory.Build.props b/Directory.Build.props
index 161e2a8..f843958 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -15,7 +15,7 @@
DataDog-SDK-iOS-net repository versioned CrashReporter.iOS as 1.11.2.1 instead; that made it
impossible to tell which Datadog release a given CrashReporter package belonged to.
-->
- 2.17.0
+ 2.30.2
1
$(DatadogNativeVersion).$(DatadogBindingRevision)
diff --git a/README.md b/README.md
index 8c207a3..5c46a41 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ DDRUM.EnableWith(new DDRUMConfiguration(applicationID: ""));
- [Installing](#installing)
- [Usage](#usage)
- [Convenience API](#convenience-api)
+- [API coverage](#api-coverage)
- [Migrating from `DatadogCore.iOS` / `DatadogObjc.iOS`](#migrating-from-datadogcoreios--datadogobjcios)
- [How this repository works](#how-this-repository-works)
- [Building locally](#building-locally)
@@ -44,8 +45,8 @@ DDRUM.EnableWith(new DDRUMConfiguration(applicationID: ""));
## Packages
Eleven packages, one per native framework in the Datadog release. Versions are
-`.` — `2.17.0.1` is dd-sdk-ios **2.17.0**, binding revision
-**1**. The fourth component belongs to this repository and advances when the bindings or packaging
+`.` — `2.30.2.1` is dd-sdk-ios **2.30.2**, binding revision
+**2**. The fourth component belongs to this repository and advances when the bindings or packaging
change while the native binaries stay put.
| Package | Wraps | Depends on | What it is for |
@@ -65,7 +66,7 @@ change while the native binaries stay put.
Most apps need one line:
```xml
-
+
```
Add `DatadogNet.CrashReporting.iOS` for crash reporting and `DatadogNet.WebViewTracking.iOS` for
@@ -87,7 +88,7 @@ OS-provided Swift runtime, which is only ABI-stable from 12.2.
```xml
-
+
```
@@ -100,7 +101,7 @@ Windows head does not try to restore them:
```xml
-
+
```
@@ -206,18 +207,29 @@ helpers. Propagation style is chosen with `DDTracingHeaderType` — `Datadog`, `
### Session Replay
```csharp
-DDSessionReplay.EnableWith(new DDSessionReplayConfiguration(replaySampleRate: 100)
-{
- DefaultPrivacyLevel = DDSessionReplayConfigurationPrivacyLevel.Mask,
-});
+using DatadogSessionReplay;
+
+DDSessionReplay.EnableWith(new DDSessionReplayConfiguration(
+ replaySampleRate: 100,
+ textAndInputPrivacyLevel: DDTextAndInputPrivacyLevel.MaskAll,
+ imagePrivacyLevel: DDImagePrivacyLevel.MaskAll,
+ touchPrivacyLevel: DDTouchPrivacyLevel.Hide));
```
-Requires RUM. Privacy levels are `Allow`, `MaskUserInput` and `Mask`; the level decides what is
-redacted *on the device*, before anything is uploaded. Loosen it deliberately.
+Requires RUM. The three levels decide what is redacted *on the device*, before anything is
+uploaded, and the initializer requires all three so the choice is never left implicit. Loosen them
+deliberately.
+
+A single view can override the session-wide levels:
+
+```csharp
+var overrides = myView.GetDdSessionReplayPrivacyOverrides();
+overrides.TextAndInputPrivacy = DDTextAndInputPrivacyLevelOverride.MaskAll;
+overrides.Hide = new NSNumber(true);
+```
-> `DDSessionReplay` exists in two namespaces — `DatadogObjc` and `DatadogSessionReplay`. They are
-> different native classes that do the same thing. Prefer the `DatadogObjc` one so a single
-> `using DatadogObjc;` covers the whole SDK; importing both namespaces makes the name ambiguous.
+Set `StartRecordingImmediately = false` to enable the feature without recording, then call
+`DDSessionReplay.StartRecording()` once the user has consented, and `StopRecording()` to pause.
### Crash reporting
@@ -270,6 +282,7 @@ still there; nothing is hidden or renamed.
| six methods per level, plus an `NSError` you do not have | `logger.Log(level, message, exception?, attributes?)` |
| `DDDatadog.SetUserInfoWithId(id, null, null, empty)` | `DDDatadog.SetUserInfo(id)` |
| `DDTrackingConsent.Granted` (a class, not an enum) | `DDDatadog.SetTrackingConsent(TrackingConsent.Granted)` |
+| `DDURLSessionInstrumentation.EnableWithConfiguration(...)` with a `Class` as a raw `IntPtr` | `DDURLSessionInstrumentation.Enable()` |
The view scope is the one worth adopting everywhere: the raw API is a `StartViewWithKey` /
`StopViewWithKey` pair matched by string key, and a view left open by an early return or an
@@ -279,6 +292,61 @@ Attribute values may be strings, any numeric type, `bool`, `DateTime`, `DateTime
enums, `NSObject`s, arrays, and nested dictionaries. Anything else throws `ArgumentException`
rather than being silently dropped.
+### Redacting events before upload
+
+Both RUM and Logs let you rewrite or drop events on the device, before anything is uploaded. This
+is the supported way to keep PII out of Datadog.
+
+```csharp
+var logs = new DDLogsConfiguration(customEndpoint: null);
+logs.SetEventMapper(logEvent =>
+{
+ logEvent.Message = Redact(logEvent.Message);
+ return logEvent; // or return null to drop the event entirely
+});
+DDLogs.EnableWith(logs);
+```
+
+RUM has five equivalents — `SetViewEventMapper`, `SetActionEventMapper`, `SetResourceEventMapper`,
+`SetErrorEventMapper` and `SetLongTaskEventMapper` — registered on `DDRUMConfiguration` before
+`DDRUM.EnableWith`. Mappers can only be set at configuration time.
+
+### Network instrumentation
+
+```csharp
+DDURLSessionInstrumentation.Enable();
+```
+
+`MySessionDelegate` must be an `NSObject` implementing `INSUrlSessionDataDelegate` and carrying a
+`[Register]` attribute. The raw binding takes the delegate class as an `IntPtr`, which accepts
+`IntPtr.Zero` happily and then instruments nothing; the generic form resolves the Objective-C class
+and throws if it does not exist.
+
+---
+
+## API coverage
+
+Every public Objective-C type Datadog declares for 2.30.2 is bound except one, and every documented
+feature is reachable from C#. Measured by parsing the `-Swift.h` header each xcframework ships and
+diffing it against the bound selectors — not by reading the documentation.
+
+The unbound type is **`DDRUMLongTaskEventLongTaskScripts`**, with the `scripts` property that
+returns it. It describes JavaScript long tasks, is reachable only from inside a RUM long-task event
+mapper, and a native iOS app does not produce them.
+
+Three further groups of *members* are deliberately not bound:
+
+- **Four `DDTelemetryConfigurationEventTelemetryConfiguration` properties** named after the Session
+ Replay privacy levels. These are read-only fields on a *telemetry* event, describing what the SDK
+ reported about its own configuration; they are not knobs. The real ones are on
+ `DDSessionReplayConfiguration`, and all of those are bound.
+- **`initWithSamplingRate:` and `initWithSamplingRate:injectEncoding:` on the tracing header
+ writers** — deprecated upstream, and differing from the bound `initWithSampleRate:` forms only by
+ argument label, which Objective Sharpie cannot project as two separate initializers.
+- **Three `URLSession` overloads on `DatadogURLSessionDelegate`** — see
+ [the note in that binding](src/DatadogNet.Internal.iOS/ApiDefinitions.cs); binding them crashes
+ every consuming app at startup, and they remain callable under their inherited names.
+
---
## Migrating from `DatadogCore.iOS` / `DatadogObjc.iOS`
@@ -288,7 +356,7 @@ edit — no `using` directive and no call site changes.
```diff
-
-+
++
```
| Old | New |
@@ -317,7 +385,7 @@ selector is already registered on the member 'DidFinishCollectingMetrics'.
```
**`CrashReporter` is versioned with everything else.** It was `1.11.2.1`, tracking PLCrashReporter
-upstream; it is now `2.17.0.1` like the rest, because it ships inside the same Datadog release and
+upstream; it is now `2.30.2.1` like the rest, because it ships inside the same Datadog release and
the old numbering made it impossible to tell which Datadog build a given package belonged to.
**`net7.0-ios` is gone, `net9`/`net10` are new.** The old packages targeted `net7.0-ios16.1` and
@@ -382,7 +450,7 @@ sample directly, as the command in the previous section does.
Requires macOS, Xcode, and the .NET 9 and .NET 10 SDKs with the `ios` workload.
```bash
-./build/FetchXcFrameworks.sh # ~116 MB, verified against build/checksums.txt
+./build/FetchXcFrameworks.sh # ~100 MB, verified against build/checksums.txt
./build/BuildNugets.sh # packs all eleven into artifacts/
dotnet test tests/DatadogNet.iOS.PackageTests
```
@@ -390,7 +458,7 @@ dotnet test tests/DatadogNet.iOS.PackageTests
Run the on-simulator smoke tests against the packed packages:
```bash
-./.github/scripts/run-simulator-tests.sh 2.17.0.1 net9.0-ios18.0
+./.github/scripts/run-simulator-tests.sh 2.30.2.1 net9.0-ios18.0
```
Build and run the sample:
@@ -436,7 +504,7 @@ dropping a package — update the `FRAMEWORKS` list, add or remove the binding p
## Releasing
-Tag it. `v2.17.0.1` builds, tests, publishes all eleven packages to nuget.org via trusted
+Tag it. `v2.30.2.1` builds, tests, publishes all eleven packages to nuget.org via trusted
publishing, and creates a GitHub release. The tag drives which native SDK is bound, so an older
line can be released by tagging it.
@@ -452,9 +520,8 @@ Curated notes in `docs/release-notes/.md` replace the generated commit
common cause. Set `DDDatadog.VerbosityLevel = DDSDKVerbosityLevel.Debug` to see the SDK's own
diagnostics in the Xcode console.
-**`DDSessionReplay` is an ambiguous reference.** You have imported both `DatadogObjc` and
-`DatadogSessionReplay`. Use the `DatadogObjc` one, or alias:
-`using SessionReplay = DatadogSessionReplay;`.
+**`DDSessionReplay` could not be found.** It moved out of the `DatadogObjc` namespace in
+dd-sdk-ios 2.19.0 and now lives only in `DatadogSessionReplay`. Add `using DatadogSessionReplay;`.
**`This version of .NET for iOS requires Xcode 26.0`.** Only affects `net10.0-ios26.0`. See
[Building locally](#building-locally).
diff --git a/build/GenerateBindings.sh b/build/GenerateBindings.sh
index 0dfc457..74e9afc 100755
--- a/build/GenerateBindings.sh
+++ b/build/GenerateBindings.sh
@@ -11,10 +11,29 @@ set -e
# ./GenerateBindings.sh # every framework
# ./GenerateBindings.sh DatadogObjc # just one
#
-# Requires Objective Sharpie, which is not on nuget.org and has to be installed separately:
+# Requires Objective Sharpie, which is not on nuget.org and has to be obtained separately:
#
# https://aka.ms/objective-sharpie
#
+# Set SHARPIE to point at the binary if it is not on PATH. The installer needs administrator
+# rights, but the package can also just be expanded and run in place, which is enough:
+#
+# curl -fsSL -o sharpie.pkg https://aka.ms/objective-sharpie
+# pkgutil --expand-full sharpie.pkg sharpie-x
+# export SHARPIE="$PWD/sharpie-x/Framework.pkg/Payload/Library/Frameworks/ObjectiveSharpie.framework/Versions/*/bin/sharpie"
+#
+# KNOWN LIMITATION: Objective Sharpie 3.5.116 (the current release) bundles a clang that cannot
+# parse the module maps in recent iOS SDKs. Against the 18.5 and 26.5 SDKs it fails with
+#
+# module '_stddef' requires feature 'found_incompatible_headers__check_search_paths'
+# unknown type name 'size_t'
+#
+# before emitting anything. It also refuses to bind a framework whose recorded DTSDKName is not
+# installed ("framework requires SDK 'iphoneos18.2'"), which is normal for a downloaded binary.
+# Until sharpie ships a newer clang, the 2.30.2 binding delta was produced by reading the shipped
+# -Swift.h headers directly and diffing them against the previous version's - see the release
+# notes. Keep this script for the day it works again.
+#
# IMPORTANT: the output is a starting point, not a drop-in replacement. It is written to
# ../Binding/ deliberately, *not* over the committed ApiDefinitions.cs files, because those carry
# fixes that regenerating would silently undo. Diff the two and port the real changes across.
@@ -42,8 +61,9 @@ ROOT="$(cd .. && pwd)"
LIBS="$ROOT/libs"
OUTPUT="$ROOT/Binding"
-if ! command -v sharpie >/dev/null 2>&1; then
- echo "error: sharpie is not installed - see https://aka.ms/objective-sharpie" >&2
+SHARPIE="${SHARPIE:-sharpie}"
+if ! command -v "$SHARPIE" >/dev/null 2>&1; then
+ echo "error: sharpie not found - set SHARPIE, or see https://aka.ms/objective-sharpie" >&2
exit 1
fi
@@ -86,7 +106,7 @@ for framework in $FRAMEWORKS; do
# -scope keeps the output to this framework's own headers: without it, a framework that
# imports another (all of them import DatadogInternal) has the imported API duplicated into
# its definitions, and the same type ends up bound in several packages.
- sharpie bind \
+ "$SHARPIE" bind \
--output "$target" \
--namespace "$framework" \
--sdk "iphoneos$SDK" \
diff --git a/build/checksums.txt b/build/checksums.txt
index ff3debe..a1f34c3 100644
--- a/build/checksums.txt
+++ b/build/checksums.txt
@@ -18,3 +18,4 @@
# Format:
2.17.0 e948375d758527118550e5a5f89a332264309b19c96e3ec56e2bf84789b6f5f9
+2.30.2 0f944182502801c7bf7e47ddc2a6a3be54fcc6067fb7f9ef8a495a86361baaa7
diff --git a/docs/release-notes/2.17.0.1.md b/docs/release-notes/2.17.0.1.md
index 6099250..b34cebe 100644
--- a/docs/release-notes/2.17.0.1.md
+++ b/docs/release-notes/2.17.0.1.md
@@ -92,7 +92,7 @@ there is no long-lived API key.
## Changed
-**Packages are about 74 MB in total, down from what shipping every slice would cost.** The upstream
+**The eleven packages come to about 80 MB in total, against roughly a gigabyte if every slice shipped.** The upstream
archive carries tvOS slices for every framework, macCatalyst/macOS/watchOS/visionOS for two of them,
and a full set of dSYMs — none of it reachable from a `net*-ios` binding, and all of it embedded
once per target framework. `FetchXcFrameworks.sh` strips to the two iOS slices and rewrites each
diff --git a/docs/release-notes/2.17.0.2.md b/docs/release-notes/2.17.0.2.md
new file mode 100644
index 0000000..fa4decd
--- /dev/null
+++ b/docs/release-notes/2.17.0.2.md
@@ -0,0 +1,106 @@
+## What's changed
+
+Binding-only release. The native SDK is unchanged — still **dd-sdk-ios 2.17.0** — and so are the
+package IDs, namespaces and every existing signature. Upgrading is a version bump.
+
+This release closes two gaps found by diffing the bound selectors against the `-Swift.h` headers
+each xcframework actually ships, rather than against Datadog's documentation. Both were places
+where the generated binding silently under-reported what the native SDK can do.
+
+> **Package versions are `.`.** `2.17.0.2` is dd-sdk-ios
+> `2.17.0`, binding revision `2`. The fourth component belongs to this repository and advances when
+> the bindings or packaging change while the native binaries stay put.
+
+## Added
+
+**Log event mapping — `DDLogsConfiguration.SetEventMapper`, and the whole `DDLogEvent` model.**
+
+Objective Sharpie had omitted all of it: ten `DDLogEvent*` classes, four enums, and
+`setEventMapper:` itself. The effect was that RUM had all five of its event mappers while Logs had
+none — so there was no supported way to redact or drop a log before it left the device, which is
+the mechanism behind most "keep PII out of Datadog" requirements. Transcribed by hand from the
+shipped header.
+
+```csharp
+var logs = new DDLogsConfiguration(customEndpoint: null);
+logs.SetEventMapper(logEvent =>
+{
+ logEvent.Message = Redact(logEvent.Message);
+ return logEvent; // or return null to drop the event entirely
+});
+DDLogs.EnableWith(logs);
+```
+
+The mapper receives a fully populated `DDLogEvent`: message, status, error (kind, message, stack,
+fingerprint, binary images), logger and service names, thread, app version and build, OS, device,
+user info, network connection info, mobile carrier info, attributes and tags. `Message`, `Tags`,
+the error fields and the two attribute dictionaries are writable; the rest are read-only, exactly
+as the native header declares them.
+
+New types: `DDLogEvent`, `DDLogEventAttributes`, `DDLogEventBinaryImage`, `DDLogEventCarrierInfo`,
+`DDLogEventDd`, `DDLogEventDeviceInfo`, `DDLogEventError`, `DDLogEventNetworkConnectionInfo`,
+`DDLogEventOperatingSystem`, `DDLogEventUserInfo`, and the enums `DDLogEventStatus`,
+`DDLogEventReachability`, `DDLogEventRadioAccessTechnology` and `DDLogEventInterface`.
+
+**Type-based `DDURLSessionInstrumentation`.**
+
+`DDURLSessionInstrumentation` is what Datadog documents for automatic RUM resource collection and
+distributed tracing, but it takes an Objective-C `Class`, which reaches C# as a bare `IntPtr`.
+Nothing in the generated signature suggests you must pass `Class.GetHandle(typeof(T))`, and the
+native call accepts `IntPtr.Zero` without complaint — then instruments nothing, silently.
+
+```csharp
+DDURLSessionInstrumentation.Enable();
+// ...
+DDURLSessionInstrumentation.Disable();
+```
+
+`Enable()`, `Disable()`, their `Type`-taking overloads, and
+`DDURLSessionInstrumentationConfiguration.Create()` resolve the Objective-C class from a managed
+type and throw `ArgumentException` if it is not registered. `DelegateType` exposes the same value
+as a `Type` rather than an `IntPtr`. The delegate must be an `NSObject` implementing
+`INSUrlSessionDataDelegate` and carrying a `[Register]` attribute.
+
+The `IntPtr` members are untouched, so existing code keeps working.
+
+## Tests
+
+The on-simulator suite grows from 14 checks to 17, all running against the packed packages on both
+`net9.0-ios18.0` and `net10.0-ios26.0`:
+
+- **RUM event mappers are invoked.** The mappers are registered on the real configuration before
+ `DDRUM.EnableWith` and asserted to have fired after events are produced. This is the only part of
+ the binding that passes a managed delegate into Swift and gets a Swift object back, so if block
+ marshalling were wrong anywhere it would be wrong here — and the failure would surface as a crash
+ inside the SDK's event-writing path, far from the call that registered the mapper.
+- **A Logs event mapper redacts a message**, and the rewritten event survives back into Swift.
+- **A URLSession delegate is instrumented by type**, and a type the Objective-C runtime has never
+ heard of is rejected rather than silently instrumenting nothing.
+
+## Documentation
+
+The README gains an **API coverage** section stating what is bound and what is not, measured rather
+than asserted: **346 of the 347 public Objective-C types** Datadog declares for 2.17.0.
+
+The one unbound type is `DDUIPressRUMActionsPredicate`, which reports Siri Remote presses. The
+protocol is declared in the iOS header, but nothing in the iOS slice accepts it — the property that
+consumes it exists only on tvOS — so it is unreachable from a `net*-ios` app.
+
+Three groups of members are also deliberately unbound, and the section says why: the JavaScript
+long-task and vital detail models reachable only from inside a mapper, four read-only *telemetry*
+fields that look like Session Replay privacy knobs but are not (the real knob,
+`DDSessionReplayConfiguration.DefaultPrivacyLevel`, was already bound), and the three
+`DatadogURLSessionDelegate` overloads whose binding crashed every consuming app at startup in the
+old packages.
+
+The Convenience API table and the Usage section now cover event mapping and network instrumentation.
+
+## Upgrading from 2.17.0.1
+
+```diff
+-
++
+```
+
+Nothing is removed or renamed, and the native binaries are byte-for-byte the same build. All eleven
+packages move together, as they depend on each other at an exact version.
diff --git a/docs/release-notes/2.30.2.1.md b/docs/release-notes/2.30.2.1.md
new file mode 100644
index 0000000..a4e94f4
--- /dev/null
+++ b/docs/release-notes/2.30.2.1.md
@@ -0,0 +1,149 @@
+## What's changed
+
+Updates the native SDK from **dd-sdk-ios 2.17.0 to 2.30.2**, the last release of the 2.x line —
+thirteen minor versions, published between September 2024 and October 2025. The 2.x line continued
+to receive fixes after 3.0.0 shipped, so 2.30.2 is genuinely the end of the line rather than the
+last release before the split.
+
+Everything upstream added is bound: **29 new types, 17 new enums and 133 new members** across the
+eleven packages — 27 types and 120 members in `DatadogObjc` alone. Measured by parsing the
+`-Swift.h` header each xcframework ships and diffing it against 2.17.0's, not by reading the
+documentation.
+
+> **Package versions are `.`.** `2.30.2.1` is dd-sdk-ios
+> `2.30.2`, binding revision `1`. The revision restarts at 1 for each new native version.
+
+## ⚠️ Breaking changes
+
+**`DDSessionReplay` and `DDSessionReplayConfiguration` no longer exist in the `DatadogObjc`
+namespace.** Upstream removed the parallel copies it used to declare there; Session Replay now
+lives only in `DatadogSessionReplay`. If you wrote `using DatadogObjc;` and referred to
+`DDSessionReplay`, add the other namespace:
+
+```diff
+ using DatadogObjc;
++using DatadogSessionReplay;
+```
+
+The upside: the two identically named types that previously made `DDSessionReplay` ambiguous when
+both namespaces were imported are gone, so no alias is needed any more.
+
+**Session Replay privacy is now three settings, not one.** `defaultPrivacyLevel` is deprecated
+upstream in favour of independent text/input, image and touch levels, and the new initializer
+requires all three — the choice can no longer be left implicit.
+
+```diff
+-DDSessionReplay.EnableWith(new DDSessionReplayConfiguration(replaySampleRate: 100)
+-{
+- DefaultPrivacyLevel = DDSessionReplayConfigurationPrivacyLevel.Mask,
+-});
++DDSessionReplay.EnableWith(new DDSessionReplayConfiguration(
++ replaySampleRate: 100,
++ textAndInputPrivacyLevel: DDTextAndInputPrivacyLevel.MaskAll,
++ imagePrivacyLevel: DDImagePrivacyLevel.MaskAll,
++ touchPrivacyLevel: DDTouchPrivacyLevel.Hide));
+```
+
+The old single-argument initializer and `DefaultPrivacyLevel` are still bound, so existing code
+keeps compiling — but they are deprecated upstream and will be removed. `Allow`, `Mask` and
+`MaskUserInput` map onto the new levels as Datadog documents.
+
+**`DDRUMVitalEventVital.details` is gone**, replaced by `failureReason`, `parentId`, `stepType` and
+`vitalDescription`. It is only reachable from inside a RUM event mapper, so most apps will not
+notice.
+
+## Fixed
+
+**Session Replay would have failed at runtime had the binding been carried over unchanged.**
+Through 2.17.0 these classes were declared `SWIFT_CLASS("_TtC20DatadogSessionReplay...")`, which
+sets the Objective-C runtime name to the mangled Swift symbol — so the binding spelled that mangled
+name out in `[BaseType (Name = ...)]`. From 2.19.0 they are declared `SWIFT_CLASS_NAMED`, which
+expands to `swift_name(...)` only and leaves the runtime name as the plain `@interface` name. The
+binary confirms it: it exports `_OBJC_CLASS_$_DDSessionReplay`, not the mangled symbol. The `Name=`
+attributes are therefore removed. Keeping them would have compiled cleanly and then failed with
+"the native class hasn't been loaded" the first time a replay type was touched.
+
+## Added
+
+**Fine-grained Session Replay masking** (2.18.0) — `DDTextAndInputPrivacyLevel`,
+`DDImagePrivacyLevel` and `DDTouchPrivacyLevel`.
+
+**Per-view privacy overrides** (2.19.0) — `DDSessionReplayPrivacyOverrides`, reached through a
+category on `UIView`, so a single view can be masked or hidden regardless of the session-wide
+level:
+
+```csharp
+var overrides = myView.GetDdSessionReplayPrivacyOverrides();
+overrides.TextAndInputPrivacy = DDTextAndInputPrivacyLevelOverride.MaskAll;
+overrides.Hide = new NSNumber(true);
+```
+
+**Deferred replay recording** (2.21.0) — `StartRecordingImmediately` on the configuration, plus
+`DDSessionReplay.StartRecording()` and `StopRecording()`, for apps that start recording only after
+consent or on a particular screen.
+
+**Account information** (2.29.0) — `DDDatadog.SetAccountInfoWithAccountId`, `AddAccountExtraInfo`
+and `ClearAccountInfo`. Account details propagate to Logs, RUM, Traces and error reporting.
+`DDLogEvent` gains a matching `AccountInfo`, and every RUM event model gains `Account`.
+
+**`DDDatadog.ClearUserInfo`** (2.30.0), and `SetUserInfoWithUserId`, which requires an id where the
+old overload did not (2.24.0).
+
+**SwiftUI auto-tracking** (2.29.0) — `DDSwiftUIRUMViewsPredicate` and
+`DDSwiftUIRUMActionsPredicate`, their `DDDefault*` implementations, and the
+`SwiftUIViewsPredicate` / `SwiftUIActionsPredicate` properties on `DDRUMConfiguration`. Bound with
+the same `[Model, Protocol]` shape as the UIKit predicates, so an app can subclass the generated
+class instead of implementing the interface.
+
+**The AP2 datacenter** (2.29.0) — `DDSite.Ap2`.
+
+**RUM attribute APIs** (2.23.0) — `DDRUMMonitor.AddAttributes` and `RemoveAttributesForKeys`, for
+setting attributes on the monitor rather than per event.
+
+**`DDConfiguration.BackgroundTasksEnabled`** (2.22.0), and `DDRUMConfiguration.TrackAnonymousUser`
+(2.24.0) with the matching `AnonymousId` on RUM user models.
+
+**New RUM view metrics** reachable through the event mappers: Time To Network Settled and
+Interaction To Next View (2.23.0), hang and hitch rates (2.25.0), and the view performance models
+(CLS, FCP, FID, INP, LCP, FBC) and slow-frame detail. Device models gain battery level, brightness,
+locale, power-saving mode and time zone (2.30.0), and every event gains `Ddtags` (2.30.1).
+
+**`DDInternalLogger`** (2.19.0) — the Objective-C entry point to the SDK's internal telemetry.
+
+**`PLCrashReporterConfig.MaxReportBytes`** and the initializer that sets it, from the PLCrashReporter
+update in 2.25.0.
+
+## Tests
+
+The on-simulator suite grows to **20 checks**, running against the packed packages on both
+`net9.0-ios18.0` and `net10.0-ios26.0`. New coverage: fine-grained Session Replay privacy with
+deferred recording start/stop, per-view privacy overrides set and read back through a fresh
+accessor, account info set/extend/clear alongside user-info clearing, and the new RUM attribute
+APIs and AP2 site.
+
+`run-simulator-tests.sh` now deletes the device app's `obj/` and `bin/` before building. Clearing
+the NuGet cache is not enough: the native payload is extracted into `obj/` and copied into the
+`.app`, and neither step re-runs when the package version string is unchanged — so re-packing the
+same version left the *previous* build's xcframeworks embedded in the app. That produced a
+genuinely misleading failure during this upgrade, in which the frameworks were present and loaded
+but every Objective-C class lookup missed, because the app was running 2.17.0 binaries against a
+2.30.2 binding.
+
+## Notes
+
+**Package size dropped from about 80 MB to about 50 MB** across the eleven packages. The frameworks
+themselves are smaller in 2.30.2; nothing changed in how they are stripped or packed.
+
+**Objective Sharpie could not be used for this upgrade.** Version 3.5.116, the current release,
+bundles a clang that cannot parse the module maps in recent iOS SDKs — it fails with
+`module '_stddef' requires feature 'found_incompatible_headers__check_search_paths'` against both
+the 18.5 and 26.5 SDKs, before emitting anything. It also refuses to bind a framework whose
+recorded `DTSDKName` is not installed, which is normal for a downloaded binary. The delta was
+therefore derived by parsing the shipped headers and diffing them against the previous version's.
+`build/GenerateBindings.sh` documents both problems and now honours a `SHARPIE` environment
+variable, so the package can be expanded and run in place without administrator rights once it
+works again.
+
+**No new packages.** dd-sdk-ios 2.30.2 ships the same eleven frameworks as 2.17.0.
+`DatadogFlags` and `DatadogProfiling` are 3.x-only, as is the removal of `DatadogObjc` and the move
+from PLCrashReporter to KSCrash.
diff --git a/samples/DatadogNet.iOS.Example/Datadog.cs b/samples/DatadogNet.iOS.Example/Datadog.cs
index 7519891..16770ae 100644
--- a/samples/DatadogNet.iOS.Example/Datadog.cs
+++ b/samples/DatadogNet.iOS.Example/Datadog.cs
@@ -1,5 +1,6 @@
using DatadogCrashReporting;
using DatadogObjc;
+using DatadogSessionReplay;
namespace DatadogNetExample;
@@ -113,19 +114,17 @@ private static void EnableSessionReplay()
{
// Session Replay requires RUM, so it is enabled last.
//
- // MaskAll is the default here on purpose. Replay records the screen, and the privacy level
- // decides what is redacted before anything leaves the device: MaskUserInput hides only what
- // the user typed, while Mask also hides all text and images. Loosen this deliberately, not
- // by accident.
- // DDSessionReplay exists in two namespaces: this one, from DatadogNet.Objc.iOS, and
- // another in DatadogNet.SessionReplay.iOS. They are not the same class - each wraps a
- // different native type (_TtC11DatadogObjc15DDSessionReplay against
- // _TtC20DatadogSessionReplay15DDSessionReplay) - but they do the same thing. Prefer the
- // DatadogObjc one, as here, so a single `using DatadogObjc;` covers the whole SDK;
- // importing both namespaces makes the name ambiguous and needs an alias to resolve.
- DDSessionReplay.EnableWith(new DDSessionReplayConfiguration(replaySampleRate: 100)
- {
- DefaultPrivacyLevel = DDSessionReplayConfigurationPrivacyLevel.Mask,
- });
+ // From dd-sdk-ios 2.19.0 the single defaultPrivacyLevel is replaced by three independent
+ // levels, and they are required by the initializer rather than defaulted - so the choice
+ // is made deliberately rather than inherited. Replay records the screen, and these decide
+ // what is redacted *on the device*, before anything is uploaded.
+ //
+ // These are the most private settings: mask every text and input, mask every image, and
+ // hide touches. Loosen them deliberately, not by accident.
+ DDSessionReplay.EnableWith(new DDSessionReplayConfiguration(
+ replaySampleRate: 100,
+ textAndInputPrivacyLevel: DDTextAndInputPrivacyLevel.MaskAll,
+ imagePrivacyLevel: DDImagePrivacyLevel.MaskAll,
+ touchPrivacyLevel: DDTouchPrivacyLevel.Hide));
}
}
diff --git a/src/DatadogNet.Core.iOS/ApiDefinitions.cs b/src/DatadogNet.Core.iOS/ApiDefinitions.cs
index 824faad..5a21430 100644
--- a/src/DatadogNet.Core.iOS/ApiDefinitions.cs
+++ b/src/DatadogNet.Core.iOS/ApiDefinitions.cs
@@ -1,6 +1,7 @@
using System;
using DatadogCore;
using Foundation;
+using ObjCRuntime;
namespace DatadogCore
{
@@ -26,6 +27,14 @@ interface __dd_private_AppLaunchHandler
[Export ("isActivePrewarm")]
bool IsActivePrewarm { get; }
+ // -(instancetype _Nonnull)initWithProcessInfo:(NSProcessInfo * _Nonnull)processInfo;
+ [Export ("initWithProcessInfo:")]
+ NativeHandle Constructor (NSProcessInfo processInfo);
+
+ // -(void)observeNotificationCenter:(NSNotificationCenter * _Nonnull)notificationCenter;
+ [Export ("observeNotificationCenter:")]
+ void ObserveNotificationCenter (NSNotificationCenter notificationCenter);
+
// -(void)setApplicationDidBecomeActiveCallback:(UIApplicationDidBecomeActiveCallback _Nonnull)callback;
[Export ("setApplicationDidBecomeActiveCallback:")]
void SetApplicationDidBecomeActiveCallback (UIApplicationDidBecomeActiveCallback callback);
diff --git a/src/DatadogNet.CrashReporter.iOS/ApiDefinitions.cs b/src/DatadogNet.CrashReporter.iOS/ApiDefinitions.cs
index 5c500f9..d8cd0df 100644
--- a/src/DatadogNet.CrashReporter.iOS/ApiDefinitions.cs
+++ b/src/DatadogNet.CrashReporter.iOS/ApiDefinitions.cs
@@ -35,6 +35,17 @@ interface PLCrashReporterConfig
[Export ("initWithSignalHandlerType:symbolicationStrategy:shouldRegisterUncaughtExceptionHandler:basePath:")]
NativeHandle Constructor (PLCrashReporterSignalHandlerType signalHandlerType, PLCrashReporterSymbolicationStrategy symbolicationStrategy, bool shouldRegisterUncaughtExceptionHandler, string basePath);
+ // -(instancetype)initWithSignalHandlerType:symbolicationStrategy:
+ // shouldRegisterUncaughtExceptionHandler:basePath:maxReportBytes:
+ // Added in PLCrashReporter 1.12, shipped from dd-sdk-ios 2.25.0.
+ [Export ("initWithSignalHandlerType:symbolicationStrategy:shouldRegisterUncaughtExceptionHandler:basePath:maxReportBytes:")]
+ NativeHandle Constructor (PLCrashReporterSignalHandlerType signalHandlerType, PLCrashReporterSymbolicationStrategy symbolicationStrategy, bool shouldRegisterUncaughtExceptionHandler, string basePath, nuint maxReportBytes);
+
+ // @property (readonly, nonatomic) NSUInteger maxReportBytes;
+ // The cap on a generated crash report. Reports above it are truncated rather than dropped.
+ [Export ("maxReportBytes")]
+ nuint MaxReportBytes { get; }
+
// @property (readonly, nonatomic) NSString * basePath;
[Export ("basePath")]
string BasePath { get; }
diff --git a/src/DatadogNet.Objc.iOS/Additions/DDURLSessionInstrumentation.Ergonomics.cs b/src/DatadogNet.Objc.iOS/Additions/DDURLSessionInstrumentation.Ergonomics.cs
new file mode 100644
index 0000000..ba7edf4
--- /dev/null
+++ b/src/DatadogNet.Objc.iOS/Additions/DDURLSessionInstrumentation.Ergonomics.cs
@@ -0,0 +1,97 @@
+// Nullable annotations are enabled per file rather than for the project: the generated
+// binding sources are not written against a nullable context, and switching the whole
+// project over would bury real warnings here under hundreds of generated ones.
+#nullable enable
+
+using System;
+using Foundation;
+using ObjCRuntime;
+
+namespace DatadogObjc
+{
+ public partial class DDURLSessionInstrumentationConfiguration
+ {
+ ///
+ /// Creates a configuration that instruments the given NSUrlSessionDataDelegate type.
+ ///
+ ///
+ /// The delegate class to instrument. Must be an subclass that
+ /// implements and is registered with the
+ /// Objective-C runtime.
+ ///
+ ///
+ /// The native initializer takes an Objective-C Class, which reaches C# as a bare
+ /// . Passing the right value means knowing to call
+ /// Class.GetHandle (typeof (T)) - which nothing in the generated signature hints at,
+ /// and which silently yields for a type the runtime does not know,
+ /// leaving instrumentation quietly disabled rather than failing.
+ ///
+ ///
+ /// is not a registered Objective-C class.
+ ///
+ public static DDURLSessionInstrumentationConfiguration Create (Type delegateType) =>
+ new DDURLSessionInstrumentationConfiguration (HandleFor (delegateType, nameof (delegateType)));
+
+ ///
+ /// The delegate class to instrument.
+ public static DDURLSessionInstrumentationConfiguration Create ()
+ where TDelegate : NSObject, INSUrlSessionDataDelegate =>
+ Create (typeof (TDelegate));
+
+ /// The delegate class being instrumented.
+ ///
+ /// The typed view of , which is an holding
+ /// an Objective-C Class. Returns if the class does not map
+ /// back to a managed type.
+ ///
+ public Type? DelegateType {
+ get => DelegateClass == IntPtr.Zero ? null : Class.Lookup (new Class (DelegateClass));
+ set => DelegateClass = value is null ? IntPtr.Zero : HandleFor (value, nameof (value));
+ }
+
+ internal static IntPtr HandleFor (Type delegateType, string parameterName)
+ {
+ if (delegateType is null)
+ throw new ArgumentNullException (parameterName);
+
+ var handle = Class.GetHandle (delegateType);
+ if (handle == IntPtr.Zero) {
+ throw new ArgumentException (
+ $"'{delegateType.FullName}' is not a registered Objective-C class. It must derive from " +
+ "NSObject, implement INSUrlSessionDataDelegate, and carry a [Register] attribute.",
+ parameterName);
+ }
+
+ return handle;
+ }
+ }
+
+ public partial class DDURLSessionInstrumentation
+ {
+ /// Starts instrumenting the given delegate type for RUM resource and trace collection.
+ ///
+ /// Shorthand for
+ /// EnableWithConfiguration (DDURLSessionInstrumentationConfiguration.Create (delegateType)).
+ /// Enable this once, before creating the NSUrlSession that uses the delegate.
+ ///
+ public static void Enable (Type delegateType) =>
+ EnableWithConfiguration (DDURLSessionInstrumentationConfiguration.Create (delegateType));
+
+ ///
+ /// The delegate class to instrument.
+ public static void Enable ()
+ where TDelegate : NSObject, INSUrlSessionDataDelegate =>
+ Enable (typeof (TDelegate));
+
+ /// Stops instrumenting the given delegate type.
+ public static void Disable (Type delegateType) =>
+ DisableWithDelegateClass (
+ DDURLSessionInstrumentationConfiguration.HandleFor (delegateType, nameof (delegateType)));
+
+ ///
+ /// The delegate class to stop instrumenting.
+ public static void Disable ()
+ where TDelegate : NSObject, INSUrlSessionDataDelegate =>
+ Disable (typeof (TDelegate));
+ }
+}
diff --git a/src/DatadogNet.Objc.iOS/ApiDefinitions.cs b/src/DatadogNet.Objc.iOS/ApiDefinitions.cs
index 2470d86..2675624 100644
--- a/src/DatadogNet.Objc.iOS/ApiDefinitions.cs
+++ b/src/DatadogNet.Objc.iOS/ApiDefinitions.cs
@@ -87,6 +87,9 @@ interface DDConfiguration
[Export ("initWithClientToken:env:")]
[DesignatedInitializer]
NativeHandle Constructor (string clientToken, string env);
+
+ [Export ("backgroundTasksEnabled")]
+ bool BackgroundTasksEnabled { get; set; }
}
partial interface IDDDataEncryption { }
@@ -163,6 +166,26 @@ interface DDDatadog
[Static]
[Export ("clearAllData")]
void ClearAllData ();
+
+ [Static]
+ [Export ("setUserInfoWithUserId:name:email:extraInfo:")]
+ void SetUserInfoWithUserId (string userId, [NullAllowed] string name, [NullAllowed] string email, NSDictionary extraInfo);
+
+ [Static]
+ [Export ("clearUserInfo")]
+ void ClearUserInfo ();
+
+ [Static]
+ [Export ("setAccountInfoWithAccountId:name:extraInfo:")]
+ void SetAccountInfoWithAccountId (string accountId, [NullAllowed] string name, NSDictionary extraInfo);
+
+ [Static]
+ [Export ("addAccountExtraInfo:")]
+ void AddAccountExtraInfo (NSDictionary extraInfo);
+
+ [Static]
+ [Export ("clearAccountInfo")]
+ void ClearAccountInfo ();
}
// @protocol DDUITouchRUMActionsPredicate
@@ -456,6 +479,13 @@ interface DDLogsConfiguration
[Export ("initWithCustomEndpoint:")]
[DesignatedInitializer]
NativeHandle Constructor ([NullAllowed] NSUrl customEndpoint);
+
+ // -(void)setEventMapper:(DDLogEvent * _Nullable (^ _Nonnull)(DDLogEvent * _Nonnull))mapper;
+ // Return the event to keep it, a modified event to rewrite it, or null to drop it entirely.
+ // This is the Logs counterpart of DDRUMConfiguration's five event mappers, and the only
+ // supported way to redact a log before it leaves the device.
+ [Export ("setEventMapper:")]
+ void SetEventMapper (Func mapper);
}
// @interface DDNSURLSessionDelegate : NSObject
@@ -604,6 +634,12 @@ interface DDRUMActionEvent
// @property (readonly, nonatomic, strong) DDRUMActionEventView * _Nonnull view;
[Export ("view", ArgumentSemantic.Strong)]
DDRUMActionEventView View { get; }
+
+ [Export ("account", ArgumentSemantic.Strong)]
+ DDRUMActionEventRUMAccount Account { get; }
+
+ [Export ("ddtags", ArgumentSemantic.Copy)]
+ string Ddtags { get; }
}
// @interface DDRUMActionEventAction : NSObject
@@ -716,6 +752,9 @@ interface DDRUMActionEventApplication
// @property (readonly, copy, nonatomic) NSString * _Nonnull id;
[Export ("id")]
string Id { get; }
+
+ [Export ("currentLocale", ArgumentSemantic.Copy)]
+ string CurrentLocale { get; }
}
// @interface DDRUMActionEventContainer : NSObject
@@ -766,6 +805,9 @@ interface DDRUMActionEventDD
// @property (readonly, nonatomic, strong) DDRUMActionEventDDSession * _Nullable session;
[NullAllowed, Export ("session", ArgumentSemantic.Strong)]
DDRUMActionEventDDSession Session { get; }
+
+ [Export ("sdkName", ArgumentSemantic.Copy)]
+ string SdkName { get; }
}
// @interface DDRUMActionEventDDAction : NSObject
@@ -780,6 +822,9 @@ interface DDRUMActionEventDDAction
// @property (readonly, nonatomic, strong) DDRUMActionEventDDActionTarget * _Nullable target;
[NullAllowed, Export ("target", ArgumentSemantic.Strong)]
DDRUMActionEventDDActionTarget Target { get; }
+
+ [Export ("nameSource")]
+ DDRUMActionEventDDActionNameSource NameSource { get; set; }
}
// @interface DDRUMActionEventDDActionPosition : NSObject
@@ -826,6 +871,9 @@ interface DDRUMActionEventDDConfiguration
// @property (readonly, nonatomic, strong) NSNumber * _Nonnull sessionSampleRate;
[Export ("sessionSampleRate", ArgumentSemantic.Strong)]
NSNumber SessionSampleRate { get; }
+
+ [Export ("profilingSampleRate", ArgumentSemantic.Strong)]
+ NSNumber ProfilingSampleRate { get; }
}
// @interface DDRUMActionEventDDSession : NSObject
@@ -936,6 +984,24 @@ interface DDRUMActionEventRUMDevice
// @property (readonly, nonatomic) enum DDRUMActionEventRUMDeviceRUMDeviceType type;
[Export ("type")]
DDRUMActionEventRUMDeviceRUMDeviceType Type { get; }
+
+ [Export ("batteryLevel", ArgumentSemantic.Strong)]
+ NSNumber BatteryLevel { get; }
+
+ [Export ("brightnessLevel", ArgumentSemantic.Strong)]
+ NSNumber BrightnessLevel { get; }
+
+ [Export ("locale", ArgumentSemantic.Copy)]
+ string Locale { get; }
+
+ [Export ("locales", ArgumentSemantic.Copy)]
+ string[] Locales { get; }
+
+ [Export ("powerSavingMode", ArgumentSemantic.Strong)]
+ NSNumber PowerSavingMode { get; }
+
+ [Export ("timeZone", ArgumentSemantic.Copy)]
+ string TimeZone { get; }
}
// @interface DDRUMActionEventRUMEventAttributes : NSObject
@@ -1008,6 +1074,9 @@ interface DDRUMActionEventRUMUser
// @property (readonly, copy, nonatomic) NSDictionary * _Nonnull usrInfo;
[Export ("usrInfo", ArgumentSemantic.Copy)]
NSDictionary UsrInfo { get; }
+
+ [Export ("anonymousId", ArgumentSemantic.Copy)]
+ string AnonymousId { get; }
}
// @interface DDRUMActionEventSession : NSObject
@@ -1139,6 +1208,15 @@ interface DDRUMConfiguration
// @property (copy, nonatomic) NSURL * _Nullable customEndpoint;
[NullAllowed, Export ("customEndpoint", ArgumentSemantic.Copy)]
NSUrl CustomEndpoint { get; set; }
+
+ [Export ("swiftUIViewsPredicate", ArgumentSemantic.Strong)]
+ IDDSwiftUIRUMViewsPredicate SwiftUIViewsPredicate { get; set; }
+
+ [Export ("swiftUIActionsPredicate", ArgumentSemantic.Strong)]
+ IDDSwiftUIRUMActionsPredicate SwiftUIActionsPredicate { get; set; }
+
+ [Export ("trackAnonymousUser")]
+ bool TrackAnonymousUser { get; set; }
}
// @interface DDRUMErrorEvent : NSObject
@@ -1241,6 +1319,12 @@ interface DDRUMErrorEvent
// @property (readonly, nonatomic, strong) DDRUMErrorEventView * _Nonnull view;
[Export ("view", ArgumentSemantic.Strong)]
DDRUMErrorEventView View { get; }
+
+ [Export ("account", ArgumentSemantic.Strong)]
+ DDRUMErrorEventRUMAccount Account { get; }
+
+ [Export ("ddtags", ArgumentSemantic.Copy)]
+ string Ddtags { get; }
}
// @interface DDRUMErrorEventAction : NSObject
@@ -1275,6 +1359,9 @@ interface DDRUMErrorEventApplication
// @property (readonly, copy, nonatomic) NSString * _Nonnull id;
[Export ("id")]
string Id { get; }
+
+ [Export ("currentLocale", ArgumentSemantic.Copy)]
+ string CurrentLocale { get; }
}
// @interface DDRUMErrorEventContainer : NSObject
@@ -1321,6 +1408,9 @@ interface DDRUMErrorEventDD
// @property (readonly, nonatomic, strong) DDRUMErrorEventDDSession * _Nullable session;
[NullAllowed, Export ("session", ArgumentSemantic.Strong)]
DDRUMErrorEventDDSession Session { get; }
+
+ [Export ("sdkName", ArgumentSemantic.Copy)]
+ string SdkName { get; }
}
// @interface DDRUMErrorEventDDConfiguration : NSObject
@@ -1335,6 +1425,9 @@ interface DDRUMErrorEventDDConfiguration
// @property (readonly, nonatomic, strong) NSNumber * _Nonnull sessionSampleRate;
[Export ("sessionSampleRate", ArgumentSemantic.Strong)]
NSNumber SessionSampleRate { get; }
+
+ [Export ("profilingSampleRate", ArgumentSemantic.Strong)]
+ NSNumber ProfilingSampleRate { get; }
}
// @interface DDRUMErrorEventDDSession : NSObject
@@ -1705,6 +1798,24 @@ interface DDRUMErrorEventRUMDevice
// @property (readonly, nonatomic) enum DDRUMErrorEventRUMDeviceRUMDeviceType type;
[Export ("type")]
DDRUMErrorEventRUMDeviceRUMDeviceType Type { get; }
+
+ [Export ("batteryLevel", ArgumentSemantic.Strong)]
+ NSNumber BatteryLevel { get; }
+
+ [Export ("brightnessLevel", ArgumentSemantic.Strong)]
+ NSNumber BrightnessLevel { get; }
+
+ [Export ("locale", ArgumentSemantic.Copy)]
+ string Locale { get; }
+
+ [Export ("locales", ArgumentSemantic.Copy)]
+ string[] Locales { get; }
+
+ [Export ("powerSavingMode", ArgumentSemantic.Strong)]
+ NSNumber PowerSavingMode { get; }
+
+ [Export ("timeZone", ArgumentSemantic.Copy)]
+ string TimeZone { get; }
}
// @interface DDRUMErrorEventRUMEventAttributes : NSObject
@@ -1777,6 +1888,9 @@ interface DDRUMErrorEventRUMUser
// @property (readonly, copy, nonatomic) NSDictionary * _Nonnull usrInfo;
[Export ("usrInfo", ArgumentSemantic.Copy)]
NSDictionary UsrInfo { get; }
+
+ [Export ("anonymousId", ArgumentSemantic.Copy)]
+ string AnonymousId { get; }
}
// @interface DDRUMErrorEventSession : NSObject
@@ -1941,6 +2055,12 @@ interface DDRUMLongTaskEvent
// @property (readonly, nonatomic, strong) DDRUMLongTaskEventView * _Nonnull view;
[Export ("view", ArgumentSemantic.Strong)]
DDRUMLongTaskEventView View { get; }
+
+ [Export ("account", ArgumentSemantic.Strong)]
+ DDRUMLongTaskEventRUMAccount Account { get; }
+
+ [Export ("ddtags", ArgumentSemantic.Copy)]
+ string Ddtags { get; }
}
// @interface DDRUMLongTaskEventAction : NSObject
@@ -1975,6 +2095,9 @@ interface DDRUMLongTaskEventApplication
// @property (readonly, copy, nonatomic) NSString * _Nonnull id;
[Export ("id")]
string Id { get; }
+
+ [Export ("currentLocale", ArgumentSemantic.Copy)]
+ string CurrentLocale { get; }
}
// @interface DDRUMLongTaskEventContainer : NSObject
@@ -2025,6 +2148,12 @@ interface DDRUMLongTaskEventDD
// @property (readonly, nonatomic, strong) DDRUMLongTaskEventDDSession * _Nullable session;
[NullAllowed, Export ("session", ArgumentSemantic.Strong)]
DDRUMLongTaskEventDDSession Session { get; }
+
+ [Export ("profiling", ArgumentSemantic.Strong)]
+ DDRUMLongTaskEventDDProfiling Profiling { get; }
+
+ [Export ("sdkName", ArgumentSemantic.Copy)]
+ string SdkName { get; }
}
// @interface DDRUMLongTaskEventDDConfiguration : NSObject
@@ -2039,6 +2168,9 @@ interface DDRUMLongTaskEventDDConfiguration
// @property (readonly, nonatomic, strong) NSNumber * _Nonnull sessionSampleRate;
[Export ("sessionSampleRate", ArgumentSemantic.Strong)]
NSNumber SessionSampleRate { get; }
+
+ [Export ("profilingSampleRate", ArgumentSemantic.Strong)]
+ NSNumber ProfilingSampleRate { get; }
}
// @interface DDRUMLongTaskEventDDSession : NSObject
@@ -2095,6 +2227,9 @@ interface DDRUMLongTaskEventLongTask
// @property (readonly, nonatomic, strong) NSNumber * _Nullable isFrozenFrame;
[NullAllowed, Export ("isFrozenFrame", ArgumentSemantic.Strong)]
NSNumber IsFrozenFrame { get; }
+
+ [Export ("startTime", ArgumentSemantic.Strong)]
+ NSNumber StartTime { get; }
}
// @interface DDRUMLongTaskEventRUMCITest : NSObject
@@ -2167,6 +2302,24 @@ interface DDRUMLongTaskEventRUMDevice
// @property (readonly, nonatomic) enum DDRUMLongTaskEventRUMDeviceRUMDeviceType type;
[Export ("type")]
DDRUMLongTaskEventRUMDeviceRUMDeviceType Type { get; }
+
+ [Export ("batteryLevel", ArgumentSemantic.Strong)]
+ NSNumber BatteryLevel { get; }
+
+ [Export ("brightnessLevel", ArgumentSemantic.Strong)]
+ NSNumber BrightnessLevel { get; }
+
+ [Export ("locale", ArgumentSemantic.Copy)]
+ string Locale { get; }
+
+ [Export ("locales", ArgumentSemantic.Copy)]
+ string[] Locales { get; }
+
+ [Export ("powerSavingMode", ArgumentSemantic.Strong)]
+ NSNumber PowerSavingMode { get; }
+
+ [Export ("timeZone", ArgumentSemantic.Copy)]
+ string TimeZone { get; }
}
// @interface DDRUMLongTaskEventRUMEventAttributes : NSObject
@@ -2239,6 +2392,9 @@ interface DDRUMLongTaskEventRUMUser
// @property (readonly, copy, nonatomic) NSDictionary * _Nonnull usrInfo;
[Export ("usrInfo", ArgumentSemantic.Copy)]
NSDictionary UsrInfo { get; }
+
+ [Export ("anonymousId", ArgumentSemantic.Copy)]
+ string AnonymousId { get; }
}
// @interface DDRUMLongTaskEventSession : NSObject
@@ -2386,6 +2542,12 @@ interface DDRUMMonitor
// @property (nonatomic) BOOL debug;
[Export ("debug")]
bool Debug { get; set; }
+
+ [Export ("addAttributes:")]
+ void AddAttributes (NSDictionary attributes);
+
+ [Export ("removeAttributesForKeys:")]
+ void RemoveAttributesForKeys (string[] keys);
}
// @interface DDRUMResourceEvent : NSObject
@@ -2480,6 +2642,12 @@ interface DDRUMResourceEvent
// @property (readonly, nonatomic, strong) DDRUMResourceEventView * _Nonnull view;
[Export ("view", ArgumentSemantic.Strong)]
DDRUMResourceEventView View { get; }
+
+ [Export ("account", ArgumentSemantic.Strong)]
+ DDRUMResourceEventRUMAccount Account { get; }
+
+ [Export ("ddtags", ArgumentSemantic.Copy)]
+ string Ddtags { get; }
}
// @interface DDRUMResourceEventAction : NSObject
@@ -2514,6 +2682,9 @@ interface DDRUMResourceEventApplication
// @property (readonly, copy, nonatomic) NSString * _Nonnull id;
[Export ("id")]
string Id { get; }
+
+ [Export ("currentLocale", ArgumentSemantic.Copy)]
+ string CurrentLocale { get; }
}
// @interface DDRUMResourceEventContainer : NSObject
@@ -2576,6 +2747,12 @@ interface DDRUMResourceEventDD
// @property (readonly, copy, nonatomic) NSString * _Nullable traceId;
[NullAllowed, Export ("traceId")]
string TraceId { get; }
+
+ [Export ("parentSpanId", ArgumentSemantic.Copy)]
+ string ParentSpanId { get; }
+
+ [Export ("sdkName", ArgumentSemantic.Copy)]
+ string SdkName { get; }
}
// @interface DDRUMResourceEventDDConfiguration : NSObject
@@ -2590,6 +2767,9 @@ interface DDRUMResourceEventDDConfiguration
// @property (readonly, nonatomic, strong) NSNumber * _Nonnull sessionSampleRate;
[Export ("sessionSampleRate", ArgumentSemantic.Strong)]
NSNumber SessionSampleRate { get; }
+
+ [Export ("profilingSampleRate", ArgumentSemantic.Strong)]
+ NSNumber ProfilingSampleRate { get; }
}
// @interface DDRUMResourceEventDDSession : NSObject
@@ -2700,6 +2880,24 @@ interface DDRUMResourceEventRUMDevice
// @property (readonly, nonatomic) enum DDRUMResourceEventRUMDeviceRUMDeviceType type;
[Export ("type")]
DDRUMResourceEventRUMDeviceRUMDeviceType Type { get; }
+
+ [Export ("batteryLevel", ArgumentSemantic.Strong)]
+ NSNumber BatteryLevel { get; }
+
+ [Export ("brightnessLevel", ArgumentSemantic.Strong)]
+ NSNumber BrightnessLevel { get; }
+
+ [Export ("locale", ArgumentSemantic.Copy)]
+ string Locale { get; }
+
+ [Export ("locales", ArgumentSemantic.Copy)]
+ string[] Locales { get; }
+
+ [Export ("powerSavingMode", ArgumentSemantic.Strong)]
+ NSNumber PowerSavingMode { get; }
+
+ [Export ("timeZone", ArgumentSemantic.Copy)]
+ string TimeZone { get; }
}
// @interface DDRUMResourceEventRUMEventAttributes : NSObject
@@ -2772,6 +2970,9 @@ interface DDRUMResourceEventRUMUser
// @property (readonly, copy, nonatomic) NSDictionary * _Nonnull usrInfo;
[Export ("usrInfo", ArgumentSemantic.Copy)]
NSDictionary UsrInfo { get; }
+
+ [Export ("anonymousId", ArgumentSemantic.Copy)]
+ string AnonymousId { get; }
}
// @interface DDRUMResourceEventResource : NSObject
@@ -2854,6 +3055,15 @@ interface DDRUMResourceEventResource
// @property (copy, nonatomic) NSString * _Nonnull url;
[Export ("url")]
string Url { get; set; }
+
+ [Export ("deliveryType")]
+ DDRUMResourceEventResourceDeliveryType DeliveryType { get; }
+
+ [Export ("protocol", ArgumentSemantic.Copy)]
+ string Protocol { get; }
+
+ [Export ("worker", ArgumentSemantic.Strong)]
+ DDRUMResourceEventResourceWorker Worker { get; }
}
// @interface DDRUMResourceEventResourceConnect : NSObject
@@ -3144,6 +3354,12 @@ interface DDRUMViewEvent
// @property (readonly, nonatomic, strong) DDRUMViewEventView * _Nonnull view;
[Export ("view", ArgumentSemantic.Strong)]
DDRUMViewEventView View { get; }
+
+ [Export ("account", ArgumentSemantic.Strong)]
+ DDRUMViewEventRUMAccount Account { get; }
+
+ [Export ("ddtags", ArgumentSemantic.Copy)]
+ string Ddtags { get; }
}
// @interface DDRUMViewEventApplication : NSObject
@@ -3154,6 +3370,9 @@ interface DDRUMViewEventApplication
// @property (readonly, copy, nonatomic) NSString * _Nonnull id;
[Export ("id")]
string Id { get; }
+
+ [Export ("currentLocale", ArgumentSemantic.Copy)]
+ string CurrentLocale { get; }
}
// @interface DDRUMViewEventContainer : NSObject
@@ -3212,6 +3431,15 @@ interface DDRUMViewEventDD
// @property (readonly, nonatomic, strong) DDRUMViewEventDDSession * _Nullable session;
[NullAllowed, Export ("session", ArgumentSemantic.Strong)]
DDRUMViewEventDDSession Session { get; }
+
+ [Export ("cls", ArgumentSemantic.Strong)]
+ DDRUMViewEventDDCLS Cls { get; }
+
+ [Export ("profiling", ArgumentSemantic.Strong)]
+ DDRUMViewEventDDProfiling Profiling { get; }
+
+ [Export ("sdkName", ArgumentSemantic.Copy)]
+ string SdkName { get; }
}
// @interface DDRUMViewEventDDConfiguration : NSObject
@@ -3230,6 +3458,9 @@ interface DDRUMViewEventDDConfiguration
// @property (readonly, nonatomic, strong) NSNumber * _Nullable startSessionReplayRecordingManually;
[NullAllowed, Export ("startSessionReplayRecordingManually", ArgumentSemantic.Strong)]
NSNumber StartSessionReplayRecordingManually { get; }
+
+ [Export ("profilingSampleRate", ArgumentSemantic.Strong)]
+ NSNumber ProfilingSampleRate { get; }
}
// @interface DDRUMViewEventDDPageStates : NSObject
@@ -3418,6 +3649,24 @@ interface DDRUMViewEventRUMDevice
// @property (readonly, nonatomic) enum DDRUMViewEventRUMDeviceRUMDeviceType type;
[Export ("type")]
DDRUMViewEventRUMDeviceRUMDeviceType Type { get; }
+
+ [Export ("batteryLevel", ArgumentSemantic.Strong)]
+ NSNumber BatteryLevel { get; }
+
+ [Export ("brightnessLevel", ArgumentSemantic.Strong)]
+ NSNumber BrightnessLevel { get; }
+
+ [Export ("locale", ArgumentSemantic.Copy)]
+ string Locale { get; }
+
+ [Export ("locales", ArgumentSemantic.Copy)]
+ string[] Locales { get; }
+
+ [Export ("powerSavingMode", ArgumentSemantic.Strong)]
+ NSNumber PowerSavingMode { get; }
+
+ [Export ("timeZone", ArgumentSemantic.Copy)]
+ string TimeZone { get; }
}
// @interface DDRUMViewEventRUMEventAttributes : NSObject
@@ -3490,6 +3739,9 @@ interface DDRUMViewEventRUMUser
// @property (readonly, copy, nonatomic) NSDictionary * _Nonnull usrInfo;
[Export ("usrInfo", ArgumentSemantic.Copy)]
NSDictionary UsrInfo { get; }
+
+ [Export ("anonymousId", ArgumentSemantic.Copy)]
+ string AnonymousId { get; }
}
// @interface DDRUMViewEventSession : NSObject
@@ -3698,6 +3950,27 @@ interface DDRUMViewEventView
// @property (copy, nonatomic) NSString * _Nonnull url;
[Export ("url")]
string Url { get; set; }
+
+ [Export ("accessibility", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewAccessibility Accessibility { get; }
+
+ [Export ("freezeRate", ArgumentSemantic.Strong)]
+ NSNumber FreezeRate { get; }
+
+ [Export ("interactionToNextViewTime", ArgumentSemantic.Strong)]
+ NSNumber InteractionToNextViewTime { get; }
+
+ [Export ("networkSettledTime", ArgumentSemantic.Strong)]
+ NSNumber NetworkSettledTime { get; }
+
+ [Export ("performance", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformance Performance { get; }
+
+ [Export ("slowFrames", ArgumentSemantic.Copy)]
+ DDRUMViewEventViewSlowFrames[] SlowFrames { get; }
+
+ [Export ("slowFramesRate", ArgumentSemantic.Strong)]
+ NSNumber SlowFramesRate { get; }
}
// @interface DDRUMViewEventViewAction : NSObject
@@ -3938,6 +4211,12 @@ interface DDRUMVitalEvent
// @property (readonly, nonatomic, strong) DDRUMVitalEventVital * _Nonnull vital;
[Export ("vital", ArgumentSemantic.Strong)]
DDRUMVitalEventVital Vital { get; }
+
+ [Export ("account", ArgumentSemantic.Strong)]
+ DDRUMVitalEventRUMAccount Account { get; }
+
+ [Export ("ddtags", ArgumentSemantic.Copy)]
+ string Ddtags { get; }
}
// @interface DDRUMVitalEventApplication : NSObject
@@ -3948,6 +4227,9 @@ interface DDRUMVitalEventApplication
// @property (readonly, copy, nonatomic) NSString * _Nonnull id;
[Export ("id")]
string Id { get; }
+
+ [Export ("currentLocale", ArgumentSemantic.Copy)]
+ string CurrentLocale { get; }
}
// @interface DDRUMVitalEventContainer : NSObject
@@ -3998,6 +4280,9 @@ interface DDRUMVitalEventDD
// @property (readonly, nonatomic, strong) DDRUMVitalEventDDVital * _Nullable vital;
[NullAllowed, Export ("vital", ArgumentSemantic.Strong)]
DDRUMVitalEventDDVital Vital { get; }
+
+ [Export ("sdkName", ArgumentSemantic.Copy)]
+ string SdkName { get; }
}
// @interface DDRUMVitalEventDDConfiguration : NSObject
@@ -4012,6 +4297,9 @@ interface DDRUMVitalEventDDConfiguration
// @property (readonly, nonatomic, strong) NSNumber * _Nonnull sessionSampleRate;
[Export ("sessionSampleRate", ArgumentSemantic.Strong)]
NSNumber SessionSampleRate { get; }
+
+ [Export ("profilingSampleRate", ArgumentSemantic.Strong)]
+ NSNumber ProfilingSampleRate { get; }
}
// @interface DDRUMVitalEventDDSession : NSObject
@@ -4132,6 +4420,24 @@ interface DDRUMVitalEventRUMDevice
// @property (readonly, nonatomic) enum DDRUMVitalEventRUMDeviceRUMDeviceType type;
[Export ("type")]
DDRUMVitalEventRUMDeviceRUMDeviceType Type { get; }
+
+ [Export ("batteryLevel", ArgumentSemantic.Strong)]
+ NSNumber BatteryLevel { get; }
+
+ [Export ("brightnessLevel", ArgumentSemantic.Strong)]
+ NSNumber BrightnessLevel { get; }
+
+ [Export ("locale", ArgumentSemantic.Copy)]
+ string Locale { get; }
+
+ [Export ("locales", ArgumentSemantic.Copy)]
+ string[] Locales { get; }
+
+ [Export ("powerSavingMode", ArgumentSemantic.Strong)]
+ NSNumber PowerSavingMode { get; }
+
+ [Export ("timeZone", ArgumentSemantic.Copy)]
+ string TimeZone { get; }
}
// @interface DDRUMVitalEventRUMEventAttributes : NSObject
@@ -4204,6 +4510,9 @@ interface DDRUMVitalEventRUMUser
// @property (readonly, copy, nonatomic) NSDictionary * _Nonnull usrInfo;
[Export ("usrInfo", ArgumentSemantic.Copy)]
NSDictionary UsrInfo { get; }
+
+ [Export ("anonymousId", ArgumentSemantic.Copy)]
+ string AnonymousId { get; }
}
// @interface DDRUMVitalEventSession : NSObject
@@ -4266,6 +4575,18 @@ interface DDRUMVitalEventVital
// @property (readonly, nonatomic) enum DDRUMVitalEventVitalVitalType type;
[Export ("type")]
DDRUMVitalEventVitalVitalType Type { get; }
+
+ [Export ("vitalDescription", ArgumentSemantic.Copy)]
+ string VitalDescription { get; }
+
+ [Export ("failureReason")]
+ DDRUMVitalEventVitalFailureReason FailureReason { get; }
+
+ [Export ("parentId", ArgumentSemantic.Copy)]
+ string ParentId { get; }
+
+ [Export ("stepType")]
+ DDRUMVitalEventVitalStepType StepType { get; }
}
// @protocol DDServerDateProvider
@@ -4287,39 +4608,7 @@ interface DDServerDateProvider
void SynchronizeWithUpdate (Action update);
}
- // @interface DDSessionReplay : NSObject
- [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc15DDSessionReplay")]
- [DisableDefaultCtor]
- interface DDSessionReplay
- {
- // +(void)enableWith:(DDSessionReplayConfiguration * _Nonnull)configuration;
- [Static]
- [Export ("enableWith:")]
- void EnableWith (DDSessionReplayConfiguration configuration);
- }
- // @interface DDSessionReplayConfiguration : NSObject
- [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc28DDSessionReplayConfiguration")]
- [DisableDefaultCtor]
- interface DDSessionReplayConfiguration
- {
- // @property (nonatomic) float replaySampleRate;
- [Export ("replaySampleRate")]
- float ReplaySampleRate { get; set; }
-
- // @property (nonatomic) enum DDSessionReplayConfigurationPrivacyLevel defaultPrivacyLevel;
- [Export ("defaultPrivacyLevel", ArgumentSemantic.Assign)]
- DDSessionReplayConfigurationPrivacyLevel DefaultPrivacyLevel { get; set; }
-
- // @property (copy, nonatomic) NSURL * _Nullable customEndpoint;
- [NullAllowed, Export ("customEndpoint", ArgumentSemantic.Copy)]
- NSUrl CustomEndpoint { get; set; }
-
- // -(instancetype _Nonnull)initWithReplaySampleRate:(float)replaySampleRate __attribute__((objc_designated_initializer));
- [Export ("initWithReplaySampleRate:")]
- [DesignatedInitializer]
- NativeHandle Constructor (float replaySampleRate);
- }
// @interface DDSite : NSObject
[BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc6DDSite")]
@@ -4355,6 +4644,10 @@ public interface DDSite
[Static]
[Export ("us1_fed")]
DDSite Us1_fed { get; }
+
+ [Static]
+ [Export ("ap2")]
+ DDSite Ap2 { get; }
}
// @interface DDTelemetryConfigurationEvent : NSObject
@@ -4409,6 +4702,9 @@ interface DDTelemetryConfigurationEvent
// @property (readonly, nonatomic, strong) DDTelemetryConfigurationEventView * _Nullable view;
[NullAllowed, Export ("view", ArgumentSemantic.Strong)]
DDTelemetryConfigurationEventView View { get; }
+
+ [Export ("effectiveSampleRate", ArgumentSemantic.Strong)]
+ NSNumber EffectiveSampleRate { get; }
}
// @interface DDTelemetryConfigurationEventAction : NSObject
@@ -4749,6 +5045,39 @@ interface DDTelemetryConfigurationEventTelemetryConfiguration
// @property (readonly, nonatomic) enum DDTelemetryConfigurationEventTelemetryConfigurationViewTrackingStrategy viewTrackingStrategy;
[Export ("viewTrackingStrategy")]
DDTelemetryConfigurationEventTelemetryConfigurationViewTrackingStrategy ViewTrackingStrategy { get; }
+
+ [Export ("invTimeThresholdMs", ArgumentSemantic.Strong)]
+ NSNumber InvTimeThresholdMs { get; }
+
+ [Export ("isMainProcess", ArgumentSemantic.Strong)]
+ NSNumber IsMainProcess { get; }
+
+ [Export ("numberOfDisplays", ArgumentSemantic.Strong)]
+ NSNumber NumberOfDisplays { get; }
+
+ [Export ("sessionPersistence")]
+ DDTelemetryConfigurationEventTelemetryConfigurationSessionPersistence SessionPersistence { get; }
+
+ [Export ("swiftuiActionTrackingEnabled", ArgumentSemantic.Strong)]
+ NSNumber SwiftuiActionTrackingEnabled { get; set; }
+
+ [Export ("swiftuiViewTrackingEnabled", ArgumentSemantic.Strong)]
+ NSNumber SwiftuiViewTrackingEnabled { get; set; }
+
+ [Export ("tnsTimeThresholdMs", ArgumentSemantic.Strong)]
+ NSNumber TnsTimeThresholdMs { get; }
+
+ [Export ("trackAnonymousUser", ArgumentSemantic.Strong)]
+ NSNumber TrackAnonymousUser { get; set; }
+
+ [Export ("trackBfcacheViews", ArgumentSemantic.Strong)]
+ NSNumber TrackBfcacheViews { get; set; }
+
+ [Export ("trackFeatureFlagsForEvents", ArgumentSemantic.Copy)]
+ NSNumber[] TrackFeatureFlagsForEvents { get; }
+
+ [Export ("useAllowedTrackingOrigins", ArgumentSemantic.Strong)]
+ NSNumber UseAllowedTrackingOrigins { get; set; }
}
// @interface DDTelemetryConfigurationEventTelemetryConfigurationForwardConsoleLogs : NSObject
@@ -4891,6 +5220,9 @@ interface DDTelemetryDebugEvent
// @property (readonly, nonatomic, strong) DDTelemetryDebugEventView * _Nullable view;
[NullAllowed, Export ("view", ArgumentSemantic.Strong)]
DDTelemetryDebugEventView View { get; }
+
+ [Export ("effectiveSampleRate", ArgumentSemantic.Strong)]
+ NSNumber EffectiveSampleRate { get; }
}
// @interface DDTelemetryDebugEventAction : NSObject
@@ -5061,6 +5393,9 @@ interface DDTelemetryErrorEvent
// @property (readonly, nonatomic, strong) DDTelemetryErrorEventView * _Nullable view;
[NullAllowed, Export ("view", ArgumentSemantic.Strong)]
DDTelemetryErrorEventView View { get; }
+
+ [Export ("effectiveSampleRate", ArgumentSemantic.Strong)]
+ NSNumber EffectiveSampleRate { get; }
}
// @interface DDTelemetryErrorEventAction : NSObject
@@ -5643,4 +5978,698 @@ partial interface OTSpanContext
[Export ("forEachBaggageItem:")]
void ForEachBaggageItem (Func callback);
}
+
+ // ---------------------------------------------------------------------------------------
+ // Log event model, reached through DDLogsConfiguration.SetEventMapper.
+ //
+ // Objective Sharpie emitted none of this - not the ten DDLogEvent* classes, not the three
+ // enums, and not setEventMapper: itself - so the previous bindings could not redact or drop a
+ // log before it was uploaded, even though RUM had all five of its mappers. Transcribed by hand
+ // from DatadogObjc-Swift.h.
+ //
+ // Only the properties the header declares as writable are bound with setters; the rest are
+ // read-only there, and making them settable here would compile but silently do nothing.
+ // ---------------------------------------------------------------------------------------
+
+ // @interface DDLogEventAttributes : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc20DDLogEventAttributes")]
+ [DisableDefaultCtor]
+ interface DDLogEventAttributes
+ {
+ // @property (copy, nonatomic) NSDictionary * _Nonnull userAttributes;
+ [Export ("userAttributes", ArgumentSemantic.Copy)]
+ NSDictionary UserAttributes { get; set; }
+
+ [Export ("accountInfo", ArgumentSemantic.Strong)]
+ DDLogEventAccountInfo AccountInfo { get; }
+ }
+
+ // @interface DDLogEventBinaryImage : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc21DDLogEventBinaryImage")]
+ [DisableDefaultCtor]
+ interface DDLogEventBinaryImage
+ {
+ [NullAllowed, Export ("arch")]
+ string Arch { get; }
+
+ [Export ("isSystem")]
+ bool IsSystem { get; }
+
+ [NullAllowed, Export ("loadAddress")]
+ string LoadAddress { get; }
+
+ [NullAllowed, Export ("maxAddress")]
+ string MaxAddress { get; }
+
+ [Export ("name")]
+ string Name { get; }
+
+ [Export ("uuid")]
+ string Uuid { get; }
+ }
+
+ // @interface DDLogEventError : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc15DDLogEventError")]
+ [DisableDefaultCtor]
+ interface DDLogEventError
+ {
+ [NullAllowed, Export ("kind")]
+ string Kind { get; set; }
+
+ [NullAllowed, Export ("message")]
+ string Message { get; set; }
+
+ [NullAllowed, Export ("stack")]
+ string Stack { get; set; }
+
+ [Export ("sourceType")]
+ string SourceType { get; set; }
+
+ [NullAllowed, Export ("fingerprint")]
+ string Fingerprint { get; set; }
+
+ [NullAllowed, Export ("binaryImages", ArgumentSemantic.Copy)]
+ DDLogEventBinaryImage[] BinaryImages { get; set; }
+ }
+
+ // @interface DDLogEventCarrierInfo : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc21DDLogEventCarrierInfo")]
+ [DisableDefaultCtor]
+ interface DDLogEventCarrierInfo
+ {
+ [NullAllowed, Export ("carrierName")]
+ string CarrierName { get; }
+
+ [NullAllowed, Export ("carrierISOCountryCode")]
+ string CarrierIsoCountryCode { get; }
+
+ [Export ("carrierAllowsVOIP")]
+ bool CarrierAllowsVoip { get; }
+
+ [Export ("radioAccessTechnology")]
+ DDLogEventRadioAccessTechnology RadioAccessTechnology { get; }
+ }
+
+ // @interface DDLogEventDeviceInfo : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc20DDLogEventDeviceInfo")]
+ [DisableDefaultCtor]
+ interface DDLogEventDeviceInfo
+ {
+ [Export ("brand")]
+ string Brand { get; }
+
+ [Export ("name")]
+ string Name { get; }
+
+ [Export ("model")]
+ string Model { get; }
+
+ [Export ("architecture")]
+ string Architecture { get; }
+ }
+
+ // @interface DDLogEventDd : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc12DDLogEventDd")]
+ [DisableDefaultCtor]
+ interface DDLogEventDd
+ {
+ [Export ("device", ArgumentSemantic.Strong)]
+ DDLogEventDeviceInfo Device { get; }
+ }
+
+ // @interface DDLogEventNetworkConnectionInfo : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc31DDLogEventNetworkConnectionInfo")]
+ [DisableDefaultCtor]
+ interface DDLogEventNetworkConnectionInfo
+ {
+ [Export ("reachability")]
+ DDLogEventReachability Reachability { get; }
+
+ [NullAllowed, Export ("availableInterfaces", ArgumentSemantic.Copy)]
+ NSNumber[] AvailableInterfaces { get; }
+
+ [NullAllowed, Export ("supportsIPv4", ArgumentSemantic.Strong)]
+ NSNumber SupportsIPv4 { get; }
+
+ [NullAllowed, Export ("supportsIPv6", ArgumentSemantic.Strong)]
+ NSNumber SupportsIPv6 { get; }
+
+ [NullAllowed, Export ("isExpensive", ArgumentSemantic.Strong)]
+ NSNumber IsExpensive { get; }
+
+ [NullAllowed, Export ("isConstrained", ArgumentSemantic.Strong)]
+ NSNumber IsConstrained { get; }
+ }
+
+ // @interface DDLogEventOperatingSystem : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc25DDLogEventOperatingSystem")]
+ [DisableDefaultCtor]
+ interface DDLogEventOperatingSystem
+ {
+ [Export ("name")]
+ string Name { get; }
+
+ [Export ("version")]
+ string Version { get; }
+
+ [NullAllowed, Export ("build")]
+ string Build { get; }
+ }
+
+ // @interface DDLogEventUserInfo : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc18DDLogEventUserInfo")]
+ [DisableDefaultCtor]
+ interface DDLogEventUserInfo
+ {
+ [NullAllowed, Export ("id")]
+ string Id { get; }
+
+ [NullAllowed, Export ("name")]
+ string Name { get; }
+
+ [NullAllowed, Export ("email")]
+ string Email { get; }
+
+ [Export ("extraInfo", ArgumentSemantic.Copy)]
+ NSDictionary ExtraInfo { get; set; }
+ }
+
+ // @interface DDLogEvent : NSObject
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc10DDLogEvent")]
+ [DisableDefaultCtor]
+ interface DDLogEvent
+ {
+ [Export ("date", ArgumentSemantic.Copy)]
+ NSDate Date { get; }
+
+ [Export ("status")]
+ DDLogEventStatus Status { get; }
+
+ // One of the two properties worth writing to: redacting a message in place is the common
+ // reason to install a log mapper at all.
+ [Export ("message")]
+ string Message { get; set; }
+
+ [NullAllowed, Export ("error", ArgumentSemantic.Strong)]
+ DDLogEventError Error { get; }
+
+ [Export ("serviceName")]
+ string ServiceName { get; }
+
+ [Export ("environment")]
+ string Environment { get; }
+
+ [Export ("loggerName")]
+ string LoggerName { get; }
+
+ [Export ("loggerVersion")]
+ string LoggerVersion { get; }
+
+ [NullAllowed, Export ("threadName")]
+ string ThreadName { get; }
+
+ [Export ("applicationVersion")]
+ string ApplicationVersion { get; }
+
+ [Export ("applicationBuildNumber")]
+ string ApplicationBuildNumber { get; }
+
+ [NullAllowed, Export ("buildId")]
+ string BuildId { get; }
+
+ [NullAllowed, Export ("variant")]
+ string Variant { get; }
+
+ [Export ("dd", ArgumentSemantic.Strong)]
+ DDLogEventDd Dd { get; }
+
+ [Export ("os", ArgumentSemantic.Strong)]
+ DDLogEventOperatingSystem Os { get; }
+
+ [Export ("userInfo", ArgumentSemantic.Strong)]
+ DDLogEventUserInfo UserInfo { get; }
+
+ [NullAllowed, Export ("networkConnectionInfo", ArgumentSemantic.Strong)]
+ DDLogEventNetworkConnectionInfo NetworkConnectionInfo { get; }
+
+ [NullAllowed, Export ("mobileCarrierInfo", ArgumentSemantic.Strong)]
+ DDLogEventCarrierInfo MobileCarrierInfo { get; }
+
+ [Export ("attributes", ArgumentSemantic.Strong)]
+ DDLogEventAttributes Attributes { get; }
+
+ [NullAllowed, Export ("tags", ArgumentSemantic.Copy)]
+ string[] Tags { get; set; }
+ }
+
+ // ---------------------------------------------------------------------------------------
+ // Types added between dd-sdk-ios 2.17.0 and 2.30.2.
+ //
+ // The SwiftUI predicates come from the SwiftUI auto-tracking added in 2.29.0, the account
+ // types from the account-info API in the same release, and the rest is RUM event-model
+ // detail reachable through the event mappers.
+ // ---------------------------------------------------------------------------------------
+
+ // @interface DDDefaultSwiftUIRUMActionsPredicate
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc35DDDefaultSwiftUIRUMActionsPredicate")]
+ interface DDDefaultSwiftUIRUMActionsPredicate : DDSwiftUIRUMActionsPredicate
+ {
+ [Export ("initWithIsLegacyDetectionEnabled:")]
+ NativeHandle Constructor (bool isLegacyDetectionEnabled);
+
+ [Export ("rumActionWith:")]
+ DDRUMAction RumActionWith (string componentName);
+ }
+
+ // @interface DDDefaultSwiftUIRUMViewsPredicate
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc33DDDefaultSwiftUIRUMViewsPredicate")]
+ interface DDDefaultSwiftUIRUMViewsPredicate : DDSwiftUIRUMViewsPredicate
+ {
+ [Export ("rumViewFor:")]
+ DDRUMView RumViewFor (string extractedViewName);
+ }
+
+ // @interface DDInternalLogger
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc16DDInternalLogger")]
+ interface DDInternalLogger
+ {
+ [Static]
+ [Export ("consolePrint:")]
+ void ConsolePrint (string message);
+
+ [Static]
+ [Export ("telemetryDebugWithId:message:")]
+ void TelemetryDebugWithId (string id, string message);
+
+ [Static]
+ [Export ("telemetryErrorWithId:message:kind:stack:")]
+ void TelemetryErrorWithId (string id, string message, [NullAllowed] string kind, [NullAllowed] string stack);
+ }
+
+ // @interface DDLogEventAccountInfo
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc21DDLogEventAccountInfo")]
+ [DisableDefaultCtor]
+ interface DDLogEventAccountInfo
+ {
+ [Export ("id", ArgumentSemantic.Copy)]
+ string Id { get; }
+
+ [Export ("name", ArgumentSemantic.Copy)]
+ string Name { get; }
+
+ [Export ("extraInfo", ArgumentSemantic.Copy)]
+ NSDictionary ExtraInfo { get; set; }
+ }
+
+ // @interface DDRUMActionEventRUMAccount
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc26DDRUMActionEventRUMAccount")]
+ [DisableDefaultCtor]
+ interface DDRUMActionEventRUMAccount
+ {
+ [Export ("id", ArgumentSemantic.Copy)]
+ string Id { get; }
+
+ [Export ("name", ArgumentSemantic.Copy)]
+ string Name { get; }
+
+ [Export ("accountInfo", ArgumentSemantic.Copy)]
+ NSDictionary AccountInfo { get; set; }
+ }
+
+ // @interface DDRUMErrorEventRUMAccount
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc25DDRUMErrorEventRUMAccount")]
+ [DisableDefaultCtor]
+ interface DDRUMErrorEventRUMAccount
+ {
+ [Export ("id", ArgumentSemantic.Copy)]
+ string Id { get; }
+
+ [Export ("name", ArgumentSemantic.Copy)]
+ string Name { get; }
+
+ [Export ("accountInfo", ArgumentSemantic.Copy)]
+ NSDictionary AccountInfo { get; set; }
+ }
+
+ // @interface DDRUMLongTaskEventDDProfiling
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc29DDRUMLongTaskEventDDProfiling")]
+ [DisableDefaultCtor]
+ interface DDRUMLongTaskEventDDProfiling
+ {
+ [Export ("errorReason")]
+ DDRUMLongTaskEventDDProfilingErrorReason ErrorReason { get; }
+
+ [Export ("status")]
+ DDRUMLongTaskEventDDProfilingStatus Status { get; }
+ }
+
+ // @interface DDRUMLongTaskEventRUMAccount
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc28DDRUMLongTaskEventRUMAccount")]
+ [DisableDefaultCtor]
+ interface DDRUMLongTaskEventRUMAccount
+ {
+ [Export ("id", ArgumentSemantic.Copy)]
+ string Id { get; }
+
+ [Export ("name", ArgumentSemantic.Copy)]
+ string Name { get; }
+
+ [Export ("accountInfo", ArgumentSemantic.Copy)]
+ NSDictionary AccountInfo { get; set; }
+ }
+
+ // @interface DDRUMResourceEventRUMAccount
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc28DDRUMResourceEventRUMAccount")]
+ [DisableDefaultCtor]
+ interface DDRUMResourceEventRUMAccount
+ {
+ [Export ("id", ArgumentSemantic.Copy)]
+ string Id { get; }
+
+ [Export ("name", ArgumentSemantic.Copy)]
+ string Name { get; }
+
+ [Export ("accountInfo", ArgumentSemantic.Copy)]
+ NSDictionary AccountInfo { get; set; }
+ }
+
+ // @interface DDRUMResourceEventResourceWorker
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc32DDRUMResourceEventResourceWorker")]
+ [DisableDefaultCtor]
+ interface DDRUMResourceEventResourceWorker
+ {
+ [Export ("duration", ArgumentSemantic.Strong)]
+ NSNumber Duration { get; }
+
+ [Export ("start", ArgumentSemantic.Strong)]
+ NSNumber Start { get; }
+ }
+
+ // @interface DDRUMViewEventDDCLS
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc19DDRUMViewEventDDCLS")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventDDCLS
+ {
+ [Export ("devicePixelRatio", ArgumentSemantic.Strong)]
+ NSNumber DevicePixelRatio { get; }
+ }
+
+ // @interface DDRUMViewEventDDProfiling
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc25DDRUMViewEventDDProfiling")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventDDProfiling
+ {
+ [Export ("errorReason")]
+ DDRUMViewEventDDProfilingErrorReason ErrorReason { get; }
+
+ [Export ("status")]
+ DDRUMViewEventDDProfilingStatus Status { get; }
+ }
+
+ // @interface DDRUMViewEventRUMAccount
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc24DDRUMViewEventRUMAccount")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventRUMAccount
+ {
+ [Export ("id", ArgumentSemantic.Copy)]
+ string Id { get; }
+
+ [Export ("name", ArgumentSemantic.Copy)]
+ string Name { get; }
+
+ [Export ("accountInfo", ArgumentSemantic.Copy)]
+ NSDictionary AccountInfo { get; set; }
+ }
+
+ // @interface DDRUMViewEventViewAccessibility
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc31DDRUMViewEventViewAccessibility")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewAccessibility
+ {
+ [Export ("assistiveSwitchEnabled", ArgumentSemantic.Strong)]
+ NSNumber AssistiveSwitchEnabled { get; }
+
+ [Export ("assistiveTouchEnabled", ArgumentSemantic.Strong)]
+ NSNumber AssistiveTouchEnabled { get; }
+
+ [Export ("boldTextEnabled", ArgumentSemantic.Strong)]
+ NSNumber BoldTextEnabled { get; }
+
+ [Export ("buttonShapesEnabled", ArgumentSemantic.Strong)]
+ NSNumber ButtonShapesEnabled { get; }
+
+ [Export ("closedCaptioningEnabled", ArgumentSemantic.Strong)]
+ NSNumber ClosedCaptioningEnabled { get; }
+
+ [Export ("grayscaleEnabled", ArgumentSemantic.Strong)]
+ NSNumber GrayscaleEnabled { get; }
+
+ [Export ("increaseContrastEnabled", ArgumentSemantic.Strong)]
+ NSNumber IncreaseContrastEnabled { get; }
+
+ [Export ("invertColorsEnabled", ArgumentSemantic.Strong)]
+ NSNumber InvertColorsEnabled { get; }
+
+ [Export ("monoAudioEnabled", ArgumentSemantic.Strong)]
+ NSNumber MonoAudioEnabled { get; }
+
+ [Export ("onOffSwitchLabelsEnabled", ArgumentSemantic.Strong)]
+ NSNumber OnOffSwitchLabelsEnabled { get; }
+
+ [Export ("reduceMotionEnabled", ArgumentSemantic.Strong)]
+ NSNumber ReduceMotionEnabled { get; }
+
+ [Export ("reduceTransparencyEnabled", ArgumentSemantic.Strong)]
+ NSNumber ReduceTransparencyEnabled { get; }
+
+ [Export ("reducedAnimationsEnabled", ArgumentSemantic.Strong)]
+ NSNumber ReducedAnimationsEnabled { get; }
+
+ [Export ("screenReaderEnabled", ArgumentSemantic.Strong)]
+ NSNumber ScreenReaderEnabled { get; }
+
+ [Export ("shakeToUndoEnabled", ArgumentSemantic.Strong)]
+ NSNumber ShakeToUndoEnabled { get; }
+
+ [Export ("shouldDifferentiateWithoutColor", ArgumentSemantic.Strong)]
+ NSNumber ShouldDifferentiateWithoutColor { get; }
+
+ [Export ("singleAppModeEnabled", ArgumentSemantic.Strong)]
+ NSNumber SingleAppModeEnabled { get; }
+
+ [Export ("speakScreenEnabled", ArgumentSemantic.Strong)]
+ NSNumber SpeakScreenEnabled { get; }
+
+ [Export ("speakSelectionEnabled", ArgumentSemantic.Strong)]
+ NSNumber SpeakSelectionEnabled { get; }
+
+ [Export ("textSize", ArgumentSemantic.Copy)]
+ string TextSize { get; }
+
+ [Export ("videoAutoplayEnabled", ArgumentSemantic.Strong)]
+ NSNumber VideoAutoplayEnabled { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformance
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc29DDRUMViewEventViewPerformance")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformance
+ {
+ [Export ("cls", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformanceCLS Cls { get; }
+
+ [Export ("fbc", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformanceFBC Fbc { get; }
+
+ [Export ("fcp", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformanceFCP Fcp { get; }
+
+ [Export ("fid", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformanceFID Fid { get; }
+
+ [Export ("inp", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformanceINP Inp { get; }
+
+ [Export ("lcp", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformanceLCP Lcp { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformanceCLS
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc32DDRUMViewEventViewPerformanceCLS")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformanceCLS
+ {
+ [Export ("currentRect", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformanceCLSCurrentRect CurrentRect { get; }
+
+ [Export ("previousRect", ArgumentSemantic.Strong)]
+ DDRUMViewEventViewPerformanceCLSPreviousRect PreviousRect { get; }
+
+ [Export ("score", ArgumentSemantic.Strong)]
+ NSNumber Score { get; }
+
+ [Export ("targetSelector", ArgumentSemantic.Copy)]
+ string TargetSelector { get; }
+
+ [Export ("timestamp", ArgumentSemantic.Strong)]
+ NSNumber Timestamp { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformanceCLSCurrentRect
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc43DDRUMViewEventViewPerformanceCLSCurrentRect")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformanceCLSCurrentRect
+ {
+ [Export ("height", ArgumentSemantic.Strong)]
+ NSNumber Height { get; }
+
+ [Export ("width", ArgumentSemantic.Strong)]
+ NSNumber Width { get; }
+
+ [Export ("x", ArgumentSemantic.Strong)]
+ NSNumber X { get; }
+
+ [Export ("y", ArgumentSemantic.Strong)]
+ NSNumber Y { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformanceCLSPreviousRect
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc44DDRUMViewEventViewPerformanceCLSPreviousRect")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformanceCLSPreviousRect
+ {
+ [Export ("height", ArgumentSemantic.Strong)]
+ NSNumber Height { get; }
+
+ [Export ("width", ArgumentSemantic.Strong)]
+ NSNumber Width { get; }
+
+ [Export ("x", ArgumentSemantic.Strong)]
+ NSNumber X { get; }
+
+ [Export ("y", ArgumentSemantic.Strong)]
+ NSNumber Y { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformanceFBC
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc32DDRUMViewEventViewPerformanceFBC")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformanceFBC
+ {
+ [Export ("timestamp", ArgumentSemantic.Strong)]
+ NSNumber Timestamp { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformanceFCP
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc32DDRUMViewEventViewPerformanceFCP")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformanceFCP
+ {
+ [Export ("timestamp", ArgumentSemantic.Strong)]
+ NSNumber Timestamp { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformanceFID
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc32DDRUMViewEventViewPerformanceFID")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformanceFID
+ {
+ [Export ("duration", ArgumentSemantic.Strong)]
+ NSNumber Duration { get; }
+
+ [Export ("targetSelector", ArgumentSemantic.Copy)]
+ string TargetSelector { get; }
+
+ [Export ("timestamp", ArgumentSemantic.Strong)]
+ NSNumber Timestamp { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformanceINP
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc32DDRUMViewEventViewPerformanceINP")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformanceINP
+ {
+ [Export ("duration", ArgumentSemantic.Strong)]
+ NSNumber Duration { get; }
+
+ [Export ("targetSelector", ArgumentSemantic.Copy)]
+ string TargetSelector { get; }
+
+ [Export ("timestamp", ArgumentSemantic.Strong)]
+ NSNumber Timestamp { get; }
+ }
+
+ // @interface DDRUMViewEventViewPerformanceLCP
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc32DDRUMViewEventViewPerformanceLCP")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewPerformanceLCP
+ {
+ [Export ("resourceUrl", ArgumentSemantic.Copy)]
+ string ResourceUrl { get; set; }
+
+ [Export ("targetSelector", ArgumentSemantic.Copy)]
+ string TargetSelector { get; }
+
+ [Export ("timestamp", ArgumentSemantic.Strong)]
+ NSNumber Timestamp { get; }
+ }
+
+ // @interface DDRUMViewEventViewSlowFrames
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc28DDRUMViewEventViewSlowFrames")]
+ [DisableDefaultCtor]
+ interface DDRUMViewEventViewSlowFrames
+ {
+ [Export ("duration", ArgumentSemantic.Strong)]
+ NSNumber Duration { get; }
+
+ [Export ("start", ArgumentSemantic.Strong)]
+ NSNumber Start { get; }
+ }
+
+ // @interface DDRUMVitalEventRUMAccount
+ [BaseType (typeof(NSObject), Name = "_TtC11DatadogObjc25DDRUMVitalEventRUMAccount")]
+ [DisableDefaultCtor]
+ interface DDRUMVitalEventRUMAccount
+ {
+ [Export ("id", ArgumentSemantic.Copy)]
+ string Id { get; }
+
+ [Export ("name", ArgumentSemantic.Copy)]
+ string Name { get; }
+
+ [Export ("accountInfo", ArgumentSemantic.Copy)]
+ NSDictionary AccountInfo { get; set; }
+ }
+
+ partial interface IDDSwiftUIRUMActionsPredicate {}
+
+ // @protocol DDSwiftUIRUMActionsPredicate
+ // [Model] like the UIKit predicates, so an app can subclass the generated class instead of
+ // implementing the interface.
+ [Model, Protocol (Name = "_TtP11DatadogObjc28DDSwiftUIRUMActionsPredicate_")]
+ [BaseType (typeof(NSObject))]
+ interface DDSwiftUIRUMActionsPredicate
+ {
+ // @required -(DDRUMAction * _Nullable)rumActionWith:(NSString * _Nonnull)componentName;
+ [Abstract]
+ [Export ("rumActionWith:")]
+ [return: NullAllowed]
+ DDRUMAction RumActionWith (string componentName);
+ }
+
+ partial interface IDDSwiftUIRUMViewsPredicate {}
+
+ // @protocol DDSwiftUIRUMViewsPredicate
+ // [Model] like the UIKit predicates, so an app can subclass the generated class instead of
+ // implementing the interface.
+ [Model, Protocol (Name = "_TtP11DatadogObjc26DDSwiftUIRUMViewsPredicate_")]
+ [BaseType (typeof(NSObject))]
+ interface DDSwiftUIRUMViewsPredicate
+ {
+ // @required -(DDRUMView * _Nullable)rumViewFor:(NSString * _Nonnull)extractedViewName;
+ [Abstract]
+ [Export ("rumViewFor:")]
+ [return: NullAllowed]
+ DDRUMView RumViewFor (string extractedViewName);
+ }
}
diff --git a/src/DatadogNet.Objc.iOS/StructsAndEnums.cs b/src/DatadogNet.Objc.iOS/StructsAndEnums.cs
index 9267697..19c8674 100644
--- a/src/DatadogNet.Objc.iOS/StructsAndEnums.cs
+++ b/src/DatadogNet.Objc.iOS/StructsAndEnums.cs
@@ -938,13 +938,6 @@ public enum DDSDKVerbosityLevel : long
Critical = 4
}
- [Native]
- public enum DDSessionReplayConfigurationPrivacyLevel : long
- {
- Allow = 0,
- Mask = 1,
- MaskUserInput = 2
- }
[Native]
public enum DDTelemetryConfigurationEventSource : long
@@ -1033,4 +1026,172 @@ public enum DDUploadFrequency : long
Average = 1,
Rare = 2
}
+
+ // The log-event model reached by DDLogsConfiguration.SetEventMapper. Objective Sharpie omitted
+ // the whole family, so the previous bindings had no way to inspect or redact a log before
+ // upload; these are transcribed from DatadogObjc-Swift.h.
+
+ [Native]
+ public enum DDLogEventStatus : long
+ {
+ Debug = 0,
+ Info = 1,
+ Notice = 2,
+ Warn = 3,
+ Error = 4,
+ Critical = 5,
+ Emergency = 6
+ }
+
+ [Native]
+ public enum DDLogEventReachability : long
+ {
+ Yes = 0,
+ Maybe = 1,
+ No = 2
+ }
+
+ [Native]
+ public enum DDLogEventRadioAccessTechnology : long
+ {
+ Gprs = 0,
+ Edge = 1,
+ Wcdma = 2,
+ Hsdpa = 3,
+ Hsupa = 4,
+ Cdma1x = 5,
+ CdmaEvdoRev0 = 6,
+ CdmaEvdoRevA = 7,
+ CdmaEvdoRevB = 8,
+ Ehrpd = 9,
+ Lte = 10,
+ Unknown = 11
+ }
+
+ /// Network interface kinds reported in DDLogEventNetworkConnectionInfo.AvailableInterfaces.
+ ///
+ /// That property is an NSNumber[] because Objective-C has no typed enum arrays, so the
+ /// values only mean anything once cast to this.
+ ///
+ [Native]
+ public enum DDLogEventInterface : long
+ {
+ Wifi = 0,
+ WiredEthernet = 1,
+ Cellular = 2,
+ Loopback = 3,
+ Other = 4
+ }
+
+ // ---------------------------------------------------------------------------------------
+ // Added by dd-sdk-ios 2.30.2. Mostly RUM event-model detail reached through the event
+ // mappers; DDCoreLoggerLevel belongs to the internal-telemetry logger added in 2.19.0.
+ // ---------------------------------------------------------------------------------------
+
+ [Native]
+ public enum DDCoreLoggerLevel : long
+ {
+ Debug = 0,
+ Warn = 1,
+ Error = 2,
+ Critical = 3
+ }
+
+ [Native]
+ public enum DDRUMActionEventDDActionNameSource : long
+ {
+ None = 0,
+ CustomAttribute = 1,
+ MaskPlaceholder = 2,
+ StandardAttribute = 3,
+ TextContent = 4,
+ MaskDisallowed = 5,
+ Blank = 6
+ }
+
+ [Native]
+ public enum DDRUMLongTaskEventDDProfilingErrorReason : long
+ {
+ None = 0,
+ NotSupportedByBrowser = 1,
+ FailedToLazyLoad = 2,
+ MissingDocumentPolicyHeader = 3,
+ UnexpectedException = 4
+ }
+
+ [Native]
+ public enum DDRUMLongTaskEventDDProfilingStatus : long
+ {
+ None = 0,
+ Starting = 1,
+ Running = 2,
+ Stopped = 3,
+ Error = 4
+ }
+
+ [Native]
+ public enum DDRUMResourceEventResourceDeliveryType : long
+ {
+ None = 0,
+ Cache = 1,
+ NavigationalPrefetch = 2,
+ Other = 3
+ }
+
+ [Native]
+ public enum DDRUMViewEventDDProfilingErrorReason : long
+ {
+ None = 0,
+ NotSupportedByBrowser = 1,
+ FailedToLazyLoad = 2,
+ MissingDocumentPolicyHeader = 3,
+ UnexpectedException = 4
+ }
+
+ [Native]
+ public enum DDRUMViewEventDDProfilingStatus : long
+ {
+ None = 0,
+ Starting = 1,
+ Running = 2,
+ Stopped = 3,
+ Error = 4
+ }
+
+ [Native]
+ public enum DDRUMVitalEventVitalFailureReason : long
+ {
+ None = 0,
+ Error = 1,
+ Abandoned = 2,
+ Other = 3
+ }
+
+ [Native]
+ public enum DDRUMVitalEventVitalStepType : long
+ {
+ None = 0,
+ Start = 1,
+ Update = 2,
+ Retry = 3,
+ End = 4
+ }
+
+ [Native]
+ public enum DDTelemetryConfigurationEventTelemetryConfigurationSessionPersistence : long
+ {
+ None = 0,
+ LocalStorage = 1,
+ Cookie = 2
+ }
+
+ [Native]
+ public enum DDTelemetryConfigurationEventTelemetryConfigurationTrackFeatureFlagsForEvents : long
+ {
+ None = 0,
+ Vital = 1,
+ Resource = 2,
+ Action = 3,
+ LongTask = 4
+ }
}
diff --git a/src/DatadogNet.SessionReplay.iOS/ApiDefinitions.cs b/src/DatadogNet.SessionReplay.iOS/ApiDefinitions.cs
index ba1ca6c..7960733 100644
--- a/src/DatadogNet.SessionReplay.iOS/ApiDefinitions.cs
+++ b/src/DatadogNet.SessionReplay.iOS/ApiDefinitions.cs
@@ -1,11 +1,27 @@
+using System;
using DatadogSessionReplay;
using Foundation;
using ObjCRuntime;
+using UIKit;
namespace DatadogSessionReplay
{
+ // NOTE ON RUNTIME NAMES
+ //
+ // Through 2.17.0 these classes were declared SWIFT_CLASS("_TtC20DatadogSessionReplay..."),
+ // which sets objc_runtime_name to the mangled Swift symbol, so the binding had to spell that
+ // mangled name out in [BaseType (Name = ...)].
+ //
+ // From 2.19.0 they are declared SWIFT_CLASS_NAMED("objc_SessionReplay"), which expands to
+ // swift_name(...) only - a compile-time alias - and leaves the runtime name as the plain
+ // @interface name. The binary confirms it: it exports _OBJC_CLASS_$_DDSessionReplay, not
+ // _OBJC_CLASS_$__TtC20DatadogSessionReplay15DDSessionReplay.
+ //
+ // So Name= is deliberately absent here. Keeping the old mangled name would compile happily and
+ // then fail to resolve the class at runtime.
+
// @interface DDSessionReplay : NSObject
- [BaseType (typeof(NSObject), Name = "_TtC20DatadogSessionReplay15DDSessionReplay")]
+ [BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface DDSessionReplay
{
@@ -13,10 +29,22 @@ interface DDSessionReplay
[Static]
[Export ("enableWith:")]
void EnableWith (DDSessionReplayConfiguration configuration);
+
+ // +(void)startRecording;
+ // Only needed when StartRecordingImmediately was set to false; recording otherwise begins
+ // as soon as the feature is enabled.
+ [Static]
+ [Export ("startRecording")]
+ void StartRecording ();
+
+ // +(void)stopRecording;
+ [Static]
+ [Export ("stopRecording")]
+ void StopRecording ();
}
// @interface DDSessionReplayConfiguration : NSObject
- [BaseType (typeof(NSObject), Name = "_TtC20DatadogSessionReplay28DDSessionReplayConfiguration")]
+ [BaseType (typeof(NSObject))]
[DisableDefaultCtor]
interface DDSessionReplayConfiguration
{
@@ -24,17 +52,97 @@ interface DDSessionReplayConfiguration
[Export ("replaySampleRate")]
float ReplaySampleRate { get; set; }
- // @property (nonatomic) enum DDSessionReplayConfigurationPrivacyLevel defaultPrivacyLevel;
- [Export ("defaultPrivacyLevel", ArgumentSemantic.Assign)]
- DDSessionReplayConfigurationPrivacyLevel DefaultPrivacyLevel { get; set; }
+ // @property (nonatomic) enum DDTextAndInputPrivacyLevel textAndInputPrivacyLevel;
+ [Export ("textAndInputPrivacyLevel", ArgumentSemantic.Assign)]
+ DDTextAndInputPrivacyLevel TextAndInputPrivacyLevel { get; set; }
+
+ // @property (nonatomic) enum DDImagePrivacyLevel imagePrivacyLevel;
+ [Export ("imagePrivacyLevel", ArgumentSemantic.Assign)]
+ DDImagePrivacyLevel ImagePrivacyLevel { get; set; }
+
+ // @property (nonatomic) enum DDTouchPrivacyLevel touchPrivacyLevel;
+ [Export ("touchPrivacyLevel", ArgumentSemantic.Assign)]
+ DDTouchPrivacyLevel TouchPrivacyLevel { get; set; }
+
+ // @property (nonatomic) BOOL startRecordingImmediately;
+ [Export ("startRecordingImmediately")]
+ bool StartRecordingImmediately { get; set; }
// @property (copy, nonatomic) NSURL * _Nullable customEndpoint;
[NullAllowed, Export ("customEndpoint", ArgumentSemantic.Copy)]
NSUrl CustomEndpoint { get; set; }
- // -(instancetype _Nonnull)initWithReplaySampleRate:(float)replaySampleRate __attribute__((objc_designated_initializer));
- [Export ("initWithReplaySampleRate:")]
+ // @property (copy, nonatomic) NSDictionary * _Nonnull featureFlags;
+ [Export ("featureFlags", ArgumentSemantic.Copy)]
+ NSDictionary FeatureFlags { get; set; }
+
+ // @property (nonatomic) enum DDSessionReplayConfigurationPrivacyLevel defaultPrivacyLevel
+ // SWIFT_DEPRECATED_MSG("... Use the new privacy levels instead.");
+ [Export ("defaultPrivacyLevel", ArgumentSemantic.Assign)]
+ DDSessionReplayConfigurationPrivacyLevel DefaultPrivacyLevel { get; set; }
+
+ // -(instancetype)initWithReplaySampleRate:(float)replaySampleRate
+ // textAndInputPrivacyLevel:(enum DDTextAndInputPrivacyLevel)textAndInputPrivacyLevel
+ // imagePrivacyLevel:(enum DDImagePrivacyLevel)imagePrivacyLevel
+ // touchPrivacyLevel:(enum DDTouchPrivacyLevel)touchPrivacyLevel;
+ [Export ("initWithReplaySampleRate:textAndInputPrivacyLevel:imagePrivacyLevel:touchPrivacyLevel:")]
[DesignatedInitializer]
+ NativeHandle Constructor (float replaySampleRate, DDTextAndInputPrivacyLevel textAndInputPrivacyLevel, DDImagePrivacyLevel imagePrivacyLevel, DDTouchPrivacyLevel touchPrivacyLevel);
+
+ // ... featureFlags:(NSDictionary * _Nullable)featureFlags;
+ [Export ("initWithReplaySampleRate:textAndInputPrivacyLevel:imagePrivacyLevel:touchPrivacyLevel:featureFlags:")]
+ NativeHandle Constructor (float replaySampleRate, DDTextAndInputPrivacyLevel textAndInputPrivacyLevel, DDImagePrivacyLevel imagePrivacyLevel, DDTouchPrivacyLevel touchPrivacyLevel, [NullAllowed] NSDictionary featureFlags);
+
+ // -(instancetype)initWithReplaySampleRate:(float)replaySampleRate
+ // SWIFT_DEPRECATED_MSG("... Use init(replaySampleRate:textAndInputPrivacyLevel:...) instead.");
+ //
+ // Still bound so code written against 2.17.0 keeps compiling. It applies the SDK's own
+ // defaults for the three fine-grained levels.
+ [Export ("initWithReplaySampleRate:")]
NativeHandle Constructor (float replaySampleRate);
}
+
+ // @interface DDSessionReplayPrivacyOverrides : NSObject
+ //
+ // Per-view privacy, overriding the session-wide levels. Reached through the UIView category
+ // below rather than constructed directly in normal use.
+ [BaseType (typeof(NSObject))]
+ [DisableDefaultCtor]
+ interface DDSessionReplayPrivacyOverrides
+ {
+ // -(instancetype _Nonnull)initWithView:(UIView * _Nonnull)view;
+ [Export ("initWithView:")]
+ [DesignatedInitializer]
+ NativeHandle Constructor (UIView view);
+
+ // @property (nonatomic) enum DDTextAndInputPrivacyLevelOverride textAndInputPrivacy;
+ [Export ("textAndInputPrivacy", ArgumentSemantic.Assign)]
+ DDTextAndInputPrivacyLevelOverride TextAndInputPrivacy { get; set; }
+
+ // @property (nonatomic) enum DDImagePrivacyLevelOverride imagePrivacy;
+ [Export ("imagePrivacy", ArgumentSemantic.Assign)]
+ DDImagePrivacyLevelOverride ImagePrivacy { get; set; }
+
+ // @property (nonatomic) enum DDTouchPrivacyLevelOverride touchPrivacy;
+ [Export ("touchPrivacy", ArgumentSemantic.Assign)]
+ DDTouchPrivacyLevelOverride TouchPrivacy { get; set; }
+
+ // @property (strong, nonatomic) NSNumber * _Nullable hide;
+ // NSNumber rather than bool: nil means "inherit", which a bool cannot express.
+ [NullAllowed, Export ("hide", ArgumentSemantic.Strong)]
+ NSNumber Hide { get; set; }
+ }
+
+ // @interface UIView (SWIFT_EXTENSION(DatadogSessionReplay))
+ //
+ // A category on UIView, so it is bound as a Category rather than as a type of its own. This is
+ // how per-view privacy is set: view.DdSessionReplayPrivacyOverrides().ImagePrivacy = ...
+ [Category]
+ [BaseType (typeof(UIView))]
+ interface UIView_DatadogSessionReplay
+ {
+ // @property (readonly, nonatomic, strong) DDSessionReplayPrivacyOverrides * _Nonnull ddSessionReplayPrivacyOverrides;
+ [Export ("ddSessionReplayPrivacyOverrides")]
+ DDSessionReplayPrivacyOverrides GetDdSessionReplayPrivacyOverrides ();
+ }
}
diff --git a/src/DatadogNet.SessionReplay.iOS/StructsAndEnums.cs b/src/DatadogNet.SessionReplay.iOS/StructsAndEnums.cs
index 2fffa02..b3dae5f 100644
--- a/src/DatadogNet.SessionReplay.iOS/StructsAndEnums.cs
+++ b/src/DatadogNet.SessionReplay.iOS/StructsAndEnums.cs
@@ -1,7 +1,28 @@
using ObjCRuntime;
+
namespace DatadogSessionReplay
{
+ /// Session-wide masking for images.
+ [Native]
+ public enum DDImagePrivacyLevel : long
+ {
+ MaskNonBundledOnly = 0,
+ MaskAll = 1,
+ MaskNone = 2
+ }
+
+ /// Per-view override of . None inherits the session-wide level.
+ [Native]
+ public enum DDImagePrivacyLevelOverride : long
+ {
+ None = 0,
+ MaskNone = 1,
+ MaskNonBundledOnly = 2,
+ MaskAll = 3
+ }
+
+ /// The single session-wide privacy level used before 2.19.0. Deprecated upstream in favour of the three fine-grained levels; still accepted for now.
[Native]
public enum DDSessionReplayConfigurationPrivacyLevel : long
{
@@ -9,4 +30,41 @@ public enum DDSessionReplayConfigurationPrivacyLevel : long
Mask = 1,
MaskUserInput = 2
}
+
+ /// Session-wide masking for text and user input.
+ [Native]
+ public enum DDTextAndInputPrivacyLevel : long
+ {
+ MaskSensitiveInputs = 0,
+ MaskAllInputs = 1,
+ MaskAll = 2
+ }
+
+ /// Per-view override of . None inherits the session-wide level.
+ [Native]
+ public enum DDTextAndInputPrivacyLevelOverride : long
+ {
+ None = 0,
+ MaskSensitiveInputs = 1,
+ MaskAllInputs = 2,
+ MaskAll = 3
+ }
+
+ /// Session-wide masking for touch interactions.
+ [Native]
+ public enum DDTouchPrivacyLevel : long
+ {
+ Show = 0,
+ Hide = 1
+ }
+
+ /// Per-view override of . None inherits the session-wide level.
+ [Native]
+ public enum DDTouchPrivacyLevelOverride : long
+ {
+ None = 0,
+ Show = 1,
+ Hide = 2
+ }
+
}
diff --git a/tests/DatadogNet.iOS.DeviceTests/SmokeTests.cs b/tests/DatadogNet.iOS.DeviceTests/SmokeTests.cs
index 49b51ad..dd8affe 100644
--- a/tests/DatadogNet.iOS.DeviceTests/SmokeTests.cs
+++ b/tests/DatadogNet.iOS.DeviceTests/SmokeTests.cs
@@ -3,16 +3,14 @@
using DatadogCrashReporting;
using DatadogInternal;
using DatadogObjc;
-// DatadogObjc declares its own DDSessionReplay, DDSessionReplayConfiguration and privacy-level
-// enum, wrapping different native classes from the identically named ones here
-// (_TtC11DatadogObjc15DDSessionReplay against _TtC20DatadogSessionReplay15DDSessionReplay). Both
-// work; importing both namespaces unqualified is what does not. These tests deliberately drive the
-// DatadogSessionReplay ones, so that package's own binding is exercised rather than only the
-// façade's - the sample shows the DatadogObjc route an app would normally take.
-using SessionReplay = DatadogSessionReplay;
+// Session Replay lives only in DatadogSessionReplay from dd-sdk-ios 2.19.0 onwards; DatadogObjc
+// used to declare a parallel set of DD* Session Replay types and no longer does, so there is
+// nothing left to disambiguate.
+using DatadogSessionReplay;
using DatadogWebViewTracking;
using Foundation;
using ObjCRuntime;
+using UIKit;
namespace DatadogNet.iOS.DeviceTests;
@@ -60,11 +58,17 @@ public static class SmokeTests
new("enables Logs and writes every level", EnablesLogsAndWritesEveryLevel),
new("enables Trace", EnablesTrace),
new("enables Session Replay", EnablesSessionReplay),
+ new("applies per-view Session Replay privacy overrides", SessionReplayPrivacyOverridesApply),
+ new("sets and clears account and user info", SetsAccountInfo),
+ new("exposes the new RUM attribute APIs and the AP2 site", NewRumAndSiteApis),
new("enables crash reporting", EnablesCrashReporting),
new("constructs a URLSession delegate for first-party tracing", ConstructsUrlSessionDelegate),
new("exposes WebView tracking", ExposesWebViewTracking),
new("exposes PLCrashReporter", ExposesCrashReporter),
new("drives RUM and Logs through the ergonomic overloads", ErgonomicOverloadsWork),
+ new("invokes a RUM event mapper", EventMapperIsInvoked),
+ new("invokes a Logs event mapper and redacts a message", LogEventMapperRedacts),
+ new("instruments a URLSession delegate by type", InstrumentsUrlSessionByType),
new("stops the RUM session and the SDK instance", StopsCleanly),
];
@@ -133,6 +137,110 @@ private static void ErgonomicOverloadsWork()
Report("view scopes, attribute conversion, logger and consent helpers all behaved");
}
+ /// Counts mapper invocations, incremented from the blocks registered when features are enabled.
+ private static int viewEventsMapped;
+ private static int actionEventsMapped;
+ private static int logEventsMapped;
+ private static int logEventsRedacted;
+
+ ///
+ /// An NSUrlSession delegate for to instrument.
+ ///
+ ///
+ /// [Register] matters: DDURLSessionInstrumentation takes an Objective-C Class, so the type has
+ /// to be visible to the Objective-C runtime for the lookup to resolve to anything.
+ ///
+ [Register(nameof(InstrumentedSessionDelegate))]
+ private sealed class InstrumentedSessionDelegate : NSUrlSessionDataDelegate
+ {
+ }
+
+ ///
+ /// Checks that the RUM event mappers actually fire, and that an event can be handed back to
+ /// Swift from managed code.
+ ///
+ ///
+ /// Mappers are how an app redacts or drops events before they are uploaded, so they are the
+ /// mechanism behind every "scrub the PII out of this" requirement. They are also the only part
+ /// of the binding that passes a managed delegate into Swift and gets a Swift object back out,
+ /// so if block marshalling is wrong anywhere it is wrong here - and the failure mode is a crash
+ /// inside the SDK's event-writing path, long after the call that registered the mapper.
+ ///
+ /// The mappers are registered on the real configuration in , before
+ /// RUM is enabled, because that is the only time they can be set. This check then runs after
+ /// has produced events and asserts the blocks were actually reached.
+ ///
+ ///
+ private static void EventMapperIsInvoked()
+ {
+ // Events are mapped on the SDK's own queue as they are written, not synchronously with the
+ // call that produced them, so give that queue a moment before concluding anything.
+ var deadline = DateTime.UtcNow.AddSeconds(5);
+ while (DateTime.UtcNow < deadline && (viewEventsMapped == 0 || actionEventsMapped == 0))
+ {
+ Thread.Sleep(100);
+ }
+
+ Assert(viewEventsMapped > 0, "The view event mapper was never invoked.");
+ Assert(actionEventsMapped > 0, "The action event mapper was never invoked.");
+
+ Report($"mappers invoked: {viewEventsMapped} view, {actionEventsMapped} action");
+ }
+
+ ///
+ /// Checks that a Logs event mapper fires and that a rewritten message survives back into Swift.
+ ///
+ private static void LogEventMapperRedacts()
+ {
+ var deadline = DateTime.UtcNow.AddSeconds(5);
+ while (DateTime.UtcNow < deadline && logEventsRedacted == 0)
+ {
+ Thread.Sleep(100);
+ }
+
+ Assert(logEventsMapped > 0, "The log event mapper was never invoked.");
+ Assert(logEventsRedacted > 0, "The log event mapper never saw the message it was meant to redact.");
+
+ Report($"log events mapped: {logEventsMapped}, redacted: {logEventsRedacted}");
+ }
+
+ ///
+ /// Checks the type-based URLSession instrumentation helpers.
+ ///
+ ///
+ /// This is the API Datadog documents for automatic resource tracking, and the raw binding takes
+ /// the delegate class as a bare IntPtr - a signature that accepts IntPtr.Zero happily and then
+ /// instruments nothing. The helpers resolve the Objective-C class from a managed Type and throw
+ /// if it does not exist, which is what this checks in both directions.
+ ///
+ private static void InstrumentsUrlSessionByType()
+ {
+ DDURLSessionInstrumentation.Enable();
+
+ var configuration = DDURLSessionInstrumentationConfiguration.Create();
+ Assert(configuration.DelegateClass != IntPtr.Zero, "The configuration resolved a null delegate class.");
+ Assert(
+ configuration.DelegateType == typeof(InstrumentedSessionDelegate),
+ $"DelegateType round-tripped to {configuration.DelegateType?.Name ?? "null"}.");
+
+ // A type the Objective-C runtime has never heard of must be rejected rather than silently
+ // instrumenting nothing.
+ var rejected = false;
+ try
+ {
+ DDURLSessionInstrumentation.Enable(typeof(SmokeTests));
+ }
+ catch (ArgumentException)
+ {
+ rejected = true;
+ }
+
+ Assert(rejected, "A non-Objective-C type was accepted as a session delegate.");
+
+ DDURLSessionInstrumentation.Disable();
+ Report("instrumented and disabled a URLSession delegate by type");
+ }
+
/// Every framework shipped as a dynamic framework, which is all but CrashReporter.
private static readonly string[] DynamicFrameworks =
[
@@ -247,6 +355,20 @@ private static void EnablesRum()
UiKitActionsPredicate = new DDDefaultUIKitRUMActionsPredicate(),
};
+ // Registered before EnableWith, which is the only point at which mappers can be set.
+ // Returning the event unchanged is the identity case; returning null would drop it.
+ configuration.SetViewEventMapper(view =>
+ {
+ Interlocked.Increment(ref viewEventsMapped);
+ return view;
+ });
+
+ configuration.SetActionEventMapper(action =>
+ {
+ Interlocked.Increment(ref actionEventsMapped);
+ return action;
+ });
+
DDRUM.EnableWith(configuration);
Assert(DDRUMMonitor.Shared is not null, "DDRUMMonitor.Shared was null after enabling RUM.");
@@ -275,7 +397,26 @@ private static void DrivesRum()
private static void EnablesLogsAndWritesEveryLevel()
{
- DDLogs.EnableWith(new DDLogsConfiguration(LocalEndpoint));
+ var logsConfiguration = new DDLogsConfiguration(LocalEndpoint);
+
+ // Registered before EnableWith, the only point at which a mapper can be set. Neither the
+ // DDLogEvent model nor setEventMapper: was bound before - Objective Sharpie omitted the
+ // whole family - so this is the first release in which a log can be redacted or dropped
+ // before upload.
+ logsConfiguration.SetEventMapper(logEvent =>
+ {
+ Interlocked.Increment(ref logEventsMapped);
+
+ if (logEvent.Message.Contains("secret", StringComparison.Ordinal))
+ {
+ logEvent.Message = "[redacted]";
+ Interlocked.Increment(ref logEventsRedacted);
+ }
+
+ return logEvent;
+ });
+
+ DDLogs.EnableWith(logsConfiguration);
// The designated initializer takes all eight settings; there is no parameterless form.
var logger = DDLogger.CreateWith(new DDLoggerConfiguration(
@@ -302,6 +443,9 @@ private static void EnablesLogsAndWritesEveryLevel()
logger.RemoveTagWithKey("suite");
logger.RemoveAttributeForKey("attempt");
+ // Picked up by the mapper registered above and rewritten to "[redacted]".
+ logger.Info("this contains a secret value");
+
Report("wrote six levels and round-tripped a tag and an attribute");
}
@@ -333,15 +477,89 @@ private static void EnablesTrace()
private static void EnablesSessionReplay()
{
- var configuration = new SessionReplay.DDSessionReplayConfiguration(replaySampleRate: 100)
+
+ // The three fine-grained levels replaced the single defaultPrivacyLevel in 2.19.0, and the
+ // initializer requires them, so the choice cannot be left implicit.
+ var configuration = new DDSessionReplayConfiguration(
+ replaySampleRate: 100,
+ textAndInputPrivacyLevel: DDTextAndInputPrivacyLevel.MaskAll,
+ imagePrivacyLevel: DDImagePrivacyLevel.MaskAll,
+ touchPrivacyLevel: DDTouchPrivacyLevel.Hide)
{
- DefaultPrivacyLevel = SessionReplay.DDSessionReplayConfigurationPrivacyLevel.Mask,
CustomEndpoint = LocalEndpoint,
+ // Recording is started explicitly below rather than on enable, which is what an app
+ // does when it wants replay only after consent or a particular screen.
+ StartRecordingImmediately = false,
};
- SessionReplay.DDSessionReplay.EnableWith(configuration);
+ DDSessionReplay.EnableWith(configuration);
+
+ Assert(
+ configuration.TextAndInputPrivacyLevel == DDTextAndInputPrivacyLevel.MaskAll,
+ "textAndInputPrivacyLevel did not round-trip.");
+ Assert(
+ configuration.TouchPrivacyLevel == DDTouchPrivacyLevel.Hide,
+ "touchPrivacyLevel did not round-trip.");
+
+ DDSessionReplay.StartRecording();
+ DDSessionReplay.StopRecording();
+
+ Report("Session Replay enabled with fine-grained privacy, then started and stopped");
+ }
+
+ ///
+ /// Per-view privacy overrides, added in 2.19.0 as a category on UIView.
+ ///
+ private static void SessionReplayPrivacyOverridesApply()
+ {
+ var view = new UIView();
+ var overrides = view.GetDdSessionReplayPrivacyOverrides();
+
+ Assert(overrides is not null, "UIView returned no privacy overrides object.");
+
+ overrides.TextAndInputPrivacy = DDTextAndInputPrivacyLevelOverride.MaskAll;
+ overrides.ImagePrivacy = DDImagePrivacyLevelOverride.MaskAll;
+ overrides.TouchPrivacy = DDTouchPrivacyLevelOverride.Hide;
+ overrides.Hide = new NSNumber(true);
+
+ // Read back through a fresh accessor call: the override object is attached to the view, so
+ // a value set through one handle must be visible through another.
+ var again = view.GetDdSessionReplayPrivacyOverrides();
+ Assert(
+ again.TextAndInputPrivacy == DDTextAndInputPrivacyLevelOverride.MaskAll,
+ $"Override did not stick: {again.TextAndInputPrivacy}");
+ Assert(again.Hide?.BoolValue == true, "Hide override did not stick.");
+
+ Report("per-view privacy overrides set and read back");
+ }
+
+ /// Account info and the user-info clearing APIs, added in 2.29.0 and 2.30.0.
+ private static void SetsAccountInfo()
+ {
+ DDDatadog.SetAccountInfoWithAccountId("acct-1", "Test Account", DatadogAttributes.Empty);
+ DDDatadog.AddAccountExtraInfo(
+ new NSDictionary(new NSString("tier"), new NSString("premium")));
+ DDDatadog.ClearAccountInfo();
+
+ // setUserInfo requires an id from 2.24.0, and clearUserInfo arrived in 2.30.0.
+ DDDatadog.SetUserInfoWithUserId("user-2", "User Two", "user2@example.invalid", DatadogAttributes.Empty);
+ DDDatadog.ClearUserInfo();
+
+ Report("account info set, extended and cleared; user info cleared");
+ }
+
+ /// Attribute APIs added to the RUM monitor in 2.23.0, and the AP2 site added in 2.29.0.
+ private static void NewRumAndSiteApis()
+ {
+ var monitor = DDRUMMonitor.Shared;
+
+ monitor.AddAttributes(
+ new NSDictionary(new NSString("build.channel"), new NSString("e2e")));
+ monitor.RemoveAttributesForKeys(["build.channel"]);
+
+ Assert(DDSite.Ap2 is not null, "DDSite.Ap2 is missing.");
- Report($"Session Replay enabled at privacy level {configuration.DefaultPrivacyLevel}");
+ Report("RUM addAttributes/removeAttributes and DDSite.Ap2 available");
}
private static void EnablesCrashReporting()