Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .aiAutoMinify.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@
},
"@microsoft/applicationinsights-osplugin-js": {
"constEnums": []
},
"@microsoft/applicationinsights-otlpchannel-js": {
"constEnums": [
"eOtlpSignal",
"eOtlpSpanKind",
"eOtlpStatusCode",
"eOtlpSeverityNumber",
"ePropertyType"
]
}
}
}
11 changes: 11 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@

<!-- ## Unreleased Changes -->

## Unreleased Changes

### New: OTLP/JSON Channel (`@microsoft/applicationinsights-otlpchannel-js` 0.1.0)

- Added a new preview channel that converts telemetry to [OTLP/JSON](https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md) in memory and exports it to an OpenTelemetry Protocol (OTLP) HTTP endpoint (`/v1/traces` and `/v1/logs`). It requires no `@opentelemetry/*` dependency and can be used on its own or alongside the existing sender, which forwards every item along the chain (the tee channel is only needed when the channels must be in separate queues).
- Conversion and serialization happen on the `processTelemetry` path as each item is received, and records are buffered pre-grouped by resource and signal with incremental byte accounting, so sending a batch performs no conversion work. This keeps the page unload path as fast as possible.
- `RequestData` / `RemoteDependencyData` / `PageviewData` are exported as spans and `MessageData` / `ExceptionData` / `EventData` / `PageviewPerformanceData` as log records. Native Common Schema spans (`OTelSpan`) are exported as spans directly, preserving their kind, parent, trace state and status. Context tags are promoted onto the OTLP `Resource`; everything else becomes record attributes, with Application Insights specific values namespaced under `microsoft.`.
- Values that the Common Schema marks as PII or customer content are dropped by default (configurable via `piiMode`), since OTLP has no equivalent marker.
- Implements `getOfflineSupport()` so it can be combined with `@microsoft/applicationinsights-offlinechannel-js`.
- Added `examples/otlp`, a multi page test site that runs two independent SDK instances per page against a local mock OTLP collector. It can be driven manually or run headlessly (`npm test`), and validates the OTLP envelope, resource attributes, span/log field validity, nanosecond timestamp precision, attribute well-formedness, and that the two instances stay fully isolated from each other.

## 3.4.3 (July 2nd, 2026)

This is a maintenance release for the 3.4.x version line adding a new SDK statistics feature, a PostChannel reliability fix, and dependency security hardening. The `@microsoft/1ds-post-js` channel is numbered 4.4.3 and requires v3.4.3.
Expand Down
21 changes: 21 additions & 0 deletions channels/otlp-channel-js/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# NPM Ignore

# ignore everything
*

# ... but these files
!package.json
!tsconfig.json
!dist-es*/**
!dist/**
!browser/**
!types/**
!/CODE_OF_CONDUCT.md
!/CONTRIBUTING.md
!/README.md
!/SECURITY.md
!/SUPPORT.md
!/NOTICE
!/PRIVACY
!/LICENSE
!/LICENSE.TXT
21 changes: 21 additions & 0 deletions channels/otlp-channel-js/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) Microsoft Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
17 changes: 17 additions & 0 deletions channels/otlp-channel-js/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
NOTICES AND INFORMATION
Do Not Translate or Localize

This software incorporates material from third parties. Microsoft makes certain
open source code available at https://3rdpartysource.microsoft.com, or you may
send a check or money order for US $5.00, including the product name, the open
source component name, and version number, to:

Source Code Compliance Team
Microsoft Corporation
One Microsoft Way
Redmond, WA 98052
USA

Notwithstanding any other terms, you may reverse engineer this software to the
extent required to debug changes to any libraries licensed under the GNU Lesser
General Public License.
3 changes: 3 additions & 0 deletions channels/otlp-channel-js/PRIVACY
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Data Collection

The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices.
247 changes: 247 additions & 0 deletions channels/otlp-channel-js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
# Microsoft Application Insights JavaScript SDK - OTLP/JSON Channel

An Application Insights channel that converts telemetry into [OTLP/JSON](https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md)
and exports it to an OpenTelemetry Protocol (OTLP) HTTP endpoint.

The channel sits at the end of the plugin chain and receives every telemetry item the SDK produces
(`trackEvent`, `trackTrace`, `trackException`, `trackPageView`, `trackDependencyData`, and any spans
created through `startSpan`), converts it in memory, and POSTs it to `/v1/traces` and `/v1/logs`.

No `@opentelemetry/*` package is required.

## Getting Started

### Install

```bash
npm install --save @microsoft/applicationinsights-otlpchannel-js
```

### Basic usage

A channel must be supplied through the `channels` configuration, not `extensions`.

```js
import { ApplicationInsights } from "@microsoft/applicationinsights-web";
import { OtlpChannel } from "@microsoft/applicationinsights-otlpchannel-js";

const otlpChannel = new OtlpChannel();

const appInsights = new ApplicationInsights({
config: {
instrumentationKey: "YOUR_INSTRUMENTATION_KEY",
channels: [[ otlpChannel ]],
extensionConfig: {
[otlpChannel.identifier]: {
endpointUrl: "https://your-collector.example.com"
}
}
}
});

appInsights.loadAppInsights();
```

### Exporting to both Application Insights and an OTLP collector

Use the tee channel to send the same telemetry to more than one channel queue.

```js
import { ApplicationInsights } from "@microsoft/applicationinsights-web";
import { TeeChannel } from "@microsoft/applicationinsights-teechannel-js";
import { OtlpChannel } from "@microsoft/applicationinsights-otlpchannel-js";

const teeChannel = new TeeChannel();
const otlpChannel = new OtlpChannel();

const appInsights = new ApplicationInsights({
config: {
instrumentationKey: "YOUR_INSTRUMENTATION_KEY",
channels: [[ teeChannel ], [ otlpChannel ]],
extensionConfig: {
[otlpChannel.identifier]: {
endpointUrl: "https://your-collector.example.com"
}
}
}
});
```

## How it works

The channel converts each telemetry item into its **final OTLP representation as the item is
received**, not when a batch is sent. Converted records are serialized immediately and appended to
buffers that are already grouped by resource and signal, with the payload size tracked
incrementally.

Sending a batch is therefore only a string join and an HTTP POST -- no mapping, no attribute
building and no serialization. This matters most during page unload, where the browser gives the
page very little time to finish its work.

Set `preSerialize: false` to keep the converted objects and serialize the whole payload at send
time instead. The item to OTLP conversion still happens at ingress in that mode.

## Signal mapping

| Application Insights `baseType` | OTLP |
| --- | --- |
| `RequestData` | Span, `kind = SERVER` |
| `RemoteDependencyData` | Span, `kind = CLIENT` (or `INTERNAL` for an `InProc` dependency) |
| `PageviewData` | Span, `kind = INTERNAL` (configurable, see `pageViewAs`) |
| `MessageData` | LogRecord |
| `ExceptionData` | LogRecord with the `exception.*` attributes |
| `EventData` | LogRecord with `eventName` |
| `PageviewPerformanceData` | LogRecord |
| `MetricData` | Ignored unless `metricsAsLogs` is enabled (the OTLP metrics signal is not supported yet) |

Context tags such as `ai.cloud.role`, `ai.cloud.roleInstance` and `ai.application.ver` are promoted
onto the OTLP `Resource` as `service.name`, `service.instance.id` and `service.version`, so they are
not repeated on every record. Everything else -- custom properties, measurements, Part C, the Part A
extensions and the remaining tags -- becomes record attributes. Values that have no OpenTelemetry
semantic convention equivalent are emitted under the `microsoft.` namespace.

## Configuration

All values below are supplied under the `OtlpChannel` key of `extensionConfig` and may be changed at
runtime.

| Name | Default | Description |
| --- | --- | --- |
| `endpointUrl` | | The base OTLP/HTTP endpoint. `/v1/traces` and `/v1/logs` are appended. |
| `tracesEndpointUrl` | | The complete url used to export spans, overrides `endpointUrl`. |
| `logsEndpointUrl` | | The complete url used to export log records, overrides `endpointUrl`. |
| `headers` | | Additional headers added to every request, typically for authentication. |
| `resourceAttributes` | | Additional resource attributes, these override the derived values. |
| `scopeName` | `@microsoft/applicationinsights-web` | The reported instrumentation scope name. |
| `scopeVersion` | package version | The reported instrumentation scope version. |
| `preSerialize` | `true` | Serialize each record as it is received rather than when it is sent. |
| `pageViewAs` | `"span"` | Whether a page view is exported as a `span` or a `log`. |
| `metricsAsLogs` | `false` | Export `MetricData` as log records instead of ignoring it. |
| `piiMode` | `"drop"` | How Common Schema PII / customer content values are handled: `drop`, `keep` or `hash`. |
| `maxBatchSizeInBytes` | `65536` | Send once this many bytes have been buffered. |
| `maxRecordsPerBatch` | `512` | Send once this many records have been buffered. |
| `maxBatchInterval` | `15000` | The maximum time (ms) to buffer records before sending. |
| `eventsLimitInMem` | `10000` | The maximum records held in memory, then the oldest are dropped. |
| `transports` | | The ordered transports to use when sending asynchronously. |
| `unloadTransports` | | The ordered transports to use during page unload. |
| `httpXHROverride` | | A user supplied transport used in preference to the built in transports. |
| `fetchCredentials` | | The `credentials` value used for `fetch` based requests. |
| `disableXhrSync` | `false` | Disable synchronous `XMLHttpRequest` during unload. |
| `disableFetchKeepAlive` | `false` | Disable `fetch` with `keepalive` during unload. |
| `xhrTimeout` | | The timeout (ms) applied to `XMLHttpRequest` based requests. |
| `maxRetryAttempts` | `6` | The maximum retries before a failed batch is discarded. |
| `maxUnloadRetryAttempts` | `2` | The maximum retries while the page is unloading. |
| `disableTelemetry` | `false` | Stop exporting, items still flow down the plugin chain. |
| `consumeEvents` | `false` | Stop passing items to the next plugin once converted. |
| `includeIKeyInResource` | `false` | Include the instrumentation key as a resource attribute. |

## Chaining after other channels

The channel calls `processNext`, sorts last by priority, and is discoverable by identifier, so it can
be placed behind other channels in the same channel queue:

| Channel | Priority |
| --- | --- |
| `TeeChannel` | 999 |
| `OfflineChannel` | 1000 |
| `Sender` (Application Insights) | 1001 |
| `PostChannel` (1DS) | 1011 |
| **`OtlpChannel`** | **1021** |

A custom SKU can therefore do:

```js
core.initialize({
instrumentationKey: "YOUR_KEY",
channels: [[ offlineChannel, otlpChannel ]]
}, []);
```

Two things are worth knowing:

**1. The offline channel must be told about it.** `OfflineChannel` resolves its "online" channel by
identifier from `primaryOnlineChannelId`, which defaults to
`[AppInsightsChannelPlugin, PostChannel]`. In a SKU that has neither, name the OTLP channel
explicitly, otherwise the offline channel finds no online channel and silently persists nothing:

```js
extensionConfig: {
["OfflineChannel"]: { primaryOnlineChannelId: [ otlpChannel.identifier ] },
["OtlpChannel"]: { endpointUrl: "https://your-collector.example.com" }
}
```

Because this channel implements `getOfflineSupport()`, the offline channel will then persist and
replay **OTLP payloads against the OTLP endpoint**.

**2. A channel that consumes items starves anything after it.** While the browser is offline the
offline channel caches the item and returns *without* calling `processNext`, by design. Anything
chained after it therefore receives nothing until connectivity returns &mdash; which is exactly why the
offline channel needs to be pointed at this channel rather than chained in front of it and ignored.

Set `consumeEvents: true` if this channel is genuinely last and nothing after it should see the item.

## Privacy

The Common Schema marks individual fields as PII or customer content, and OTLP has no equivalent
marker. By default (`piiMode: "drop"`) any value carrying such a marker is **omitted** from the
exported payload. Set `piiMode` to `"hash"` to export a stable non reversible hash instead, or to
`"keep"` to export the value along with a `microsoft.pii.<key>` marker attribute so that a
downstream collector can scrub it.

Note that custom headers cannot be sent using `navigator.sendBeacon`, and that a collector must
allow the CORS preflight that `application/json` with custom headers requires.

## Retries and partial success

Requests that fail with `408`, `429`, `500`, `502`, `503`, `504`, or that do not complete at all, are
retried with an exponential backoff (honouring any `Retry-After` header) up to `maxRetryAttempts`.

A `200` response whose body reports `partialSuccess` means the collector permanently rejected some
records; those are **not** retried. The rejection is logged and reported through the
`eventsDiscarded` notification.

## Offline support

`getOfflineSupport()` is implemented, so the channel can be combined with
`@microsoft/applicationinsights-offlinechannel-js` to persist and later replay OTLP payloads.

## Limitations

- The OTLP metrics signal (`/v1/metrics`) is not implemented.
- Span events and links are not populated.
- Telemetry created from a span has already been flattened into the Application Insights shape by
the time the channel sees it, so the conversion back to OTLP is not perfectly lossless. Custom
attributes are preserved verbatim through `baseData.properties`.

## Build

```bash
npm install
npm run build --silent
```

## Test

```bash
npm run test
```

## Data Collection

As this SDK is designed to enable applications to perform data collection which is sent to the
Microsoft collection endpoints the following is required to identify our privacy statement.

The software may collect information about you and your use of the software and send it to Microsoft.
Microsoft may use this information to provide services and improve our products and services. You may
turn off the telemetry as described in the repository. There are also some features in the software
that may enable you and Microsoft to collect data from users of your applications. If you use these
features, you must comply with applicable law, including providing appropriate notices to users of
your applications together with a copy of Microsoft's privacy statement. Our privacy statement is
located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection
and use in the help documentation and our privacy statement. Your use of the software operates as
your consent to these practices.

## License

[MIT](LICENSE)
Loading
Loading