Skip to content

Semantic conventions

Belemetry follows the OpenTelemetry data model and its semantic conventions, so a page view, a fetch or an exception arrives with the attribute names every OTLP backend already knows how to query. This page is the reference: what each record looks like, the resource that describes where it came from, the feature bit it belongs to, and what the script keeps in browser storage.

Feature bits

Every record belongs to exactly one feature, and is only collected while that feature is both switched on by configuration (options.Features) and granted by the user. The numbers are the same in C# (BelemetryFeatures) and in the script (Features), and they are what BitBelemetry.setConsent takes.

NameBitCovers
Errors1JS errors and unhandled rejections; .NET logs at Error/Critical or carrying an exception; TrackException
PageViews2Page views (history/enhanced navigation, TrackPageView)
Interactions4Clicks and other user interactions
Performance8Web vitals (LCP, INP, CLS, FCP, TTFB), document-load span, resource timing, long tasks
Dependencies16Browser fetch/XHR client spans
Sessions32A session id that survives reloads (in sessionStorage). Without it, the session id lives in memory only
UserTracking64enduser.pseudo.id (random id persisted in localStorage) and user.id (authenticated id from SetUser)
Logs128.NET logs below Error; browser console capture below error
Traces256.NET Activity spans
Metrics512.NET Meter metrics
Persistence1024Keeping unsent telemetry on the device (localStorage / files) for retry after going offline or reloading
Events2048Custom events (TrackEvent)
GroupValueMembers
Diagnostics401Errors, Logs, Traces, Dependencies
Analytics2150PageViews, Interactions, Sessions, UserTracking, Events
Monitoring520Performance, Metrics
All4095Every feature

BelemetryFeatures Enum

The independently consentable parts of Belemetry. Every telemetry record belongs to exactly one feature, and a record is only sent while its feature is both enabled by configuration and granted by the user.

Value Number Description
None 0 Nothing.
Errors 1 JS errors and unhandled rejections, .NET logs at Error/Critical or carrying an exception, and TrackException.
PageViews 2 Page views - history and enhanced navigation, and TrackPageView.
Interactions 4 Clicks and other user interactions.
Performance 8 Web vitals (LCP, INP, CLS, FCP, TTFB), the document-load span, resource timing and long tasks.
Dependencies 16 Browser fetch/XHR client spans.
Sessions 32 A session id that survives page reloads (kept in sessionStorage). Without it the session id lives in memory only.
UserTracking 64 The pseudonymous user id (enduser.pseudo.id, persisted on the device) and the authenticated user id (user.id).
Logs 128 .NET logs below Error, and browser console capture below error.
Traces 256 .NET Activity spans.
Metrics 512 .NET Meter metrics.
Persistence 1024 Keeping unsent telemetry on the device (browser storage or files) to retry it after going offline or restarting.
Events 2048 Custom events (TrackEvent).
Diagnostics 401 Errors, logs, traces and dependencies - what is needed to troubleshoot the app.
Analytics 2150 Page views, interactions, sessions, user tracking and custom events - what describes how the app is used.
Monitoring 520 Web vitals and metrics - how the app performs.
All 4095 Every feature.

Browser records

Events are log records with an eventName, the way the OpenTelemetry Events API models them. Spans use the OTLP span kinds (1 internal, 2 server, 3 client) and status codes (0 unset, 1 ok, 2 error), and log severities use the OTLP SeverityNumber. Times are milliseconds since the Unix epoch, from performance.timeOrigin + performance.now().

RecordShapeScopeFeature
Page view Log record, eventName = "browser.page_view". Attributes: url.full, url.path, page.title, page.referrer (redacted), browser.navigation.type (initial/push/replace/pop/hash/manual) bit.belemetry.page_views PageViews
Page visit time Log record, eventName = "browser.page_visit_time", only with TrackPageVisitTime: emitted for the previous page when the next page view starts, and for the current page when it is hidden. Attributes: url.full, url.path, page.title, page.visit.duration (ms) bit.belemetry.page_views PageViews
Click Log record, eventName = "browser.user_interaction". Attributes: event.type, target.element, target.id, target.name (data-bit-belemetry-name, aria-label, then name), target.text (only with captureText), target.xpath. Elements under [data-bit-belemetry-ignore] are skipped bit.belemetry.interactions Interactions
Web vital Log record, eventName = "browser.web_vital". Attributes: web_vital.name (LCP/INP/CLS/FCP/TTFB), web_vital.value, web_vital.delta, web_vital.rating (good/needs-improvement/poor), web_vital.id, web_vital.navigation_type bit.belemetry.web_vitals Performance
Document load Internal span documentLoad, with events domInteractive, domContentLoadedEventEnd, loadEventEnd, ... from PerformanceNavigationTiming bit.belemetry.document_load Performance
Resource timing Internal span resourceFetch with url.full, http.response.body.size, network.protocol.name bit.belemetry.resources Performance
Long task Internal span longtask bit.belemetry.long_tasks Performance
fetch/XHR Client span {METHOD}. Attributes: http.request.method, url.full, server.address, server.port, http.response.status_code, error.type. Adds traceparent only for targets matched by propagateTraceContextTo bit.belemetry.http Dependencies
JS error Log record, severity 17 (ERROR), eventName = "exception". Attributes: exception.type, exception.message, exception.stacktrace bit.belemetry.errors Errors
Console Log record at the console call's level (with captureConsole, for the levels in consoleLevels) bit.belemetry.console Errors at error, Logs below
Custom event Log record, eventName = the name passed to trackEvent, with its attributes bit.belemetry.events Events
Common (every record) session.id. enduser.pseudo.id and user.id only with UserTracking

.NET records

RecordShape
ILogger entry Log record with the category as its scope, the severity mapped from the LogLevel, the structured values as attributes, log.event.id and log.event.name (from the EventId, when set), the values of active scopes (Logs.IncludeScopes), log.record.template (with Logs.IncludeMessageTemplate), and the current trace and span id
ILogger entry with an exception The same, plus exception.type, exception.message, exception.stacktrace - feature Errors
Activity A span with the activity's kind, status, tags as attributes, events and links, scoped by its ActivitySource
Meter instrument Counters and up-down counters as sums, histograms with explicit buckets, gauges as last values; past the cardinality limit, an otel.metric.overflow = true point
TrackEvent / TrackPageView / TrackException The same records as their browser counterparts: an event log record, a browser.page_view log record, an exception log record

Resource attributes

The resource describes the producer rather than the event, and travels once per batch. The first eight are common to both sides; the rest say which side the record came from.

AttributeValueSide
service.nameServiceName, else OTEL_SERVICE_NAME, else the entry assembly nameboth
service.versionServiceVersion, else the entry assembly's informational versionboth
service.namespaceServiceNamespaceboth
service.instance.idServiceInstanceId; else, on a server, the platform's instance name (WEBSITE_INSTANCE_ID, CONTAINER_APP_REPLICA_NAME) or the machine name; else a random id per process, and always a random id per page load in the browserboth
deployment.environment.nameEnvironmentboth
telemetry.sdk.namebit-belemetryboth
telemetry.sdk.languagedotnet / webjsboth
telemetry.sdk.versionThe package versionboth
process.runtime.name, .version, .description.NET, the runtime version and framework description.NET
os.type, os.description, host.archThe operating system and process architecture.NET
process.pidThe process id (not in WebAssembly).NET
host.name, process.executable.name, process.ownerThe machine name, the executable and the account the process runs as (server only - a device's are its owner's).NET
container.idFrom /proc/self/mountinfo or /proc/self/cgroup (server only, Linux).NET
cloud.provider, cloud.platform, cloud.region, cloud.resource_id, host.id, azure.*Azure App Service, Functions or Container Apps, from their environment variables (server only, with UseEnvironmentVariables).NET
browser.language, browser.mobile, browser.platform, browser.brandsFrom navigator and User-Agent Client Hints, where availablebrowser
user_agent.originalThe user agent string (with Privacy.CollectUserAgent)browser

options.ResourceAttributes adds your own, and outside the browser OTEL_RESOURCE_ATTRIBUTES is merged in first, so explicit options win.

Browser storage keys

Belemetry sets no cookies. These are the only keys it writes, and each one is gated by the feature it serves.

KeyStorageGated byContent
bit-belemetry-consentlocalStoragealways (strictly necessary: records the choice itself){"v":1,"features":<int>,"time":<ms>}
bit-belemetry-sessionsessionStorageSessions{"id":"<32 hex>","start":<ms>,"last":<ms>}
bit-belemetry-pseudo-idlocalStorageUserTracking32 hex chars
bit-belemetry-user-idsessionStorageUserTrackingauthenticated id from setUser
bit-belemetry-queuelocalStoragePersistence[{"id","exporter","url","contentType","body"(base64),"time"}], capped by persistence.maxBytes

Revoking a feature clears its key: Persistence removes the queue, Sessions the stored session, and UserTracking the pseudo id and the user id.

Browser configuration

<BelemetryScript /> writes this object into <script type="application/json" id="bit-belemetry-config">, built from the server's BelemetryOptions, and the module starts from it on load. <BelemetryInitializer /> passes the same object to start(config), which is idempotent. Without .NET, pass it to BitBelemetry.start yourself - every field is optional.

{
  "service": { "name": "MyApp", "version": "1.0.0", "namespace": null, "instanceId": null, "environment": "Production" },
  "resource": { "any.attribute": "value" },             // extra resource attributes
  "sdkVersion": "10.6.2",
  "transport": "direct",                                 // "direct" (JS exports itself) | "relay" (JS hands records to .NET)
  "exporters": [
    { "type": "otlp", "endpoint": "http://localhost:4318", "tracesEndpoint": null, "logsEndpoint": null,
      "protocol": "http/protobuf", "headers": { "x-api-key": "..." }, "compression": "none", "signals": 3 },   // protocol: http/protobuf | http/json ; compression: none | gzip
    { "type": "azureMonitor", "connectionString": "InstrumentationKey=...;IngestionEndpoint=https://...", "maskIp": true,
      "compression": "none", "signals": 3 },
    { "type": "console" }
  ],
  "features": 4095,                                      // instrumentations switched on by configuration
  "consent": { "default": 0, "persist": true, "honorGlobalPrivacyControl": true, "pendingLimit": 500 },
  "pageViews": { "trackHashChanges": false },
  "interactions": { "events": ["click"], "captureText": false, "maxTextLength": 64 },
  "performance": { "webVitals": true, "documentLoad": true, "resources": false, "longTasks": false },
  "dependencies": { "fetch": true, "xhr": true, "propagateTraceContextTo": ["same-origin"], "ignoreUrls": ["/_framework/", "/_blazor", "/_content/"] },
  "errors": { "ignoreMessages": ["ResizeObserver loop"] },
  "logs": { "captureConsole": false, "consoleLevels": ["error", "warn"] },
  "privacy": { "redactQueryParameters": ["token","code","password","pwd","secret","key","apikey","api_key","auth","authorization","session","sid","sig","signature","email","access_token","id_token","refresh_token"],
               "stripQueryString": false, "stripFragment": true, "scrubPatterns": true, "collectUserAgent": true, "blockedAttributes": [] },
  "session": { "inactivityTimeoutMinutes": 30, "maxDurationMinutes": 1440 },
  "sampling": { "sessionRatio": 1.0 },
  "batch": { "maxQueueSize": 1024, "maxBatchSize": 100, "flushIntervalMs": 5000 },
  "persistence": { "enabled": true, "maxBytes": 1048576, "maxAgeHours": 48, "retryIntervalMs": 60000 },
  "debug": false
}
  • propagateTraceContextTo entries are "same-origin", "*", or a regex source matched against the absolute URL.
  • ignoreUrls and ignoreMessages are regex sources.

The constants

BelemetrySemanticConventions holds every attribute and event name above as a const string, for processors and custom exporters that read or write them - so a typo is a compile error rather than an attribute nobody queries.

BelemetrySemanticConventions Static class

The OpenTelemetry semantic-convention attribute and event names Belemetry emits and understands.

Name Type and default Description
ServiceName string= "service.name" service.name
ServiceVersion string= "service.version" service.version
ServiceNamespace string= "service.namespace" service.namespace
ServiceInstanceId string= "service.instance.id" service.instance.id
DeploymentEnvironmentName string= "deployment.environment.name" deployment.environment.name
TelemetrySdkName string= "telemetry.sdk.name" telemetry.sdk.name
TelemetrySdkLanguage string= "telemetry.sdk.language" telemetry.sdk.language
TelemetrySdkVersion string= "telemetry.sdk.version" telemetry.sdk.version
OsType string= "os.type" os.type
OsDescription string= "os.description" os.description
HostArch string= "host.arch" host.arch
ProcessRuntimeName string= "process.runtime.name" process.runtime.name
ProcessRuntimeVersion string= "process.runtime.version" process.runtime.version
ProcessRuntimeDescription string= "process.runtime.description" process.runtime.description
ProcessPid string= "process.pid" process.pid
ProcessExecutableName string= "process.executable.name" process.executable.name
ProcessOwner string= "process.owner" process.owner
HostName string= "host.name" host.name
HostId string= "host.id" host.id
ContainerId string= "container.id" container.id
CloudProvider string= "cloud.provider" cloud.provider
CloudPlatform string= "cloud.platform" cloud.platform
CloudRegion string= "cloud.region" cloud.region
CloudResourceId string= "cloud.resource_id" cloud.resource_id
DeviceModelIdentifier string= "device.model.identifier" device.model.identifier
SessionId string= "session.id" session.id
EndUserPseudoId string= "enduser.pseudo.id" enduser.pseudo.id - a random identifier not linked to the user's real identity.
UserId string= "user.id" user.id - the authenticated user's identifier.
ExceptionType string= "exception.type" exception.type
ExceptionMessage string= "exception.message" exception.message
ExceptionStacktrace string= "exception.stacktrace" exception.stacktrace
HttpRequestMethod string= "http.request.method" http.request.method
HttpResponseStatusCode string= "http.response.status_code" http.response.status_code
HttpRoute string= "http.route" http.route
UrlFull string= "url.full" url.full
UrlPath string= "url.path" url.path
UrlQuery string= "url.query" url.query
UrlScheme string= "url.scheme" url.scheme
ServerAddress string= "server.address" server.address
ServerPort string= "server.port" server.port
ClientAddress string= "client.address" client.address
ErrorType string= "error.type" error.type
DbSystemName string= "db.system.name" db.system.name
DbQueryText string= "db.query.text" db.query.text
PageTitle string= "page.title" page.title
PageVisitDuration string= "page.visit.duration" page.visit.duration - how long a page was visited, in milliseconds.
BrowserLanguage string= "browser.language" browser.language
WebVitalName string= "web_vital.name" web_vital.name
WebVitalValue string= "web_vital.value" web_vital.value
LogCategory string= "log.category" log.category - the ILogger category name.
LogEventId string= "log.event.id" log.event.id - the EventId.Id of an ILogger entry.
LogEventName string= "log.event.name" log.event.name - the EventId.Name of an ILogger entry.
LogMessageTemplate string= "log.record.template" log.record.template - the message template of a structured ILogger entry.
PageViewEvent string= "browser.page_view" The event name of a page view log record.
PageVisitTimeEvent string= "browser.page_visit_time" The event name of a page visit time log record (how long the page view before it lasted).
UserInteractionEvent string= "browser.user_interaction" The event name of an interaction log record.
WebVitalEvent string= "browser.web_vital" The event name of a web vital log record.
ExceptionEvent string= "exception" The event name of an exception log record.
SdkName string= "bit-belemetry" The telemetry.sdk.name Belemetry reports.
An unhandled error has occurred. Reload 🗙