# io.Connect Desktop

Source: https://docs.interop.io/insights/configuration/io-connect-desktop/index.html

## Overview

**io.Insights** comes as a built-in feature of **io.Connect Desktop**. The default OpenTelemetry signals it publishes can be enabled, disabled or customized based on your specific business scenarios.

> ⚠️ *Note that the following sections describe how to configure the main features of **io.Insights** in **io.Connect Desktop**. All available settings for configuring **io.Insights** are described in the `otel.json` [configuration schema](https://docs.interop.io/desktop/assets/configuration/otel.json).*

## Enabling io.Insights

**io.Insights** is disabled by default. To enable **io.Insights** and configure its features in **io.Connect Desktop**, use the `"otel"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**  located in the `<installation_location>/config` folder:

```json
{
    "otel": {
        "enabled": true,
        "metrics": {
            "enabled": true,
            "url": "http://localhost:4242/my-metrics-collector",
            "publishInterval": 60000,
            "platformMetricsEnabled": true,
            "metrics": [
                {
                   "type": "app_crash",
                   "enabled": false
                }
            ]
        }
    }
}
```

The `"otel"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"additionalAttributes"` | `object` | Additional properties to publish as part of each OpenTelemetry signal, specified as key/value pairs. You can use environment variables as values. Environment variables must start and end with a percent sign (e.g., `%MyEnvVar%`), and can contain a fallback value (e.g., `%MyEnvVar?DefaultValue%`). *Available since **io.Connect Desktop** 9.9.* |
| `"additionalResourceAttributes"` | `object` | Additional properties to publish as part of the OpenTelemetry resource definition for all OpenTelemetry signals, specified as key/value pairs. You can use environment variables as values. Environment variables must start and end with a percent sign (e.g., `%MyEnvVar%`), and can contain a fallback value (e.g., `%MyEnvVar?DefaultValue%`). *Available since **io.Connect Desktop** 9.9.* |
| `"addResourceAttributesToAttributes"` | `boolean` | If `true`, all resource-level attributes will be copied into every signal data point (metric data points, spans, log records). Defaults to `false`. Signal-level settings take precedence over this value. *Available since **io.Connect Desktop** 10.1.* |
| `"enabled"` | `boolean` | **Required.** If `true`, will enable publishing of telemetry data. Defaults to `false`. |
| `"errorlessMode"` | `boolean` | If `true`, the library will silently swallow all errors instead of propagating them. Useful in production environments where telemetry failures should not affect the platform. Defaults to `false`. *Available since **io.Connect Desktop** 10.1.* |
| `"failOnInitError"` | `boolean` | If `true`, a failure to initialize the library will propagate as an error to the caller. If `false` (default), the library will fail silently and operate in no-op mode. *Available since **io.Connect Desktop** 10.1.* |
| `"finalExportGracePeriodMs"` | `number` | Interval in milliseconds to wait for any remaining telemetry data to be published by any apps before proceeding with the platform shutdown. Defaults to `0`. *Available since **io.Connect Desktop** 9.8.* |
| `"finalExportTimeoutMs"` | `number` | Interval in milliseconds to wait for any remaining telemetry data to be exported during shutdown of the platform. This is the maximum awaiting interval and the platform may shut down before it expires if all telemetry data has already been published. Defaults to `0`. *Available since **io.Connect Desktop** 9.8.* |
| `"headers"` | `object` | Additional headers to send with all HTTP export requests across all signals (metrics, traces, logs), specified as key/value pairs where values are strings. Signal-level `"headers"` settings will be merged with and take precedence over this value. *Available since **io.Connect Desktop** 10.1.* |
| `"logSettingsOnStartup"` | `boolean` | If `true` (default), the library will log the effective settings used to initialize it. *Available since **io.Connect Desktop** 10.1.* |
| `"logs"` | `object` | Settings for publishing logs. *Available since **io.Connect Desktop** 10.1.* |
| `"metrics"` | `object` | Settings for publishing metrics. |
| `"platformVersion"` | `string` | If provided, this value will be added to the metric and span attributes and to the span filtering context. If not provided, defaults to the platform version. *Available since **io.Connect Desktop** 10.1.* |
| `"serviceId"` | `string` | Value to use for the `service.instance.id` OpenTelemetry resource attribute. If not provided, defaults to the platform-generated instance identifier. *Available since **io.Connect Desktop** 10.1.* |
| `"serviceName"` | `string` | Value to use for the `service.name` OpenTelemetry resource attribute. If not provided, defaults to the platform name. *Available since **io.Connect Desktop** 10.1.* |
| `"serviceVersion"` | `string` | Value to use for the `service.version` OpenTelemetry resource attribute. If not provided, defaults to the platform version. *Available since **io.Connect Desktop** 10.1.* |
| `"suppressDoubleInitializationWarnings"` | `boolean` | If `true`, warnings from the OpenTelemetry SDK about double initialization will be suppressed. Defaults to `false`. *Available since **io.Connect Desktop** 10.1.* |
| `"traces"` | `object` | Settings for publishing traces. *Available since **io.Connect Desktop** 10.1.* |
| `"useSSOAuth"` | `boolean` | If `true`, the platform SSO login information will be used when making requests to the OpenTelemetry collector. When enabled, the `Authorization` header will be set using the SSO token, and any authentication headers will be appended to the export requests. Defaults to `false`. Signal-level `"useSSOAuth"` settings take precedence over this value. *Available since **io.Connect Desktop** 10.1.* |
| `"useSSOAuthRawToken"` | `boolean` | Used when the SSO login information contains a `token` property. If `true`, the `token` will be used as-is. If `false` (default), the `token` may be prepended with `"Bearer "` if it doesn't already contain an Authorization type prefix. Signal-level settings take precedence. *Available since **io.Connect Desktop** 10.1.* |
| `"userId"` | `string` | Value to use for the `user.id` (and `user`) OpenTelemetry resource attribute. If not provided, defaults to the authenticated user identity. *Available since **io.Connect Desktop** 10.1.* |

## Metrics

To provide custom settings for publishing metrics, use the `"metrics"` property of the `"otel"` object.

The `"metrics"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"additionalAttributes"` | `object` | Additional properties to publish as part of each metric, specified as key/value pairs. You can use environment variables as values. Environment variables must start and end with a percent sign (e.g., `%MyEnvVar%`), and can contain a fallback value (e.g., `%MyEnvVar?DefaultValue%`). *Available since **io.Connect Desktop** 9.9.* |
| `"additionalResourceAttributes"` | `object` | Additional properties to publish as part of the OpenTelemetry resource definition for metrics signals, specified as key/value pairs. You can use environment variables as values. Environment variables must start and end with a percent sign (e.g., `%MyEnvVar%`), and can contain a fallback value (e.g., `%MyEnvVar?DefaultValue%`). *Available since **io.Connect Desktop** 9.9.* |
| `"addResourceAttributesToAttributes"` | `boolean` | Whether to add resource attributes to metric data point attributes. Defaults to `false`. Signal-level setting takes precedence over the top-level one. *Available since **io.Connect Desktop** 10.1.* |
| `"compression"` | `"none"` \| `"gzip"` | Compression algorithm to use for metric export requests. *Available since **io.Connect Desktop** 10.1.* |
| `"concurrencyLimit"` | `number` | Maximum number of concurrent metric export requests. *Available since **io.Connect Desktop** 10.1.* |
| `"enabled"` | `boolean` | If `true`, will enable publishing metrics. Defaults to `false`. |
| `"filters"` | `object[]` | Array of filter rules to determine which metrics should be collected and exported. Each entry matches metrics by `"name"` and `"type"`, and can enable or disable them individually. *Available since **io.Connect Desktop** 10.1.* |
| `"headers"` | `object` | Additional headers to send with metric export HTTP requests, specified as key/value pairs where values are strings. Merged with and takes precedence over the top-level `"headers"` setting. *Available since **io.Connect Desktop** 10.1.* |
| `"hostname"` | `string` | Hostname to include in exported metrics. *Available since **io.Connect Desktop** 10.1.* |
| `"keepAlive"` | `boolean` | If `true`, will use HTTP keep-alive connections for metric exports. *Available since **io.Connect Desktop** 10.1.* |
| `"meter"` | `object` | Partial meter configuration options. *Available since **io.Connect Desktop** 10.1.* |
| `"metrics"` | `object[]` | Settings for the default platform metrics. Defaults to an array of the default platform metrics. |
| `"platformMetricsEnabled"` | `boolean` | If `true`, will enable publishing of all default platform metrics. |
| `"publishInterval"` | `number` | Interval in milliseconds at which to publish the generated metrics. |
| `"timeoutMillis"` | `number` | Maximum time in milliseconds the OTLP exporter will wait for each batch export. Defaults to `10000`. *Available since **io.Connect Desktop** 10.1.* |
| `"url"` | `string` | URL pointing to an OpenTelemetry metrics collector. |
| `"useDefaultFilters"` | `boolean` | If `true` (default), the predefined default filters for platform metrics will be applied. *Available since **io.Connect Desktop** 10.1.* |
| `"useSSOAuth"` | `boolean` | If `true`, the platform SSO login information will be used when making metric export requests. Takes precedence over the top-level `"useSSOAuth"` setting. Defaults to `false`. *Available since **io.Connect Desktop** 10.1.* |
| `"useSSOAuthRawToken"` | `boolean` | Used when the SSO login information contains a `token` property. If `true` (default), the `token` will be used as-is. If `false`, the `token` may be prepended with `"Bearer "`. Takes precedence over the top-level setting. *Available since **io.Connect Desktop** 10.1.* |

The following sections describe the configuration settings for the the main features related to publishing metrics with **io.Insights**.

> ℹ️ *For details on all available settings for configuring **io.Insights**, see the `otel.json` [configuration schema](https://docs.interop.io/desktop/assets/configuration/otel.json).*

### Platform Metrics

You can enable, disable, or override the settings for the default platform metrics published by **io.Insights** by using a combination of the `"platformMetricsEnabled"` and the `"metrics"` properties of the `"metrics"` object. For instance, you can enable all default platform metrics by setting the `"platformMetricsEnabled"` to `true`, and then disable or customize individual metrics by specifying the predefined metric type in the `"metrics"` array:

```json
{
    "otel": {
        "enabled": true,
        "metrics": {
            "url": "http://localhost:4242/my-metrics-collector",
            "platformMetricsEnabled": true,
            "metrics": [
                // Disabling a default metric.
                {
                   "type": "app_error",
                   "enabled": false
                },
                // Overriding the default settings for a predefined metric.
                {
                    "type": "layout_startup",
                    "name": "Global Layout Startup",
                    "description": "The time it takes to load a Global Layout.",
                    "buckets": [
                        10000,
                        15000,
                        20000
                    ]
                }
            ]
        }
    }
}
```

Each object in the `"metrics"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"additionalAttributes"` | `object` | Additional attributes to add to this specific metric, specified as key/value pairs. *Available since **io.Connect Desktop** 9.9.* |
| `"baseMetricType"` | `"histogram"` \| `"gauge"` | Override the base OpenTelemetry instrument type for this metric. This allows publishing the same predefined metric in different forms simultaneously (e.g., as both a histogram and a gauge with different names). *Available since **io.Connect Desktop** 10.1.* |
| `"buckets"` | `number[]` | Specify explicit bucket boundaries for the OpenTelemetry SDK if the metric is a `Histogram`. |
| `"description"` | `string` | **Required.** Description for the metric. |
| `"enabled"` | `boolean` | **Required.** If `true` (default), will enable publishing the metric. |
| `"name"` | `string` | **Required.** Name for the metric. May be used in visualization tools. |
| `"platformVersion"` | `string` | If provided, this value will be added to the metric attributes. *Available since **io.Connect Desktop** 10.1.* |
| `"type"` | `string` | **Required.** Type of the predefined metric. |
| `"unit"` | `string` | The unit of measurement for this metric (e.g., `"ms"`, `"bytes"`). *Available since **io.Connect Desktop** 10.1.* |
| `"user"` | `string` | If provided, this value will be added to the metric attributes. *Available since **io.Connect Desktop** 10.1.* |

The `"type"` property accepts the following values describing a predefined metric type:

| Value |
|-------|
| `"app_count"` |
| `"app_cpu"` |
| `"app_crash"` |
| `"app_duration"` |
| `"app_error"` |
| `"app_memory"` |
| `"app_started"` |
| `"app_startup"` |
| `"app_stopped"` |
| `"custom_counter"` |
| `"custom_gauge"` |
| `"custom_histogram"` |
| `"custom_observable_counter"` |
| `"custom_observable_gauge"` |
| `"custom_observable_up_down_counter"` |
| `"custom_up_down_counter"` |
| `"layout_startup"` |
| `"platform_error"` |
| `"platform_startup"` |
| `"system_cpu"` |
| `"system_memory"` |
| `"workspace_count"` |
| `"workspace_selected"` |
| `"workspace_started"` |
| `"workspace_startup"` |
| `"workspace_startup_apps"` |
| `"workspace_startup_component"` |
| `"workspace_startup_frame"` |
| `"workspace_startup_frame_init"` |
| `"workspace_startup_frame_page_load"` |
| `"workspace_startup_frame_workspace_render"` |
| `"workspace_stopped"` |

### Metric Filters

You can use the `"filters"` property of the `"metrics"` object to control which metrics are collected and exported. Each filter rule matches metrics by `"name"` and `"type"`, and can enable or disable them. The `"useDefaultFilters"` property controls whether the built-in default filters for platform metrics are applied.

The following example demonstrates how to disable a specific metric by name using a filter:

```json
{
    "otel": {
        "enabled": true,
        "metrics": {
            "enabled": true,
            "url": "http://localhost:4242/my-metrics-collector",
            "useDefaultFilters": true,
            "filters": [
                {
                    "name": "app_cpu",
                    "type": "app_cpu",
                    "enabled": false
                }
            ]
        }
    }
}
```

Each object in the `"filters"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"attributes"` | `object` | Attributes used for matching metrics. For example, `{ "complexLoad": true }` can match metrics with a specific attribute value. |
| `"enabled"` | `boolean` | If `true`, the matching metric will be collected. If `false`, the matching metric will be suppressed. |
| `"name"` | `string` | **Required.** Name of the metric to match. |
| `"overrideDefaultFilters"` | `boolean` | If `true`, this filter rule will be matched before any default filters provided by the platform. Defaults to `false`. |
| `"type"` | `string` | **Required.** Type of the metric to match. Must be one of the predefined metric types (see [Platform Metrics](#platform_metrics)). |

#### Default Metric Filters

When `"useDefaultFilters"` is set to `true` (the default), the platform applies a predefined set of metric filters that reduce the default verbosity of the published metric data. These default filters are evaluated before any user-defined filters (unless a user filter has `"overrideDefaultFilters"` set to `true`).

Currently, the default metric filters disable all `workspace_startup_xxx` metrics when the `complexLoad` attribute is `true`, preventing complex Workspace load scenarios from inflating the metric data:

```json
[
    {
        "name": "workspace_startup",
        "type": "workspace_startup",
        "attributes": { "complexLoad": true },
        "enabled": false
    },
    {
        "name": "workspace_startup_frame",
        "type": "workspace_startup_frame",
        "attributes": { "complexLoad": true },
        "enabled": false
    },
    {
        "name": "workspace_startup_frame_init",
        "type": "workspace_startup_frame_init",
        "attributes": { "complexLoad": true },
        "enabled": false
    },
    {
        "name": "workspace_startup_frame_page_load",
        "type": "workspace_startup_frame_page_load",
        "attributes": { "complexLoad": true },
        "enabled": false
    },
    {
        "name": "workspace_startup_frame_workspace_render",
        "type": "workspace_startup_frame_workspace_render",
        "attributes": { "complexLoad": true },
        "enabled": false
    },
    {
        "name": "workspace_startup_component",
        "type": "workspace_startup_component",
        "attributes": { "complexLoad": true },
        "enabled": false
    },
    {
        "name": "workspace_startup_apps",
        "type": "workspace_startup_apps",
        "attributes": { "complexLoad": true },
        "enabled": false
    }
]
```

To override a specific default filter, add a filter entry with the same `"name"` and `"type"` in the `"filters"` array and set `"overrideDefaultFilters"` to `true`:

```json
{
    "otel": {
        "enabled": true,
        "metrics": {
            "enabled": true,
            "url": "http://localhost:4318/v1/metrics",
            "useDefaultFilters": true,
            "filters": [
                {
                    "name": "workspace_startup",
                    "type": "workspace_startup",
                    "overrideDefaultFilters": true,
                    "enabled": true
                }
            ]
        }
    }
}
```

To disable all default metric filters entirely, set `"useDefaultFilters"` to `false`.

### Exporter Settings

The metrics exporter can be fine-tuned using the `"compression"`, `"timeoutMillis"`, `"concurrencyLimit"`, and `"keepAlive"` properties of the `"metrics"` object. These settings control the HTTP transport behavior of the OTLP metrics exporter.

The following example demonstrates how to configure the metrics exporter with GZIP compression and a custom timeout:

```json
{
    "otel": {
        "enabled": true,
        "metrics": {
            "enabled": true,
            "url": "http://localhost:4318/v1/metrics",
            "publishInterval": 60000,
            "compression": "gzip",
            "timeoutMillis": 15000,
            "keepAlive": true,
            "concurrencyLimit": 5
        }
    }
}
```

### Resource & Metric Attributes

You can customize the OpenTelemetry resource-level attributes and the metric data point attributes using the `"additionalResourceAttributes"` and `"additionalAttributes"` properties of the `"metrics"` object. These are merged with (and take precedence over) the respective top-level settings.

If you set `"addResourceAttributesToAttributes"` to `true`, all resource-level attributes will be copied into every metric data point, making them available for grouping and filtering in your metrics backend.

> ℹ️ *For details on the common resource-level attributes published by **io.Connect Desktop**, see the [Signals > Overview > Common Resource Attributes](https://docs.interop.io/insights/signals/overview/index.md#common_resource_attributes) section.*

The following example demonstrates how to add custom resource and data point attributes to metrics, and how to merge resource attributes into data points:

```json
{
    "otel": {
        "enabled": true,
        "metrics": {
            "enabled": true,
            "url": "http://localhost:4318/v1/metrics",
            "additionalResourceAttributes": {
                "deployment.environment": "production",
                "team": "platform-engineering"
            },
            "additionalAttributes": {
                "datacenter": "%DATACENTER_NAME%"
            },
            "addResourceAttributesToAttributes": true
        }
    }
}
```

## Traces

Available since io.Connect Desktop 10.1

To provide custom settings for publishing traces, use the `"traces"` property of the `"otel"` object.

The `"traces"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"additionalAttributes"` | `object` | Additional span attributes to publish as part of each span, specified as key/value pairs. You can use environment variables as values. Environment variables must start and end with a percent sign (e.g., `%MyEnvVar%`), and can contain a fallback value (e.g., `%MyEnvVar?DefaultValue%`). |
| `"additionalResourceAttributes"` | `object` | Additional attributes to publish as part of the OpenTelemetry resource definition for trace signals, specified as key/value pairs. You can use environment variables as values. Environment variables must start and end with a percent sign (e.g., `%MyEnvVar%`), and can contain a fallback value (e.g., `%MyEnvVar?DefaultValue%`). |
| `"addResourceAttributesToAttributes"` | `boolean` | Whether to add resource attributes to span attributes. Defaults to `false`. Signal-level setting takes precedence over the top-level one. |
| `"clickstream"` | `boolean` \| `string` \| `object` | Whether the Click Stream trace will be enabled. Can be set to `true`/`false`, to `"nested"` or `"sibling"` to control the span structure, or to an object for full configuration. Defaults to `false`. See [Click Stream](#click_stream). |
| `"closeTrace"` | `boolean` | If `true`, the app will create a span named `interopio.api.application.close` when it's being closed. This requires close handlers to be enabled in the app configuration. Defaults to `false`. |
| `"console"` | `boolean` | If `true`, a `ConsoleTraceExporter` will be added, which logs all spans to the console. Useful for debugging. Defaults to `false`. |
| `"countMetric"` | `string` \| `null` | Name of the span hit counter metric used for Traces as Metrics. Set to `null` to disable. Defaults to `"insights_trace_count"`. |
| `"defaults"` | `object` | Default span creation options used as a fallback when no matching filter or sampling rule is found. |
| `"durationMetric"` | `string` \| `null` | Name of the span duration histogram metric used for Traces as Metrics. Set to `null` to disable. Defaults to `"insights_trace_duration"`. |
| `"enabled"` | `boolean` | If `true`, will enable publishing traces. Defaults to `false`. |
| `"filters"` | `object[]` | Array of filter entries used to determine whether a particular operation will create a tracing span. |
| `"headers"` | `object` | Additional headers to send with trace export HTTP requests, specified as key/value pairs where values are strings. Merged with and takes precedence over the top-level `"headers"` setting. |
| `"parentNameLimit"` | `number` | Maximum length for parent operation names in span hierarchies. |
| `"resultMetric"` | `string` \| `null` | Name of the span result counter metric used for Traces as Metrics. Set to `null` to disable. Defaults to `"insights_trace_result"`. |
| `"sampling"` | `object[]` | Array of sampling setting entries used to determine whether a span will be sampled (exported). |
| `"startupParentSpanTimeoutMs"` | `number` | How long in milliseconds after app startup any traced operations will automatically be nested under the app startup trace. Defaults to `3000`. |
| `"url"` | `string` | URL pointing to an OpenTelemetry traces collector. |
| `"useDefaultFilters"` | `boolean` | If `true` (default), a predefined list of filters for well-known platform traces will be applied. |
| `"useOTELContextManager"` | `boolean` | If `true`, the library will use the ContextManager provided by the active OpenTelemetry SDK to manage propagation information across asynchronous operations. Defaults to `false`. |
| `"userJourney"` | `boolean` \| `string` \| `object` | If `true` (default), the User Journey trace will be enabled. Can be set to `true`/`false`, to `"nested"` or `"sibling"` to control the span structure, or to an object for full configuration. |
| `"useSSOAuth"` | `boolean` | If `true`, the platform SSO login information will be used when making trace export requests. Takes precedence over the top-level `"useSSOAuth"` setting. Defaults to `false`. |
| `"useSSOAuthRawToken"` | `boolean` | Used when the SSO login information contains a `token` property. If `true` (default), the `token` will be used as-is. If `false`, the `token` may be prepended with `"Bearer "`. Takes precedence over the top-level setting. |

The following sections describe the configuration settings for the main features related to publishing traces with **io.Insights**.

> ℹ️ *For details on all available settings for configuring **io.Insights**, see the `otel.json` [configuration schema](https://docs.interop.io/desktop/assets/configuration/otel.json).*

### Span Filters

You can use the `"filters"` property of the `"traces"` object to control which operations create tracing spans. Each filter entry matches spans by their `"source"` (span name/operation identifier) and optionally by `"context"` values. When a traced operation is initiated, the filter list is searched for a matching entry, and the settings from that entry are applied. If no match is found, the settings from `"defaults"` are used.

The following example demonstrates how to disable tracing for a specific Interop method invocation and customize settings for a specific app start by using the `"context"` property to narrow down the filter matching:

```json
{
    "otel": {
        "enabled": true,
        "traces": {
            "enabled": true,
            "url": "http://localhost:4318/v1/traces",
            "useDefaultFilters": true,
            "filters": [
                {
                    "source": "interopio.api.interop.invoke",
                    "context": {
                        "method": "T42.UserPreferences"
                    },
                    "enabled": false
                },
                {
                    "source": "interopio.desktop.app.start",
                    "context": {
                        "appName": "clientportfolio"
                    },
                    "enabled": true,
                    "level": "DEBUG",
                    "sample": 0.5
                }
            ],
            "defaults": {
                "enabled": true,
                "level": "INFO",
                "sample": true
            }
        }
    }
}
```

Each object in the `"filters"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"addContextToTrace"` | `boolean` | Whether the filtering context will be added as span attributes to the span. Defaults to `true`. |
| `"autoSetSuccessStatus"` | `boolean` | Whether the span's status will be automatically set to `OK` on completion if it's still `UNSET`. Defaults to `false`. |
| `"canBeRoot"` | `boolean` | Whether the span can start a new trace. If `false`, the span will only be created if an existing trace is currently active. Defaults to `true`. |
| `"context"` | `object` | Specifies filtering context values used for matching spans. Values are strings, numbers, or booleans. Start string values with `#` for case-insensitive regex matching. |
| `"countMetric"` | `boolean` | Whether the span will be counted in the `insights_trace_count` metric. Requires both the Traces and Metrics modules to be enabled. Defaults to `false`. |
| `"countMetricOnDisabledSpans"` | `boolean` | Whether the span will be counted in the `insights_trace_count` metric even when the span itself is disabled. Allows using tracing instrumentation purely for generating metrics. |
| `"disableNesting"` | `boolean` | If `true`, forces the span to always create a new trace, even if a parent span is currently active. |
| `"disablePropagation"` | `boolean` | If `true`, the span will not inject its propagation info into data transfer objects for span nesting across system boundaries. Defaults to `false`. |
| `"durationMetric"` | `boolean` | Whether the span duration will be recorded in the `insights_trace_duration` histogram metric. Requires both the Traces and Metrics modules to be enabled. Defaults to `false`. |
| `"durationMetricOnDisabledSpans"` | `boolean` | Whether the span duration will be recorded in the `insights_trace_duration` metric even when the span itself is disabled. |
| `"enabled"` | `boolean` | If `true` (default), the matching span will be created. If `false`, the operation will be a no-op. |
| `"forceChildTracing"` | `boolean` | If `true`, any child spans (including nested spans across system boundaries) will be forced to be traced, even if their own filter configuration disables them. Defaults to `false`. |
| `"level"` | `"OFF"` \| `"LOWEST"` \| `"DIAGNOSTIC"` \| `"DEBUG"` \| `"INFO"` \| `"WARN"` \| `"HIGHEST"` | Attribute verbosity level for the span. Defaults to `"INFO"`. |
| `"log"` | `boolean` | If `true`, enabled spans will also be published as log entries via the io.Connect logging API. |
| `"logOnDisabledSpans"` | `boolean` | If `true`, disabled spans will also be published as log entries via the io.Connect logging API. |
| `"maxAttributeDepth"` | `number` | How deep the `addData()` method should recurse into objects when adding attributes to spans. Defaults to `3`. |
| `"minDurationMs"` | `number` | If specified, spans whose duration is lower than this value (in milliseconds) will not be sampled. Useful for filtering out short-lived spans such as quick app focus changes. |
| `"otelSpanOptions"` | `object` | OpenTelemetry span options. Accepts `"kind"` (SpanKind: `0` = INTERNAL, `1` = SERVER, `2` = CLIENT, `3` = PRODUCER, `4` = CONSUMER), `"attributes"`, `"links"`, `"startTime"`, and `"root"`. |
| `"overrideDefaultFilters"` | `boolean` | If `true`, this filter rule will be matched before any default filters provided by the platform. Default filters reduce verbosity by not tracing some internal operations. Defaults to `false`. |
| `"resultMetric"` | `boolean` | Whether the span will be counted in the `insights_trace_result` metric, which includes the final span status (OK or error) as an attribute. Requires both the Traces and Metrics modules to be enabled. Defaults to `false`. |
| `"resultMetricOnDisabledSpans"` | `boolean` | Whether the span will be counted in the `insights_trace_result` metric even when the span itself is disabled. |
| `"sample"` | `boolean` \| `number` | Sampling setting. If `true`, the span will be sampled. If `false`, it won't be sampled. If a number between `0` and `1`, it represents the sampling probability. Defaults to `true`. |
| `"source"` | `string` | Specifies the source string used for matching spans (operation name). Start the string with `#` for case-insensitive regex matching. |
| `"stopPropagationIfSpanIsDisabled"` | `boolean` | If a span is disabled by its filter, setting this to `true` will stop the propagation of trace nesting info across it, preventing subsequent spans from being nested under the disabled span's parent. |

The `"defaults"` object accepts the same properties as a filter entry (except `"source"` and `"context"`) and is used as a fallback when no matching filter is found.

#### Default Span Filters

When `"useDefaultFilters"` is set to `true` (the default), the platform applies a predefined set of span filters that reduce the default verbosity of the published trace data. These default filters disable tracing for internal platform operations and prevent certain spans from starting new traces. They are evaluated before any user-defined filters (unless a user filter has `"overrideDefaultFilters"` set to `true`).

The following is the full list of default span filters applied by the platform:

```json
[
    {
        "source": "interopio.api.appStartup.finished",
        "enabled": false,
        "context": {
            "tracingAppName": "web-group-application"
        }
    },
    {
        "source": "interopio.api.startup",
        "enabled": false,
        "context": {
            "tracingAppName": "web-group-application"
        }
    },
    {
        "source": "interopio.desktop.workspaces.open",
        "canBeRoot": true
    },
    {
        "source": "interopio.desktop.startup",
        "canBeRoot": true
    },
    {
        "source": "interopio.api.interop.register.callback",
        "disableNesting": true
    },
    {
        "source": "interopio.desktop.app.start",
        "canBeRoot": true
    },
    {
        "source": "interopio.desktop.userJourney",
        "canBeRoot": true
    },
    {
        "source": "interopio.desktop.layouts.restore",
        "canBeRoot": true
    },
    {
        "source": "interopio.desktop",
        "canBeRoot": false
    },
    {
        "source": "interopio.desktop.internal",
        "canBeRoot": false
    },
    {
        "source": "interopio.api.instrumentation.fetch",
        "canBeRoot": false
    },
    {
        "source": "interopio.api.instrumentation.xhr",
        "canBeRoot": false
    },
    {
        "source": "interopio.api.prefs",
        "canBeRoot": false
    },
    {
        "source": "interopio.api.layouts",
        "canBeRoot": false
    },
    {
        "source": "interopio.api.windows",
        "canBeRoot": false
    },
    {
        "source": "interopio.api.interop",
        "context": {
            "stream": "#^t42[.].*"
        },
        "canBeRoot": false,
        "enabled": false
    },
    {
        "source": "interopio.api.interop",
        "context": {
            "stream": "apps.event"
        },
        "canBeRoot": false,
        "enabled": false
    },
    {
        "source": "interopio.api.interop",
        "context": {
            "name": "#^t42[.].*"
        },
        "canBeRoot": false,
        "enabled": false
    },
    {
        "source": "interopio.api.interop",
        "context": {
            "name": "apps.event"
        },
        "canBeRoot": false,
        "enabled": false
    },
    {
        "source": "interopio.api.interop",
        "context": {
            "method": "apps.command"
        },
        "canBeRoot": false
    },
    {
        "source": "interopio.api.interop",
        "context": {
            "method": "#^t42[.].*"
        },
        "canBeRoot": false
    },
    {
        "source": "interopio.api.contexts",
        "context": {
            "context": "___insights_pi_storage___"
        },
        "enabled": false
    },
    {
        "source": "interopio.api.contexts",
        "context": {
            "context": "#^t42[.].*"
        },
        "canBeRoot": false
    },
    {
        "source": "interopio.api.contexts",
        "context": {
            "context": "#^__.*"
        },
        "canBeRoot": false
    },
    {
        "source": "interopio.api.appManager",
        "canBeRoot": false
    },
    {
        "source": "interopio.api.notifications",
        "canBeRoot": false
    }
]
```

To override a specific default filter, add a filter entry with the same `"source"` (and `"context"`, if applicable) in the `"filters"` array and set `"overrideDefaultFilters"` to `true`:

```json
{
    "otel": {
        "enabled": true,
        "traces": {
            "enabled": true,
            "url": "http://localhost:4318/v1/traces",
            "useDefaultFilters": true,
            "filters": [
                {
                    "source": "interopio.api.layouts",
                    "overrideDefaultFilters": true,
                    "canBeRoot": true
                }
            ]
        }
    }
}
```

To disable all default span filters entirely, set `"useDefaultFilters"` to `false`.

### Sampling

You can use the `"sampling"` property of the `"traces"` object to control the sampling of completed spans before they are exported. While filters control whether a span is created, sampling rules control whether an already-created span is exported based on its name, attributes, or context. This is useful for reducing the volume of exported trace data without disabling tracing entirely.

The following example demonstrates how to sample only 10% of Interop invocation spans, while keeping all other spans:

```json
{
    "otel": {
        "enabled": true,
        "traces": {
            "enabled": true,
            "url": "http://localhost:4318/v1/traces",
            "sampling": [
                {
                    "name": "#interopio\\.api\\.interop\\.invoke",
                    "sample": 0.1
                }
            ]
        }
    }
}
```

Each object in the `"sampling"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"attributes"` | `object` | Span attributes that determine if the span will match this sampling entry. Values are strings, numbers, or booleans. Start string values with `#` for case-insensitive regex matching. |
| `"context"` | `object` | Context values that determine if the span will match this sampling entry. Values are strings, numbers, or booleans. Start string values with `#` for case-insensitive regex matching. |
| `"name"` | `string` | Span name used to match this sampling entry. Start the string with `#` for case-insensitive regex matching. |
| `"sample"` | `boolean` \| `number` | **Required.** Probability that the span will be sampled based on its trace ID. If `true`, the span will always be sampled. If `false`, it will never be sampled. If a number between `0` and `1`, it represents the sampling probability. |

### User Journey

The User Journey trace tracks app focus changes across the platform, creating spans for each user navigation step. You can enable, disable, or configure this feature using the `"userJourney"` property of the `"traces"` object.

The `"userJourney"` property can be set to:

- `true` or `false` to enable or disable the User Journey trace.
- `"nested"` or `"sibling"` to control the span structure - `"nested"` creates child spans under a parent, `"sibling"` creates independent linked spans.
- An object with the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"descriptiveName"` | `boolean` | If `true` (default), the User Journey trace span names will include the name of the focused app. |
| `"enabled"` | `boolean` | If `true`, the User Journey trace will be enabled. |
| `"structure"` | `"nested"` \| `"sibling"` | Span structure of User Journey traces. Defaults to `"sibling"`. |

### Click Stream

The Click Stream trace tracks user interactions with DOM elements in web apps, creating spans for each captured event. You can enable, disable, or configure this feature using the `"clickstream"` property of the `"traces"` object.

The `"clickstream"` property can be set to:

- `true` or `false` to enable or disable the Click Stream trace.
- `"nested"` or `"sibling"` to control the span structure.
- An object with the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"descriptiveName"` | `boolean` | If `true` (default), the Click Stream trace span names will include the app name (e.g., `interopio.api.clickstream.<appName>.<event>`). If `false`, span names will be `interopio.api.clickstream.<event>`. |
| `"enabled"` | `boolean` | If `true`, the Click Stream trace will be enabled. |
| `"events"` | `string[]` | List of DOM event names to capture as Click Stream trace spans. Defaults to `["click"]`. |
| `"structure"` | `"nested"` \| `"sibling"` | Span structure of Click Stream traces. Defaults to `"sibling"`. |

The following example demonstrates how to configure the Click Stream trace to capture both click and double-click events:

```json
{
    "otel": {
        "enabled": true,
        "traces": {
            "enabled": true,
            "url": "http://localhost:4318/v1/traces",
            "clickstream": {
                "enabled": true,
                "structure": "sibling",
                "events": ["click", "dblclick"]
            }
        }
    }
}
```

### Resource & Span Attributes

You can customize the OpenTelemetry resource-level attributes and the span attributes using the `"additionalResourceAttributes"` and `"additionalAttributes"` properties of the `"traces"` object. These are merged with (and take precedence over) the respective top-level settings.

If you set `"addResourceAttributesToAttributes"` to `true`, all resource-level attributes will be copied into every span, making them available for filtering and querying in your traces backend.

> ℹ️ *For details on the common resource-level attributes published by **io.Connect Desktop**, see the [Signals > Overview > Common Resource Attributes](https://docs.interop.io/insights/signals/overview/index.md#common_resource_attributes) section.*

The following example demonstrates how to add custom resource and span attributes to traces:

```json
{
    "otel": {
        "enabled": true,
        "traces": {
            "enabled": true,
            "url": "http://localhost:4318/v1/traces",
            "additionalResourceAttributes": {
                "deployment.environment": "production",
                "team": "platform-engineering"
            },
            "additionalAttributes": {
                "datacenter": "%DATACENTER_NAME%"
            },
            "addResourceAttributesToAttributes": true
        }
    }
}
```

## Logs

Available since io.Connect Desktop 10.1

To provide custom settings for publishing logs, use the `"logs"` property of the `"otel"` object.

The `"logs"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"additionalAttributes"` | `object` | Additional log attributes to publish as part of each log entry, specified as key/value pairs. You can use environment variables as values. Environment variables must start and end with a percent sign (e.g., `%MyEnvVar%`), and can contain a fallback value (e.g., `%MyEnvVar?DefaultValue%`). |
| `"additionalResourceAttributes"` | `object` | Additional attributes to publish as part of the OpenTelemetry resource definition for log signals, specified as key/value pairs. You can use environment variables as values. Environment variables must start and end with a percent sign (e.g., `%MyEnvVar%`), and can contain a fallback value (e.g., `%MyEnvVar?DefaultValue%`). |
| `"addResourceAttributesToAttributes"` | `boolean` | Whether to add resource attributes to log record attributes. Defaults to `false`. Signal-level setting takes precedence over the top-level one. |
| `"defaults"` | `object` | Default log filter options used as a fallback when no matching filter entry is found. |
| `"enabled"` | `boolean` | If `true`, will enable publishing logs. Defaults to `false`. |
| `"exporterSettings"` | `object` | Settings for the OTLP exporter used to send logs. Provides fine-grained control over the OTLP log exporter HTTP transport. |
| `"filters"` | `object[]` | Array of filter entries used to determine whether a particular log entry will be emitted, and which attributes will be included. If no matching filter entry is found, the settings from `"defaults"` are used. |
| `"headers"` | `object` | Additional headers to send with log export HTTP requests, specified as key/value pairs where values are strings. Merged with and takes precedence over the top-level `"headers"` setting. |
| `"keepAlive"` | `boolean` | If `true` (default), the HTTP connection will be kept alive when sending logs. |
| `"maxAttributeDepth"` | `number` | Maximum depth for flattening nested objects into log attributes. Defaults to `5`. |
| `"url"` | `string` | URL pointing to an OpenTelemetry logs collector. |
| `"useSSOAuth"` | `boolean` | If `true`, the platform SSO login information will be used when making log export requests. Takes precedence over the top-level `"useSSOAuth"` setting. Defaults to `false`. |
| `"useSSOAuthRawToken"` | `boolean` | Used when the SSO login information contains a `token` property. If `true` (default), the `token` will be used as-is. If `false`, the `token` may be prepended with `"Bearer "`. Takes precedence over the top-level setting. |

The following sections describe the configuration settings for the main features related to publishing logs with **io.Insights**.

> ℹ️ *For details on all available settings for configuring **io.Insights**, see the `otel.json` [configuration schema](https://docs.interop.io/desktop/assets/configuration/otel.json).*

### Log Filters

You can use the `"filters"` property of the `"logs"` object to control which log entries are published and which attributes are included. Each filter entry matches log records by category name, severity, and/or body content. When a log entry is emitted, the filter list is searched for a matching entry, and the settings from that entry are applied. If no match is found, the settings from `"defaults"` are used.

The following example demonstrates how to filter log entries by severity and category, and how to redact sensitive data:

```json
{
    "otel": {
        "enabled": true,
        "logs": {
            "enabled": true,
            "url": "http://localhost:4318/v1/logs",
            "filters": [
                {
                    "severity": "DEBUG",
                    "enabled": false
                },
                {
                    "categoryName": "auth",
                    "hideRegex": "(password|secret|token)=[^&\\s]+"
                },
                {
                    "categoryName": "app-own-log",
                    "allowedAttributes": ["applicationName", "instanceId", "loggerName"]
                }
            ],
            "defaults": {
                "enabled": true
            }
        }
    }
}
```

Each object in the `"filters"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"allowedAttributes"` | `string[]` | List of allowed attributes for the log entry. If specified, any attributes missing from the list will be removed before publishing. |
| `"bodyRegex"` | `string` | Regex pattern used to match the text body of the log entry. |
| `"categoryName"` | `string` | Used to match the category of the log entry. |
| `"enabled"` | `boolean` | If `true`, the matching log entry will be published. |
| `"hideRegex"` | `string` | Regex pattern for redacting sensitive log data. Text matching this regex will be replaced with asterisks. |
| `"severity"` | `"TRACE"` \| `"DEBUG"` \| `"INFO"` \| `"WARN"` \| `"ERROR"` \| `"FATAL"` | Used to match the severity of the log entry. |

The `"defaults"` object accepts the same properties as a filter entry (except `"categoryName"`, `"severity"`, and `"bodyRegex"`) and is used as a fallback when no matching filter is found.

### Resource & Log Attributes

You can customize the OpenTelemetry resource-level attributes and the log record attributes using the `"additionalResourceAttributes"` and `"additionalAttributes"` properties of the `"logs"` object. These are merged with (and take precedence over) the respective top-level settings.

If you set `"addResourceAttributesToAttributes"` to `true`, all resource-level attributes will be copied into every log record, making them available for filtering and querying in your logs backend.

> ℹ️ *For details on the common resource-level attributes published by **io.Connect Desktop**, see the [Signals > Overview > Common Resource Attributes](https://docs.interop.io/insights/signals/overview/index.md#common_resource_attributes) section.*

The following example demonstrates how to add custom resource and log record attributes:

```json
{
    "otel": {
        "enabled": true,
        "logs": {
            "enabled": true,
            "url": "http://localhost:4318/v1/logs",
            "additionalResourceAttributes": {
                "deployment.environment": "production",
                "team": "platform-engineering"
            },
            "additionalAttributes": {
                "datacenter": "%DATACENTER_NAME%"
            },
            "addResourceAttributesToAttributes": true
        }
    }
}
```
