Table of Contents
Last updated: 6/17/2026

OpenTelemetry with Azure Monitor

In order to log OpenTelemetry signals into Azure Monitor, you need to obtain an Azure Monitor connection string. In order to set up Azure Monitor with log collection, follow the Azure Monitor guide from Microsoft Learn.

In short, in an Azure resource group you will need:

  • One Log Analytics Workspace resource.
  • One Application Insights resource that uses the analytics workspace resource.
  • The Application Insights resource has the connection string listed on the Overview page.

Afterwards, edit appsettings.json for the ShareAspace Service Host and all of the installed extensions to include APPLICATIONINSIGHTS_CONNECTION_STRING at the root level:

{
  "Logging": {
  // ...
  },
  // ...
  "APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=REDACTED;IngestionEndpoint=REDACTED;LiveEndpoint=REDACTED;ApplicationId=REDACTED"
}

The following properties may consequently be removed from the configuration files:

  • OTEL_EXPORTER_OTLP_ENDPOINT
  • OTEL_EXPORTER_OTLP_PROTOCOL
  • OTEL_EXPORTER_OTLP_HEADERS

Common use cases

The following section lists some useful KQL queries that can be used against the traces and exceptions tables in Application Insights.

Many of the queries below follow a common pattern:

  • first identifying relevant SpanId or ConnectionId values, then joining back
  • to the traces table to reconstruct the complete activity context.

User activities

Download

List all file downloads of managed files.

traces
| where message contains "File Downloaded"

Check request start and finish surrounding the file download event. Each SpanId is its own download.

traces
| extend
    SpanId = tostring(customDimensions["SpanId"])
| where message contains "File Downloaded"
| project SpanId
| distinct SpanId
| join kind=inner (
    traces
    | extend
        SpanId = tostring(customDimensions["SpanId"])
) on SpanId
| order by timestamp desc

Delete

List all delete requests (start and finish).

traces
| where customDimensions["Method"] == "DELETE"

List all traces for what the delete request did (between start and finish). Each SpanId is its own delete request trace.

traces
| extend
    SpanId = tostring(customDimensions["SpanId"])
| where customDimensions["Method"] == "DELETE"
| project SpanId
| distinct SpanId
| join kind=inner (
    traces
    | extend
        SpanId = tostring(customDimensions["SpanId"])
) on SpanId
| order by timestamp desc

Authentication token exchange ("Sign in")

While there is no explicit “sign in” in ShareAspace, a user exchanges an ID token for a ShareAspace access token by performing a POST request to authorization/token.

traces
| where customDimensions["Path"] contains "authorization/token"

To see what user "signed in", one can combine the token trade with the connection id. When using ShareAspace web, a user will request its own user information after login. Each unique ConnectionId represents one "sign in".

traces
| extend
    ConnectionId = tostring(customDimensions["ConnectionId"])
| where customDimensions["Path"] contains "authorization/token"
| project ConnectionId
| distinct ConnectionId
| join kind=inner (
    traces
    | extend
        ConnectionId = tostring(customDimensions["ConnectionId"])
    | where message startswith "Request starting"
    | where customDimensions["RequestPath"] startswith "/collection/user/"
) on ConnectionId
| order by timestamp asc

Failure identification

User trace

Tracing all failures from request start to finish. Each SpanId is its own failure request trace.

traces
| extend
    StatusCode = toint(customDimensions["StatusCode"]),
    SpanId = tostring(customDimensions["SpanId"])
| where StatusCode == 500
| project SpanId
| distinct SpanId
| join kind=inner (
    traces
    | extend
        SpanId = tostring(customDimensions["SpanId"])
) on SpanId
| order by timestamp desc

Check what the user was doing in the "session" where the failure happened.

traces
| extend
    StatusCode = toint(customDimensions["StatusCode"]),
    SpanId = tostring(customDimensions["SpanId"]),
    ConnectionId = tostring(customDimensions["ConnectionId"])
| where StatusCode == 500
| project ConnectionId
| distinct ConnectionId
| join kind=inner (
    traces
    | extend
        ConnectionId = tostring(customDimensions["ConnectionId"])
) on ConnectionId
| order by timestamp desc

Check what user had the issue.

traces
| extend
    StatusCode = toint(customDimensions["StatusCode"]),
    SpanId = tostring(customDimensions["SpanId"]),
    ConnectionId = tostring(customDimensions["ConnectionId"])
| where StatusCode == 500
| project ConnectionId
| distinct ConnectionId
| join kind=inner (
    traces
    | extend
        ConnectionId = tostring(customDimensions["ConnectionId"])
) on ConnectionId
| where customDimensions["RequestPath"] startswith "/collection/user/"
| order by timestamp desc

System activities

Host stop activities

traces
| extend
    EventId = tostring(customDimensions["EventId"]),
    EventName = tostring(customDimensions["EventName"])
| where EventName == "Stopped"
    or EventName == "Stop"
    or EventName == "AllServicesStopped"

Indexing activity

traces
| extend
    WorkName = tostring(customDimensions["WorkName"]),
    SpanId = tostring(customDimensions["SpanId"])
| where WorkName == "IndexRebuildingWork"

Checkpoint start to finish

traces
| extend
    SpanId = tostring(customDimensions["SpanId"]),
    EventName = tostring(customDimensions["EventName"])
| where EventName == "CheckpointStarted"
    or EventName == "CheckpointFinished"

Each SpanId represents everything that happened during one checkpoint activity.

traces
| extend
    SpanId = tostring(customDimensions["SpanId"])
| where message == "Checkpoint started"
| project SpanId
| distinct SpanId
| join kind=inner (
    traces
    | extend
        SpanId = tostring(customDimensions["SpanId"])
) on SpanId
| order by timestamp asc

Space create

List all space create requests.

traces
| extend
    RequestPath = tostring(customDimensions["RequestPath"]),
    SpanId = tostring(customDimensions["SpanId"])
| where customDimensions["typeName"] == "SpaceBootstrapWork"
| where customDimensions["EventName"] == "RunWorkStartedAfterWaitingForSlot"

Everything that happened during space create. Each unique SpanId represents one space create.

traces
| extend
    RequestPath = tostring(customDimensions["RequestPath"]),
    SpanId = tostring(customDimensions["SpanId"])
| where customDimensions["typeName"] == "SpaceBootstrapWork"
| where customDimensions["EventName"] == "RunWorkStartedAfterWaitingForSlot"
| project SpanId
| distinct SpanId
| join kind=inner (
    traces
    | extend
        SpanId = tostring(customDimensions["SpanId"])
) on SpanId
| order by timestamp desc

Similar examples:

traces
| extend
    ConnectionId = tostring(customDimensions["ConnectionId"])
| where customDimensions["Method"] == "POST"
| where customDimensions["Path"] startswith "/collection/space/"
| project ConnectionId
| distinct ConnectionId
| join kind=inner (
    traces
    | extend
        ConnectionId = tostring(customDimensions["ConnectionId"])
) on ConnectionId
| order by timestamp desc
traces
| extend
    SpanId = tostring(customDimensions["SpanId"])
| where customDimensions["Method"] == "POST"
| where customDimensions["Path"] startswith "/collection/space/"
| project SpanId
| distinct SpanId
| join kind=inner (
    traces
    | extend
        SpanId = tostring(customDimensions["SpanId"])
) on SpanId
| order by timestamp desc

License limits

It is only possible to find blocking license limits like exceeding number of origins, participants, or users. Unit-of-information and disk space is not blocking.

exceptions
| extend
    SpanId = tostring(customDimensions["SpanId"])
| where outerMessage contains "license limitation"
exceptions
| extend
    SpanId = tostring(customDimensions["SpanId"])
| where outerMessage contains "license limitation"
| distinct SpanId
| join kind=inner (
    traces
    | extend
        SpanId = tostring(customDimensions["SpanId"])
) on SpanId
| order by timestamp desc

Request limits

Requests that hit the request limiter (i.e. requests returning status code 429 - Too many requests).

traces
| extend
    StatusCode = toint(customDimensions["StatusCode"]),
    SpanId = tostring(customDimensions["SpanId"])
| where StatusCode == 429
| order by timestamp desc

Other requests that happened around the time of the too many requests responses.

traces
| extend
    StatusCode = toint(customDimensions["StatusCode"]),
    ConnectionId = tostring(customDimensions["ConnectionId"])
| where StatusCode == 429
| project ConnectionId
| distinct ConnectionId
| join kind=inner (
    traces
    | extend
        ConnectionId = tostring(customDimensions["ConnectionId"])
) on ConnectionId
| order by timestamp desc