# Logging

Canonical page: https://docs.ovok.com/native-sdk/guide/components/helpers/logging

The SDK exposes three supported logging functions from `@ovok/native/helpers` and
the package root `@ovok/native`. These are function APIs rather than rendered UI
components. They share one logger configuration across SDK log calls and app-owned
diagnostics.

~~~ts
import {
  configureOvokLogger,
  ovokLogger,
  slog,
} from "@ovok/native/helpers";
~~~

## Public API [#public-api]

| Export | Signature | Purpose |
| --- | --- | --- |
| `configureOvokLogger` | `(logger?: OvokLogger) => void` | Set a host logger callback. Call without an argument to restore the default console logger. |
| `ovokLogger` | `(level, message, extra?) => void` | Write an app-owned log through the configured SDK logger. |
| `slog` | `(error, scope, additionalData?, level?) => void` | Compatibility helper used by SDK features; defaults to the `error` level. |

`OvokLogger` and `OvokLogLevel` describe the callback signature in the source
module, but the helper barrel does not re-export those type names. The callback
shape is:

~~~ts
type OvokLogLevel = "error" | "warning" | "info" | "debug" | "fatal" | "trace";
type OvokLogger = (
  level: OvokLogLevel,
  message: string,
  extra?: Record<string, unknown>,
) => void;
~~~

## Route logs to your logger [#route-logs-to-your-logger]

~~~ts
import { configureOvokLogger } from "@ovok/native/helpers";

configureOvokLogger((level, message, extra = {}) => {
  appLogger.write({ level, message, attributes: extra });
});
~~~

The callback is called synchronously and the SDK does not catch exceptions from
it. Keep it fast and non-throwing so a logging failure cannot interrupt the SDK
operation that emitted the log. Configure it during app startup.

`ovokLogger` first attempts to emit an OpenTelemetry log when a logger provider is
available, then calls your configured callback. Without a custom callback it uses
the console logger. Configuring your callback replaces the console destination; it
does not disable OpenTelemetry logging. The default console logger prefixes messages
with `[Ovok]` and maps `warning` to `console.warn`, `trace` to `console.debug`, and
`fatal` to `console.error`.

Error and fatal calls also add one to the `ovok.errors` counter. The metric uses
`extra.errorCode` when it is a string and `unknown` otherwise. Telemetry provider
failures are swallowed; custom callback failures are not.

## Use the compatibility helper [#use-the-compatibility-helper]

`slog` adapts the logger calls used by existing SDK features:

~~~ts
slog(error, "bt.connect", { provider: "bluetooth" }, "warning");
~~~

Its parameters are `error`, a free-text `scope`, optional `additionalData`, and an
optional level (`error`, `warning`, `info`, or `debug`). The default level is
`error`. It sends `scope` as the log message and wraps the other values as
`{ error, additionalData }` in `extra`.

The old `sentryLogger` name is an internal deprecated source alias. It is not
re-exported from the public helper barrel, and it does not send events to Sentry.
Use `slog` for the established helper shape or `ovokLogger` for a direct message.

## Handle log data deliberately [#handle-log-data-deliberately]

The logger does not sanitize the message or `extra` object. The telemetry attribute
allowlist also does not apply to these log fields. Avoid credentials, patient or
account identifiers, clinical values, and raw device payloads in messages and
extras. Apply your own redaction before forwarding log data to a vendor.

For structured spans, metrics, and the attribute sanitizer, see
[Telemetry](/native-sdk/guide/components/helpers/telemetry). For setup and built-in SDK signals, see the
[Logs and telemetry guide](/native-sdk/guide/how-to/observability).
