# Custom instrumentation

Copy as Markdown[Open in ChatGPT](https://chatgpt.com/?q=Read%20https%3A%2F%2Fcoralogix.com%2Fdocs%2Fuser-guides%2Frum%2Fsdk-installation%2Fapple%2Fios%2Ffeatures%2Fcustom-instrumentation.md%20and%20help%20me%20with%20my%20question%20about%20this%20Coralogix%20documentation%20page.)[Open in Claude](https://claude.ai/new?q=Read%20https%3A%2F%2Fcoralogix.com%2Fdocs%2Fuser-guides%2Frum%2Fsdk-installation%2Fapple%2Fios%2Ffeatures%2Fcustom-instrumentation.md%20and%20help%20me%20with%20my%20question%20about%20this%20Coralogix%20documentation%20page.)

### Custom Logs[​](#custom-logs "Direct link to Custom Logs")

Send a structured log at a chosen severity, with optional structured `data` and `labels`.

```
coralogixRum.log(severity: .info,

                 message: "User completed onboarding",

                 data: ["step_count": 4],

                 labels: ["flow": "onboarding"])
```

`CoralogixLogSeverity` is an `Int`-backed enum with six cases:

| Case        | Level |
| ----------- | ----- |
| `.debug`    | 1     |
| `.verbose`  | 2     |
| `.info`     | 3     |
| `.warn`     | 4     |
| `.error`    | 5     |
| `.critical` | 6     |

### Custom Spans[​](#custom-spans "Direct link to Custom Spans")

Create your own OpenTelemetry spans to trace app-specific work (e.g. a checkout flow) with full control over attributes, events, and status. The custom tracer requires `traceParentInHeader` to be enabled in the options.

```
// 1. Enable the custom tracer in your options

let options = CoralogixExporterOptions(coralogixDomain: CORALOGIX-DOMAIN,

                                        environment: "ENVIRONMENT",

                                        application: "APP-NAME",

                                        version: "APP-VERSION",

                                        publicKey: "API-KEY",

                                        traceParentInHeader: ["enable": true])



// 2. Open a global span, then child spans under it

guard let tracer = coralogixRum.getCustomTracer() else { return }

guard let global = tracer.startGlobalSpan(name: "checkout.flow",

                                          labels: ["screen": "cart"]) else { return }



let child = global.startCustomSpan(name: "checkout.authorize")

child.setAttribute(key: "step", value: "authorize")

child.addEvent(name: "authorized")

child.setStatus(.ok)

child.endSpan()



global.endSpan()
```

**Notes:**

* `getCustomTracer()` returns `nil` unless `traceParentInHeader: ["enable": true]` is set.
* While a global span is open it becomes OpenTelemetry's active context, so auto-instrumentation (e.g. `URLSession`) shares the same `traceId` until you call `endSpan()`.
* Only one global span may be open at a time — a second `startGlobalSpan` returns `nil` until the first one ends.
* Use `getCustomTracer(ignoredInstruments: [.networkRequests, .errors])` to exclude specific auto-instruments from the span's trace.

### Custom Measurement[​](#custom-measurement "Direct link to Custom Measurement")

Report a one-off numeric measurement (e.g. a computed score or payload size) as a `custom-measurement` event. To time a span of work instead, use [Custom Time Measurement](#custom-time-measurement).

```
coralogixRum.sendCustomMeasurement(name: "image_load_score", value: 43.0)
```

### Manual View & Application Context[​](#manual-view--application-context "Direct link to Manual View & Application Context")

Override the automatically-tracked screen name, or update the reported application name / version at runtime.

```
// Set the current screen/view name manually (useful for custom navigation)

coralogixRum.setView(name: "CheckoutScreen")



// Update the application name / version reported on subsequent events

coralogixRum.setApplicationContext(application: "MyApp", version: "2.5.0")
```

In SwiftUI, the `trackCXView` view modifier is the declarative equivalent of `setView`: attach it to a view and the SDK reports that view name for you, without a manual call in the navigation code.

```
import SwiftUI

import Coralogix



struct ContentView: View {

    var body: some View {

        Text("Hello, World!")

            .trackCXView(name: "ContentView")

    }

}
```

### Custom Time Measurement[​](#custom-time-measurement "Direct link to Custom Time Measurement")

Time arbitrary spans of work in your app code with `startTimeMeasure(name:labels:)` and `endTimeMeasure(name:)`. Use this when you need to measure something the SDK can't auto-instrument — checkout flows, custom render passes, asset loading, etc. The duration is reported as a `custom-measurement` span (milliseconds).

```
coralogixRum.startTimeMeasure(name: "checkout", labels: ["cart_size": 3])

performCheckoutFlow()

coralogixRum.endTimeMeasure(name: "checkout")
```

**Parameters:**

| Method             | Parameter | Type             | Notes                                                                                                                                |
| ------------------ | --------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `startTimeMeasure` | `name`    | `String`         | Unique identifier. Empty / whitespace-only keys are ignored. A duplicate `start` for an in-flight name is also ignored (first wins). |
| `startTimeMeasure` | `labels`  | `[String: Any]?` | Optional labels attached at start; merged with SDK-level `labels` at `end`. Start labels win on key collision.                       |
| `endTimeMeasure`   | `name`    | `String`         | Must match a prior `start`. No-op when the key was never started, was already ended, or the session has gone idle.                   |

**Pair `start` / `end` like `lock` / `unlock`.** The SDK keeps in-flight measurements in memory and does not impose a cap; an unbalanced caller will accumulate state until the next session-idle reset (15 min of inactivity). The `defer` idiom makes pairing automatic:

```
coralogixRum.startTimeMeasure(name: "checkout")

defer { coralogixRum.endTimeMeasure(name: "checkout") }

try performCheckout()
```

**Notes:**

* **Monotonic clock.** Durations use `DispatchTime.now().uptimeNanoseconds`, so wall-clock changes (NTP step, manual time adjustments) cannot produce negative durations.
* **Trimmed keys.** Leading and trailing whitespace is stripped; `"k "` and `"k"` resolve to the same entry.

Parity note: the Coralogix Browser SDK exposes the same `startTimeMeasure` / `endTimeMeasure` surface with matching semantics.

### Utility Methods[​](#utility-methods "Direct link to Utility Methods")

Read the current session at runtime, for example to attach it to a support ticket. `getSessionId` is a property, and it is `nil` until the SDK has started a session.

```
if let sessionId = coralogixRum.getSessionId {

    attachToSupportTicket(sessionId)

}
```
