DatadogNet.Trace.iOS 3.14.0.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package DatadogNet.Trace.iOS --version 3.14.0.4
                    
NuGet\Install-Package DatadogNet.Trace.iOS -Version 3.14.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DatadogNet.Trace.iOS" Version="3.14.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DatadogNet.Trace.iOS" Version="3.14.0.4" />
                    
Directory.Packages.props
<PackageReference Include="DatadogNet.Trace.iOS" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DatadogNet.Trace.iOS --version 3.14.0.4
                    
#r "nuget: DatadogNet.Trace.iOS, 3.14.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DatadogNet.Trace.iOS@3.14.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DatadogNet.Trace.iOS&version=3.14.0.4
                    
Install as a Cake Addin
#tool nuget:?package=DatadogNet.Trace.iOS&version=3.14.0.4
                    
Install as a Cake Tool

DatadogNet.iOS

NuGet release Targets: net8.0 | net9.0 | net10.0 dd-sdk-ios 3.14.0 Licence: MIT AND Apache-2.0

.NET for iOS and .NET MAUI bindings for the native Datadog iOS SDK (dd-sdk-ios).

Enable Datadog Real User Monitoring, Logs, Trace, Session Replay, WebView tracking and crash reporting from C#, in a net8.0-ios, net9.0-ios or net10.0-ios app.

dotnet add package DatadogNet.Core.iOS
dotnet add package DatadogNet.RUM.iOS
using DatadogCore;
using DatadogRUM;

var configuration = new DDConfiguration(clientToken: "<CLIENT_TOKEN>", env: "production")
{
    Service = "my-app",
    Site = DDSite.Us1(),
};

DDDatadog.InitializeWithConfiguration(configuration, DDTrackingConsent.Granted());
DDRUM.EnableWith(new DDRUMConfiguration(applicationID: "<RUM_APPLICATION_ID>"));

Built against dd-sdk-ios 3.14.0. Coming from the 2.x packages? See Migrating from 2.x — the types moved namespace, so it is not a version bump alone.


Contents


Packages

Twelve packages, one per native framework, plus a compatibility meta-package. Versions are <dd-sdk-ios version>.<binding revision>3.14.0.1 is dd-sdk-ios 3.14.0, binding revision 1. 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
DatadogNet.Core.iOS DatadogCore Internal SDK init, consent, user/account info, URLSession instrumentation. Always needed.
DatadogNet.RUM.iOS DatadogRUM Core, Internal Real User Monitoring — the whole DDRUM* API.
DatadogNet.Logs.iOS DatadogLogs Core, Internal Log collection.
DatadogNet.Trace.iOS DatadogTrace Core, Internal, OpenTelemetryApi Distributed tracing (APM).
DatadogNet.SessionReplay.iOS DatadogSessionReplay Core, Internal Session Replay. Requires RUM.
DatadogNet.WebViewTracking.iOS DatadogWebViewTracking Core, Internal Bridges RUM/Logs out of a WKWebView.
DatadogNet.CrashReporting.iOS DatadogCrashReporting Core, Internal Native crash capture (KSCrash). Reports through RUM.
DatadogNet.Flags.iOS DatadogFlags Core, Internal Feature flags. No C# API yet — see below.
DatadogNet.Profiling.iOS DatadogProfiling Core, Internal Continuous profiling. No C# API yet — see below.
DatadogNet.Internal.iOS DatadogInternal Shared foundation. Pulled in transitively.
DatadogNet.OpenTelemetryApi.iOS OpenTelemetryApi OpenTelemetry API types for trace propagation.
DatadogNet.Objc.iOS — (meta-package) Core, RUM, Logs, Trace, SessionReplay Compatibility only. Redirects an existing 2.x PackageReference. New apps ignore it.

Reference the modules you use. A typical app takes DatadogNet.Core.iOS plus DatadogNet.RUM.iOS, and adds Logs, Trace, SessionReplay, CrashReporting or WebViewTracking as needed.

DatadogNet.Flags.iOS and DatadogNet.Profiling.iOS expose no callable API. Upstream ships these modules but has not projected them into Objective-C, so there is nothing for C# to bind. The packages exist so the set mirrors the SDK and so adding the API later is a version bump. There is no reason to reference them today.

The dependency graph is the real one, read off the frameworks' Mach-O load commands. DatadogInternal is the root; every product module depends on it, and DatadogTrace also on OpenTelemetryApi.

Target frameworks: net8.0-ios18.0, net9.0-ios18.0, net10.0-ios26.0. Minimum deployment target: iOS 12.2 — the Datadog frameworks are Swift and use the OS-provided Swift runtime, ABI-stable from 12.2.

net8 sunset. The net8 head is already past its platform support window — the net8 mobile workloads left support with MAUI 8 on 14 May 2025 — and ships for the apps that still target it, with the simulator checks run against it so what works is verified rather than assumed. So the decision does not persist by inertia: the net8 head is dropped in the first release after .NET 8 itself leaves support on 10 November 2026.


Installing

<ItemGroup>
  <PackageReference Include="DatadogNet.Core.iOS" Version="3.14.0.4" />
  <PackageReference Include="DatadogNet.RUM.iOS" Version="3.14.0.4" />
</ItemGroup>

In a multi-targeted MAUI project, guard the references so an Android or Windows head does not try to restore them:

<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
  <PackageReference Include="DatadogNet.Core.iOS" Version="3.14.0.4" />
  <PackageReference Include="DatadogNet.RUM.iOS" Version="3.14.0.4" />
</ItemGroup>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">12.2</SupportedOSPlatformVersion>

Usage

The C# names are the Objective-C selectors projected into C#. Each feature is in its own namespace now — one using per module. samples/DatadogNet.iOS.Example is a working MAUI app that does all of the below; Datadog.cs is the setup in one file.

Initialize

Once, as early as possible — in MAUI, in MauiProgram.CreateMauiApp before the builder runs, so crash reporting and startup metrics cover the whole launch.

using DatadogCore;
using DatadogInternal;   // DDCoreLoggerLevel

var configuration = new DDConfiguration(clientToken: "<CLIENT_TOKEN>", env: "production")
{
    Service = "my-app",
    Site = DDSite.Us1(),   // Us1, Us3, Us5, Eu1, Ap1, Ap2, Us1_fed
};

DDDatadog.InitializeWithConfiguration(configuration, DDTrackingConsent.Granted());
DDDatadog.SetVerbosityLevel(DDCoreLoggerLevel.Warn);   // SDK problems to the Xcode console

DDSite and DDTrackingConsent are classes of static factory methods, so the values are called: DDSite.Us1(), DDTrackingConsent.Granted().

RUM

using DatadogRUM;

var rum = new DDRUMConfiguration(applicationID: "<RUM_APPLICATION_ID>")
{
    SessionSampleRate = 100,
    TrackFrustrations = true,
    TrackMemoryWarnings = true,   // new in 3.0
    UiKitViewsPredicate = new DDDefaultUIKitRUMViewsPredicate(),
    UiKitActionsPredicate = new DDDefaultUIKitRUMActionsPredicate(),
};

DDRUM.EnableWith(rum);

Manual reporting through DDRUMMonitor.Shared():

var monitor = DDRUMMonitor.Shared();

using (monitor.StartView("checkout", "Checkout"))
{
    // View-level attributes propagate to the actions, resources and errors recorded here - a 3.0
    // change that removes the need to repeat them on every call.
    monitor.AddViewAttributes(new Dictionary<string, object?> { ["cart.total"] = 42.50m });

    monitor.AddAction(DDRUMActionType.Tap, "pay");

    try { /* ... */ }
    catch (Exception exception) { monitor.AddError(exception); }
}

Logs

using DatadogLogs;

DDLogs.Enable();

var logger = DDLogger.Create(name: "app", bundleWithRumEnabled: true);

logger.Log(DDLogLevel.Info, "user signed in");
logger.Log(DDLogLevel.Error, "payment failed", exception, new Dictionary<string, object?>
{
    ["order.id"] = orderId,
});

Redact or drop logs before upload with an event mapper:

var configuration = new DDLogsConfiguration(customEndpoint: null);
configuration.SetEventMapper(logEvent =>
{
    logEvent.Message = Redact(logEvent.Message);
    return logEvent;    // or return null to drop the event
});
DDLogs.EnableWith(configuration);

Trace

using DatadogTrace;

DDTrace.EnableWith(new DDTraceConfiguration
{
    SampleRate = 100,
    NetworkInfoEnabled = true,
    BundleWithRumEnabled = true,
});

Header writers for distributed tracing — DDHTTPHeadersWriter (Datadog), DDB3HTTPHeadersWriter (B3) and DDW3CHTTPHeadersWriter (W3C tracecontext). None takes a sampling argument in 3.x; sampling is derived from the RUM session.id.

Network instrumentation

Automatic RUM resource collection and trace propagation, from 3.0 through the unified DDURLSessionInstrumentation. This binding resolves the delegate class for you:

using DatadogCore;

DDURLSessionInstrumentation.Enable<MySessionDelegate>();
// ...
DDURLSessionInstrumentation.Disable<MySessionDelegate>();

MySessionDelegate must be an NSObject implementing INSUrlSessionDataDelegate with a [Register] attribute. Attach it to your NSUrlSession as usual.

Session Replay

using DatadogSessionReplay;

DDSessionReplay.EnableWith(new DDSessionReplayConfiguration(
    replaySampleRate: 100,
    textAndInputPrivacyLevel: DDTextAndInputPrivacyLevel.MaskAll,
    imagePrivacyLevel: DDImagePrivacyLevel.MaskAll,
    touchPrivacyLevel: DDTouchPrivacyLevel.Hide));

Requires RUM. The three levels are required arguments, so what gets redacted on the device is always an explicit choice. A single view can override them:

var overrides = myView.GetDdSessionReplayPrivacyOverrides();
overrides.TextAndInputPrivacy = DDTextAndInputPrivacyLevelOverride.MaskAll;
overrides.Hide = new NSNumber(true);

WebView tracking

using DatadogWebViewTracking;
using Foundation;

DDWebViewTracking.EnableWithWebView(
    webView, new NSSet<NSString>(new NSString("example.com")), logsSampleRate: 100);
// ...and when the web view goes away - the bridge holds a reference to it:
DDWebViewTracking.DisableWithWebView(webView);

The page inside must run the Datadog Browser SDK, and its host must be on the allowlist — which is an allowlist because the bridge lets page JavaScript write into your RUM session.

Crash reporting

Add DatadogNet.CrashReporting.iOS, then enable it after initializing the SDK:

using DatadogCrashReporting;

DDCrashReporter.Enable();

The engine is KSCrash. Crashes are reported on the next launch as RUM errors — enable RUM too, or they are not delivered. Upload your app's dSYMs to Datadog for symbolication.

DDDatadog.SetUserInfo("user-123", "Ada Lovelace", "ada@example.com");
DDDatadog.SetAccountInfo("acct-42", "Acme Corp");
DDDatadog.SetTrackingConsent(TrackingConsent.Pending);

Convenience API

The generated binding is a faithful projection of Objective-C, which makes some things clumsy in C#. Each product module adds a small hand-written layer over it. The generated members are all still there; nothing is hidden or renamed.

Instead of Write
monitor.StartViewWithKey(...)StopViewWithKey(...) matched by key using (monitor.StartView("k", "Name"))
new NSDictionary<NSString, NSObject>(...) with hand-wrapped values new Dictionary<string, object?> { ["k"] = 42 } on any overload below
monitor.AddActionWithType(type, name, attributes) monitor.AddAction(type, name, attributes?)
monitor.AddErrorWithMessage(...) with an NSError you do not have monitor.AddError(exception)
monitor.AddViewAttributes(nsDictionary) monitor.AddViewAttributes(dictionary) / RemoveViewAttributes(params keys)
six log methods per level, plus an NSError you do not have logger.Log(level, message, exception?, attributes?)
new DDLoggerConfiguration(service, name, bool, bool, bool, float, level, bool) DDLogger.Create(name: "app")
DDDatadog.SetUserInfoWithUserId(id, null, null, empty) DDDatadog.SetUserInfo(id)
DDTrackingConsent.Granted() (a factory, not an enum) DDDatadog.SetTrackingConsent(TrackingConsent.Granted)
DDURLSessionInstrumentation.EnableWithConfiguration(...) with a raw Class handle DDURLSessionInstrumentation.Enable<TDelegate>()
a one-element dictionary round-trip to convert one value DatadogAttributes.ToNSObject(value, key)
monitor.AddAttributeForKey(k, nsObject) monitor.AddAttribute(k, value) / AddViewAttribute / AddFeatureFlagEvaluation
monitor.CurrentSessionIDWithCompletion(block) await monitor.GetCurrentSessionIdAsync()
construct a writer, pass it as the carrier, read headers back off it — once per format span.InjectHeaders(tracer)
no way at all to read a span's ids span.GetTraceId(tracer) / span.GetSpanId(tracer)
span.SetErrorWithKind(kind, message, stack) from an exception you must decompose span.SetError(exception)

Attribute values may be strings, any numeric type, bool, DateTime, DateTimeOffset, Guid, enums, NSObjects, arrays, and nested dictionaries. Anything else throws ArgumentException rather than being silently dropped. DatadogAttributes lives in DatadogCore.

The convenience layer is fully documented, and the main entry types of the generated tier carry summaries tooDDDatadog, DDConfiguration, DDSite, DDTrackingConsent, the Enable/ configuration types of every module, DDRUMMonitor, DDLogger, DDTracer and the header writers — written in ApiDefinitions.cs, which the binding generator carries through to the package's XML docs. The long tail of generated members (the 377 RUM model types, mostly) has no upstream docs to import and stays bare; the C# names map 1:1 onto the Objective-C ones, so upstream's reference covers them.

Trace ids

GetTraceId returns 32 lowercase hexadecimal characters and GetSpanId returns decimal. The asymmetry is not a choice — it is Datadog's wire format, and matching it is what makes a RUM resource correlate with its APM trace. dd-sdk-android's own DatadogInterceptor writes _dd.trace_id as DatadogTraceId.toHexString() and _dd.span_id as String.valueOf(long).

Reading the ids takes work because OTSpanContext exposes none: they are recovered by injecting into a Datadog-format writer, and the trace id arrives in two pieces — the decimal low 64 bits in x-datadog-trace-id, and the high 64 as _dd.p.tid inside x-datadog-tags. Using only the former yields a decimal string naming half of a different-looking id, which is a mistake that reached a release of a consumer of this package before it was caught.


API coverage

Measured by diffing each framework's generated -Swift.h against ApiDefinitions.cs, not estimated.

Framework Objective-C types Bound
DatadogRUM 377 377
DatadogLogs 16 16
DatadogCore 12 12
DatadogTrace 12 12
DatadogSessionReplay 4 4
DatadogInternal 2 2
DatadogCrashReporting 1 1
DatadogWebViewTracking 1 1

Member coverage is the same story: of 61 selectors and properties on DatadogCore, 59 are exported, and the two that are not are init and new, which [DisableDefaultCtor] removes on purpose.

What is missing is missing upstream. Three parts of dd-sdk-ios have no Objective-C projection at all, so there is nothing for a binding to bind:

Swift types ObjC types Consequence
DatadogFlags 15 0 Feature Flags are unreachable from C#. The API leans on generics (FlagDetails<T>) and enums with associated values (AnyValue), neither of which Swift projects into Objective-C.
DatadogProfiling 2 0 Profiling is unreachable.
OpenTelemetryApi no -Swift.h at all A pure-Swift module. DatadogNet.OpenTelemetryApi.iOS can only ever be a link-time dependency of DatadogNet.Trace.iOS.

DatadogTrace is additionally 24 public Swift types projected down to 12, and the casualty is OTelTracerProvider — so OpenTelemetry tracing is unreachable even though OpenTracing is not.

DatadogNet.Flags.iOS and DatadogNet.Profiling.iOS therefore ship the frameworks and expose no callable API. They exist so the SDK is mirrored and so a future projection needs no new package.

There is a way around this — a hand-written Swift @objc wrapper, which we can compile ourselves — and a working prototype for Flags lives in shims/DatadogFlagsObjc/. Nothing ships yet.


Migrating from 2.x

The 2.x packages (2.30.2.1 and earlier) bound dd-sdk-ios 2.x, where every DD* type lived in a single DatadogObjc namespace. dd-sdk-ios 3.0 deleted that framework and moved the types into the module each belongs to, so migration is a code change, not a version bump.

Namespaces. Replace using DatadogObjc; with a per-feature set:

-using DatadogObjc;
+using DatadogCore;      // DDDatadog, DDConfiguration, DDSite, DDTrackingConsent
+using DatadogRUM;       // DDRUM, DDRUMMonitor, DDRUMConfiguration, RUM event models
+using DatadogLogs;      // DDLogs, DDLogger, DDLoggerConfiguration
+using DatadogTrace;     // DDTrace, DDTracer, header writers
+using DatadogInternal;  // DDCoreLoggerLevel, DDTracingHeaderType

Packages. If you referenced DatadogNet.Objc.iOS, it still resolves — it is now a dependency-only meta-package pulling Core, RUM, Logs, Trace and SessionReplay — but prefer moving to the product modules directly. DatadogNet.CrashReporter.iOS is retired (KSCrash replaced PLCrashReporter and is part of DatadogNet.CrashReporting.iOS).

API changes, all upstream:

2.x 3.x
DDSite.Us1 (property) DDSite.Us1() (factory method)
DDTrackingConsent.Granted DDTrackingConsent.Granted()
DatadogURLSessionDelegate / DDNSURLSessionDelegate DDURLSessionInstrumentation.Enable<T>()
DDOTelHTTPHeadersWriter DDW3CHTTPHeadersWriter
new DDHTTPHeadersWriter(samplingStrategy, injection) new DDHTTPHeadersWriter(injection)
RUMView(path:) RUMView(name:)
crashes via Logs crashes via RUM error tracking

If you cannot make these changes yet, stay on 2.30.2.1 — it remains on nuget.org. Note that the 2.x line receives no further upstream fixes.


How this repository works

DataDog/dd-sdk-ios release  ──►  Datadog.xcframework.zip  (one archive, eleven frameworks)
        │  build/FetchXcFrameworks.sh — download, verify SHA-256, strip to iOS slices
        ▼
   libs/<Framework>.xcframework
        │  src/DatadogNet.<Package>.iOS/ — binding project + committed ApiDefinitions.cs
        │  build/BuildNugets.sh — pack twice (net9 band, net10 band), then merge
        ▼
   artifacts/*.nupkg  ──►  nuget.org

There is no Carthage step and nothing is compiled from source. Datadog publishes the built xcframeworks as a release asset, so the build downloads one archive, verifies it against a hash pinned in build/checksums.txt, and strips it to the two iOS slices.

Why the two-pass build. Each .NET SDK's iOS workload supports the current target framework and the previous one — the .NET 9 band builds net8 + net9, the .NET 10 band builds net9 + net10. No single SDK builds all three, so BuildNugets.sh packs twice and merge-packages.py grafts the net10 assets and dependency groups into the net9 packages.

Layout

Path What
src/DatadogNet.*.iOS/ One binding project per framework. ApiDefinitions.cs and StructsAndEnums.cs are committed sources.
src/Datadog.Binding.props Everything the binding projects share, so each .csproj is a dozen lines.
src/DatadogNet.*.iOS/Additions/ The hand-written convenience API, in Core, RUM and Logs.
src/DatadogNet.Objc.iOS/ The compatibility meta-package: dependencies, no assembly.
build/ Fetch, pack, merge and binding-regeneration scripts, plus the checksum pins.
tests/DatadogNet.iOS.PackageTests/ Asserts the shape of the packed .nupkgs — 127 checks.
tests/DatadogNet.iOS.DeviceTests/ An iOS app that consumes the packed packages and drives the real SDK on a simulator.
samples/DatadogNet.iOS.Example/ A MAUI app doing the same, the way an app would.

The tests consume the packed .nupkgs from artifacts/ rather than referencing the projects, so they exercise what actually gets published — including the inter-package dependencies, which a ProjectReference would bypass entirely.

DatadogNet.sln deliberately contains the binding projects and the tests but not the sample. A solution-wide Release build would AOT-compile the MAUI app for device across both of its target frameworks, which takes longer than everything else in the repository put together. Build the sample directly, as the command in the next section does.


Building locally

Requires macOS, Xcode, and the .NET 9 and .NET 10 SDKs with the ios workload.

./build/FetchXcFrameworks.sh    # ~200 MB, verified against build/checksums.txt
./build/BuildNugets.sh          # packs all twelve into artifacts/
dotnet test tests/DatadogNet.iOS.PackageTests

Run the on-simulator smoke tests against the packed packages:

./.github/scripts/run-simulator-tests.sh 3.14.0.4 net9.0-ios18.0

Build and run the sample:

dotnet build samples/DatadogNet.iOS.Example/DatadogNetExample.csproj -p:RuntimeIdentifier=iossimulator-arm64

Building anything that targets net10.0-ios26.0 needs Xcode 26.0 specifically — .NET for iOS refuses any other version. If your default Xcode is newer, prefix the command: DEVELOPER_DIR=/Applications/Xcode_26.0.1.app/Contents/Developer .... CI handles this with the select-xcode action.


Upgrading the Datadog SDK

  1. ./build/BumpNativeVersion.sh 3.15.0 does the mechanical part: bumps DatadogNativeVersion in Directory.Build.props and resets DatadogBindingRevision to 1; pins the new archive's hash in build/checksums.txt from the digest GitHub publishes for the release asset, verified against a fresh download of the same bytes (build/UpdateChecksums.sh); points PackageValidationBaselineVersion at the version being left behind; rewrites this README's badge, prose and install snippets; and scaffolds docs/release-notes/3.15.0.1.md.
  2. ./build/DiffSwiftHeaders.sh 3.15.0 — before fetching, while libs/ still holds the previous release — writes one build/<Framework>.Swift.h.diff per framework whose generated header changed, which is the porting work list; docs/regenerating-bindings.md explains how to read one. (./build/GenerateBindings.sh is the automated alternative for when Objective Sharpie works again — it writes to Binding/, not over the committed sources, and its header lists the fixes the committed files carry that regenerating would otherwise undo.)
  3. ./build/FetchXcFrameworks.sh — replaces libs/ with the new release's frameworks.
  4. Port the diffs into the committed ApiDefinitions.cs files.
  5. ./build/BuildNugets.sh and run both test suites.
  6. Finish the scaffolded release notes — its TODOs mark what cannot be generated — then tag (see Releasing).

build/CheckReadmeVersions.sh verifies the badge, the "Built against" prose and the install snippets against Directory.Build.props — the bump script runs it last, and CI runs it on every build, so a stale spot fails loudly rather than shipping.

If Datadog adds or removes a framework, FetchXcFrameworks.sh fails loudly rather than silently dropping a package — update the FRAMEWORKS list, add or remove the binding project, and update Packages.All in the package tests.

Note. Objective Sharpie 3.5.116 cannot currently generate these bindings — its bundled clang fails on recent iOS SDK module maps. The committed sources were produced by parsing the shipped -Swift.h headers directly; GenerateBindings.sh documents the problem and honours a SHARPIE override for when it is fixed. Until then the header diff is the upgrade path — see docs/regenerating-bindings.md.


Releasing

Tag it. v3.14.0.3 builds, tests, publishes every package 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.

The tag must agree with Directory.Build.props: pushing v3.15.0.1 while DatadogNativeVersion still says 3.14.0 — or a fourth component that is not DatadogBindingRevision — fails the workflow before anything builds, since it would publish packages whose version does not describe their contents. For a deliberate different-line release, set the RELEASE_ALLOW_VERSION_MISMATCH repository variable to true for that release, and unset it afterwards.

Pull requests publish a -beta.<pr>.<run> prerelease of the whole set.

Curated notes in docs/release-notes/<version>.md replace the generated commit list when present.


Troubleshooting

DDDatadog/DDRUMMonitor/DDLogger could not be found. The types moved namespace in 3.0. Add the per-module using — see Migrating from 2.x.

Nothing appears in Datadog. Check Site matches your organisation's region — the most common cause. Set DDDatadog.SetVerbosityLevel(DDCoreLoggerLevel.Debug) to see the SDK's own diagnostics in the Xcode console.

Crashes do not show up. Crash reports are delivered through RUM in 3.x, so RUM must be enabled alongside Crash Reporting, and dSYMs uploaded for symbolication.

This version of .NET for iOS requires Xcode 26.0. Only affects net10.0-ios26.0. See Building locally.

ArgumentNullException passing null attributes to logger.Info(message, attributes) — or any other level. Faithful to upstream: the Objective-C projection declares the dictionary (and the NSError) _Nonnull, and the Swift implementation takes a non-optional [String: Any], so a binding that allowed null through would crash natively in the bridging thunk instead. Use the message-only overload, or the convenience logger.Log(level, message, exception?, attributes?), which accepts null for both.

A framework fails to load at runtime. Usually a partially restored package. Clear the cached copies and restore again: rm -rf ~/.nuget/packages/datadognet.*.


Licence

The binding code in this repository is MIT. The native binaries the packages ship are built and published by Datadog and are Apache-2.0 — which covers dd-sdk-ios, KSCrash and opentelemetry-swift alike. Every package declares MIT AND Apache-2.0 and carries both texts under licenses/.

Product Compatible and additional computed target framework versions.
.NET net8.0-ios18.0 is compatible.  net9.0-ios was computed.  net9.0-ios18.0 is compatible.  net10.0-ios was computed.  net10.0-ios26.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on DatadogNet.Trace.iOS:

Package Downloads
DatadogNet.Objc.iOS

Dependency-only compatibility meta-package for the Datadog iOS SDK bindings. dd-sdk-ios 3.0 removed the DatadogObjc framework and moved its DD* types into the product modules, so this package now just pulls in DatadogNet.Core.iOS, DatadogNet.RUM.iOS, DatadogNet.Logs.iOS, DatadogNet.Trace.iOS and DatadogNet.SessionReplay.iOS. Namespaces changed with the move, so code needs updating - see the migration table in the README. New apps should reference the product modules directly.

DatadogNet

One cross-platform Datadog API for .NET MAUI: RUM, Logs, Trace and Session Replay on Android, iOS and Mac Catalyst from shared code, over the native dd-sdk-android and dd-sdk-ios bindings. Restores and no-ops on Windows, so a multi-headed app needs no conditionals.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.14.0.5 87 7/28/2026
3.14.0.5-beta.11.23 26 7/30/2026
3.14.0.5-beta.10.21 26 7/30/2026
3.14.0.5-beta.9.20 37 7/29/2026
3.14.0.5-beta.8.19 32 7/28/2026
3.14.0.4 88 7/26/2026
3.14.0.4-beta.7.16 42 7/26/2026
3.14.0.3 133 7/24/2026
3.14.0.3-beta.6.15 55 7/24/2026
3.14.0.3-beta.6.14 48 7/24/2026
3.14.0.2 107 7/23/2026
3.14.0.2-beta.5.12 46 7/23/2026
3.14.0.2-beta.5.11 46 7/23/2026
3.14.0.2-beta.5.10 48 7/23/2026
3.14.0.1 96 7/23/2026
3.14.0.1-beta.3.8 45 7/23/2026
2.30.2.2 109 7/23/2026
2.30.2.1 94 7/22/2026
2.30.2.1-beta.2.4 50 7/22/2026
2.17.0.1-beta.1.2 43 7/22/2026
Loading failed

## What's changed

Binding-only release. The native SDK is unchanged — still
[dd-sdk-ios 3.14.0](https://github.com/DataDog/dd-sdk-ios/releases/tag/3.14.0) — and so are the
package ids, namespaces and API. The fourth component advances for the changes below: round two of
the ergonomics review, aimed this time at the packaging metadata, the supply chain around the
native archive, and the release machinery.

## Descriptions no longer point at an empty package

Since 3.14.0.1 the RUM, Logs and Trace descriptions ended "The managed DD* API lives in
DatadogNet.Objc.iOS; this package ships the native feature" — carried over from 2.x, where the
DatadogObjc framework really did hold every DD* type, and wrong ever since 3.0 deleted it: each
package binds its own surface (RUM's `ApiDefinitions.cs` alone is 7,400 lines), and
DatadogNet.Objc.iOS is a dependency-only meta-package with no assembly at all. A reader on
nuget.org following that sentence installed an empty package. The descriptions now say where the
API actually is, the stale rationale comment in `src/Datadog.Binding.props` is rewritten to match
reality, and the package tests reject any description that makes the old claim again.

## The packed README's links now work on nuget.org

The same README.md ships in every package and is rendered on each package's nuget.org page — where
its eleven repo-relative links (the sample, `build/checksums.txt`, the regeneration guide, the
Flags shim, the licence and friends) resolved against nuget.org and rendered as dead text. Every
repository link is absolute now; in-page anchors stay as they are, since those work everywhere the
file renders.

## Checksums: trust-on-first-use replaced by GitHub's own digests

`build/checksums.txt` is the trust anchor for the ~200 MB native archive, but its pins were
recorded by downloading the archive and writing down whatever hash arrived — so a tampered first
download would have minted the poisoned hash as the truth. The new `build/UpdateChecksums.sh`
records the digest the GitHub releases API reports for the asset, computed by GitHub at upload
time, and requires a fresh download to hash to the same value before anything is written.
`FetchXcFrameworks.sh` additionally cross-checks the pin against the live digest before
downloading and hard-fails on a disagreement; when the API is unreachable — offline,
rate-limited — the pinned hash still guards the download, so no build grows a network dependency
it did not have. Run against 3.14.0, the published digest equals the pin recorded under the old
flow: a retroactive check the old flow could not offer.

## Package validation against the published baseline

CI now holds every packed package's API to the last published release —  this one's baseline is
`3.14.0.3` — so an accidental API break, most plausibly a regenerated binding quietly dropping a
member, fails in CI instead of surfacing in a consumer's compiler. It runs as
`build/ValidatePackageApi.sh` on the merged artifacts rather than at pack time: each band's pack
pass produces an intermediate that legitimately lacks the other band's frameworks, and only the
finished package carries the framework set the baseline has. The baseline downloads from
nuget.org, so the check is CI's and an explicit local invocation's, never part of an offline
pack.

## Release machinery

- **A release tag must agree with `Directory.Build.props`.** The tag alone drives which native
 line is bound, so a mistyped tag would have published packages whose version does not describe
 their contents. The workflow now fails before building when the tag's native prefix or binding
 revision disagrees with the props; releasing a different line on purpose remains possible
 through a documented repository variable.
- **Upstream releases are watched.** A weekly workflow compares `DatadogNativeVersion` against
 the latest dd-sdk-ios release and opens one issue — idempotently — when upstream is ahead,
 linking the release and the upgrade ritual.
- **`build/BumpNativeVersion.sh` starts a native upgrade in one command**: props, digest-anchored
 checksum pin, README badge/prose/snippets, the validation baseline, and a scaffolded
 release-notes file, finishing with a self-check. The README's upgrade guide now leads with it —
 and puts `DiffSwiftHeaders.sh` *before* `FetchXcFrameworks.sh`, since the previous step order
 would have diffed the new release against itself.
- **`build/CheckReadmeVersions.sh` now also verifies the dd-sdk-ios badge and the "Built
 against" prose** — the two hardcoded spots the upgrade guide used to shrug about ("nothing
 else will notice when it goes stale"). Something notices.
- `GenerateBindings.sh`'s usage example no longer names DatadogObjc, a framework deleted
 upstream in 3.0.

## Upgrading from 3.14.0.3

```diff
-<PackageReference Include="DatadogNet.RUM.iOS" Version="3.14.0.3" />
+<PackageReference Include="DatadogNet.RUM.iOS" Version="3.14.0.4" />
```

Nothing to change beyond the version: same native SDK, same API, same package set, and the native
xcframeworks are byte-for-byte the same build. All packages move together, as they depend on each
other at an exact version. The corrected descriptions and working README links appear on
nuget.org with this version.