Skip to content

feat: session and document URL as log resource entities#269

Open
martinkuba wants to merge 6 commits into
open-telemetry:prototype/browser-e2e-demofrom
martinkuba:martinkuba/entity-aware-logs
Open

feat: session and document URL as log resource entities#269
martinkuba wants to merge 6 commits into
open-telemetry:prototype/browser-e2e-demofrom
martinkuba:martinkuba/entity-aware-logs

Conversation

@martinkuba

Copy link
Copy Markdown
Contributor

Demonstrates recording browser.session (session.id) and browser.document (browser.document.url.full) as entities on the log resource, using a delegating EntityAwareLoggerProvider.

Related: discussion #265, #237.

martinkuba added 6 commits May 6, 2026 16:53
… + document URL

Adds a new packages/sdk-browser workspace with a multi-entity proxy
LoggerProvider. setEntity(e) keys by entity.type and rebuilds an inner
real LoggerProvider whose Resource is the base merged with all current
entities; processor instances are reused across rebuilds. ProxyLogger
resolves the current delegate on every emit so loggers obtained once
during init transparently pick up new entities.

Includes Entity factories for browser.session (session.id) and
browser.document (browser.document.url.full, matching open-telemetry#237), plus a
DocumentTracker that observes URL changes via popstate/hashchange and
patched pushState/replaceState.

Wires the example to use SessionManager from @opentelemetry/web-common
and DocumentTracker, exposes Push History and Rotate Session buttons,
and adds an OTLP HTTP processor pointed at the demo collector. Also
adds http://localhost:5173 to the demo collector CORS origins.
Encapsulates EntityAwareLoggerProvider construction, the global logs.setGlobalLoggerProvider call, SessionManager start + observer wiring, and trackDocument(). Returns a BrowserSdk handle exposing the provider, document tracker, getSessionId(), rotateSession(), and shutdown(). Slims the example down to a single initializeSdk({...}) call.
@martinkuba martinkuba changed the title Prototype: session and document URL as log resource entities feat: session and document URL as log resource entities May 7, 2026
@martinkuba martinkuba marked this pull request as ready for review May 21, 2026 15:32
@martinkuba martinkuba requested a review from a team as a code owner May 21, 2026 15:32
@mquentin

Copy link
Copy Markdown
Contributor

Hey Martin, following @overbalance input about this change in yesterday SIG, I took the chance to think about it a bit.

Problem statement

With this current PR entity implementation, I think carrying the browser.document.url.full as a resource entity is not perfect as the full url will mutate a lot with any url param changing, or any route change. Here is why:

Say:

  • t1: click on URL_A → emit() → record carries Resource{url=A}
  • t2: history.pushState(URL_B) → DocumentTracker fires → setEntity({url:B}) → new _currentProvider with Resource{url=B}
  • t3: error on URL_B → emit() → record carries Resource{url=B}
  • t4: pushState to URL_C → new _currentProvider with Resource{url=C}
  • t5: resource-timing emitted on URL_C → record carries Resource{url=C}

Then you end up with a API intake request like:

Request {
    resourceLogs: [
      { resource: { browser.document.url.full: URL_A, ... }, logRecords: [click] },
      { resource: { browser.document.url.full: URL_B, ... }, logRecords: [error] },
      { resource: { browser.document.url.full: URL_C, ... }, logRecords: [resource-timing] },
    ]
  }

Chances are that not many logs will share the exact same url.full which will lead into a huge number of resourceLogs entries rather that fewer resourceLogs for a lot of logRecords (which is the goal of the resource: reduce the payload by preventing duplicating each shared attribute in the logRecords themselve)

For me browser.document.url.full cannot really be an entity as it would drastically increase resourceLogs partitions and therefore the final payload size.

Session.id however makes way more sens as an entity as I don't see it mutate that much in comparison

Suggestion

1- We proceed with the span and log processor for browser.document.url.full like in this example PR.
2- We keep the session.id as a resource entity

What do you think about this ?

@joaquin-diaz

Copy link
Copy Markdown
Contributor

Hey @mquentin I appreciate the thorough analysis. I don't remember if we discussed this but I don't think we should store query params in browser.document.url.full, I agree with you that those are likely to change a lot and they (most times) don't represent the page where the user is but its state. I understand your concerns about creating many resources and increasing the payload size but would we have a similar impact if we instead add the attribute browser.document.url.full to all logs and spans?

I still think is worth having entities that represent layers of the app that users can use as dimensions when searching for telemetry

Session
├── Page: https://example.com/home
│   ├── Logs
│   │   ├── [INFO]  Page load started
│   │   ├── [WARN]  Slow resource detected
│   │   └── [ERROR] Failed to fetch /api/user
│   └── Spans
│       ├── fetch /api/user          [320ms]
│       └── render <HeroSection>     [ 45ms]
│
└── Page: https://example.com/dashboard
    ├── Logs
    │   ├── [INFO]  Page load started
    │   └── [INFO]  Dashboard ready
    └── Spans
        ├── fetch /api/metrics       [180ms]
        ├── fetch /api/alerts        [ 95ms]
        └── render <ChartGrid>       [210ms]

@mquentin

Copy link
Copy Markdown
Contributor

Hey @mquentin I appreciate the thorough analysis. I don't remember if we discussed this but I don't think we should store query params in browser.document.url.full, I agree with you that those are likely to change a lot and they (most times) don't represent the page where the user is but its state. I understand your concerns about creating many resources and increasing the payload size but would we have a similar impact if we instead add the attribute browser.document.url.full to all logs and spans?

I still think is worth having entities that represent layers of the app that users can use as dimensions when searching for telemetry

Session
├── Page: https://example.com/home
│   ├── Logs
│   │   ├── [INFO]  Page load started
│   │   ├── [WARN]  Slow resource detected
│   │   └── [ERROR] Failed to fetch /api/user
│   └── Spans
│       ├── fetch /api/user          [320ms]
│       └── render <HeroSection>     [ 45ms]
│
└── Page: https://example.com/dashboard
    ├── Logs
    │   ├── [INFO]  Page load started
    │   └── [INFO]  Dashboard ready
    └── Spans
        ├── fetch /api/metrics       [180ms]
        ├── fetch /api/alerts        [ 95ms]
        └── render <ChartGrid>       [210ms]

@joaquin-diaz indeed I don't think we discussed about it.
Unfortunately (unless I missunderstood something) url.full represent the absolute URL of a document which includes all the query parameters, cf. this OTel doc: https://opentelemetry.io/docs/specs/semconv/registry/attributes/url/#url-full

I feel it would be misleading to change this semantic definition for the browser.document.url.full.
On top of that, the query params are quite useful for debugging errors as an example or to understand the state of a web application.

However, I also pretty fan of having

entities that represents layers of the app that users can use as dimensions when searching for telemetry

I think that's an interesting topic to discuss during the SIG

@mquentin

Copy link
Copy Markdown
Contributor

Hey @mquentin I appreciate the thorough analysis. I don't remember if we discussed this but I don't think we should store query params in browser.document.url.full, I agree with you that those are likely to change a lot and they (most times) don't represent the page where the user is but its state. I understand your concerns about creating many resources and increasing the payload size but would we have a similar impact if we instead add the attribute browser.document.url.full to all logs and spans?
I still think is worth having entities that represent layers of the app that users can use as dimensions when searching for telemetry

...

I think that's an interesting topic to discuss during the SIG

Follow up on this, as we discussed about it during the SIG:

  • SIG agrees that we don’t want the url on all the signals and it should be shared as an entity
  • Out of the box the browser.document.url.full is the page entity for the time being
  • This will be later improved by providing a new API to pick what page url entity we leverage for this entity out of one or several attributes out of https://opentelemetry.io/docs/specs/semconv/registry/attributes/url

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants