Repository navigation
Conversation
fateeand
requested review from
TerranceKhumalo-absa,
korel-san and
lukasmatta
as code owners
November 10, 2026 15:11
Contributor
Core coverage report
Test suite run success419 tests passing in 22 suites. Report generated by 🧪jest coverage report action from 380e134 |
8 tasks
Contributor
Ngx coverage report
Show files with reduced coverage 🔻
Test suite run success544 tests passing in 14 suites. Report generated by 🧪jest coverage report action from 380e134 |
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Disabled broadcast components still send traffic over shared connections, while missing validation for required identity fields allows incomplete configurations that cause silent log loss.
3 open issues
What changed in this PR
Extracts the shared telemetry engine into @absaoss-cps/ui-watchtower, enabling non-Angular applications and future framework adapters as requested in #35. The existing Angular package becomes an adapter over that core.
Changes:
- Introduces the framework-independent core with lifecycle controls, broadcast support, and optional RUM and RxJS entry points.
- Delegates Angular services and providers to the core while preserving existing imports and typed name declarations.
- Adds two-package build and release support, API snapshots, consumer smoke checks, coverage thresholds, and adapter documentation.
| File | Description |
|---|---|
tsconfig.json |
Adds core import mappings and project references. |
scripts/smoke/core-ts/nodom.ts |
Checks core usage without DOM typings. |
scripts/smoke/core-node/consumer.mjs |
Exercises installed core without frameworks or browser globals. |
scripts/smoke/angular/variants/shell.app.config.ts |
Configures an Angular shell smoke consumer. |
scripts/smoke/angular/variants/fragment.app.config.ts |
Configures an Angular broadcast fragment consumer. |
scripts/smoke/angular/tsconfig.json |
Configures strict Angular consumer compilation. |
scripts/smoke/angular/src/telemetry.schema.ts |
Checks existing Angular name augmentation. |
scripts/smoke/angular/src/main.ts |
Bootstraps the browser smoke application. |
scripts/smoke/angular/src/main.server.ts |
Bootstraps the server smoke application. |
scripts/smoke/angular/src/index.html |
Supplies the smoke application's HTML entry. |
scripts/smoke/angular/src/app/home.ts |
Exercises telemetry services during rendering. |
scripts/smoke/angular/src/app/app.ts |
Hosts routed smoke content. |
scripts/smoke/angular/src/app/app.routes.ts |
Routes to the telemetry smoke component. |
scripts/smoke/angular/src/app/app.routes.server.ts |
Enables prerendering for smoke routes. |
scripts/smoke/angular/src/app/app.config.server.ts |
Composes server-rendering providers. |
scripts/smoke/angular/angular.json |
Configures browser and prerendered consumer builds. |
scripts/publish-packages.mjs |
Publishes tagged versions in dependency order. |
scripts/api-snapshot.mjs |
Compares built public APIs with snapshots. |
release-please-config.json |
Configures independent package releases and dependency updates. |
projects/ui-watchtower/type-tests/tsconfig.json |
Configures core compatibility and empty-registry checks. |
projects/ui-watchtower/type-tests/tsconfig.augmented.json |
Isolates augmented core registry checks. |
projects/ui-watchtower/type-tests/empty-registry.ts |
Checks unrestricted names before augmentation. |
projects/ui-watchtower/type-tests/augmented.ts |
Checks registered names across core APIs. |
projects/ui-watchtower/tsconfig.spec.json |
Configures core and optional-entry-point tests. |
projects/ui-watchtower/tsconfig.lib.prod.json |
Configures production package declarations. |
projects/ui-watchtower/tsconfig.lib.json |
Configures core library compilation. |
projects/ui-watchtower/src/public-api.ts |
Exposes the framework-independent core API. |
projects/ui-watchtower/src/public-api.spec.ts |
Covers core operation without browser globals. |
projects/ui-watchtower/src/lib/utils/uwt-user-timings-internal.util/uwt-user-timings-internal.util.ts |
Provides framework-independent timing helpers. |
projects/ui-watchtower/src/lib/utils/uwt-user-timings-internal.util/uwt-user-timings-internal.util.spec.ts |
Opts timing tests into jsdom. |
projects/ui-watchtower/src/lib/utils/uwt-telemetry-event.util/uwt-telemetry-event.util.ts |
Classifies telemetry payloads by event type. |
projects/ui-watchtower/src/lib/utils/uwt-telemetry-event.util/uwt-telemetry-event.util.spec.ts |
Covers classification and namespace handling. |
projects/ui-watchtower/src/lib/utils/uwt-session-start.util/uwt-session-start.util.ts |
Documents the retained storage key for compatibility. |
projects/ui-watchtower/src/lib/utils/uwt-session-start.util/uwt-session-start.util.spec.ts |
Opts session-storage tests into jsdom. |
projects/ui-watchtower/src/lib/utils/uwt-debug-flag.util/uwt-debug-flag.util.ts |
Passes reporters through debug-write suppression. |
projects/ui-watchtower/src/lib/utils/uwt-debug-flag.util/uwt-debug-flag.util.spec.ts |
Opts debug-flag tests into jsdom. |
projects/ui-watchtower/src/lib/sinks/uwt-telemetry/uwt-telemetry-abstract.sink/uwt-telemetry-abstract.sink.ts |
Removes Angular metadata from the sink contract. |
projects/ui-watchtower/src/lib/sinks/uwt-telemetry/uwt-noop-telemetry.sink/uwt-noop-telemetry.sink.ts |
Provides the core no-op destination. |
projects/ui-watchtower/src/lib/sinks/uwt-telemetry/uwt-noop-telemetry.sink/uwt-noop-telemetry.sink.spec.ts |
Covers the no-op destination contract. |
projects/ui-watchtower/src/lib/sinks/uwt-broadcast/uwt-broadcast-telemetry.sink.ts |
Provides broadcast forwarding and connection ownership. |
projects/ui-watchtower/src/lib/scenario/uwt-scenario/uwt-scenario.spec.ts |
Opts scenario tests into jsdom. |
projects/ui-watchtower/src/lib/providers/uwt-noop-log-api.provider/uwt-noop-log-api.provider.ts |
Provides a framework-independent no-op log store. |
projects/ui-watchtower/src/lib/providers/uwt-noop-log-api.provider/uwt-noop-log-api.provider.spec.ts |
Covers discarded logs and empty query results. |
projects/ui-watchtower/src/lib/providers/uwt-log-api.provider/uwt-log-api.provider.ts |
Defines shared log-store and query contracts. |
projects/ui-watchtower/src/lib/providers/uwt-broadcast-log-api.provider/uwt-broadcast-log-api.provider.ts |
Forwards logs and queries over shared connections. |
projects/ui-watchtower/src/lib/models/uwt-telemetry-common.models/uwt-telemetry-common.models.ts |
Defines shared telemetry types and event names. |
projects/ui-watchtower/src/lib/models/uwt-telemetry-common.models/uwt-telemetry-common.models.spec.ts |
Covers event namespaces and defaults. |
projects/ui-watchtower/src/lib/models/uwt-scenario.models/uwt-scenario.models.ts |
Documents core and Angular registry augmentation. |
projects/ui-watchtower/src/lib/models/uwt-log.models/uwt-log.models.ts |
Updates logging documentation for the shared core. |
projects/ui-watchtower/src/lib/models/uwt-bi.models/uwt-bi.models.ts |
Documents shared business-event registry augmentation. |
projects/ui-watchtower/src/lib/engine/uwt-telemetry/uwt-telemetry.ts |
Creates and disposes the unified telemetry engine. |
projects/ui-watchtower/src/lib/engine/uwt-telemetry-page/uwt-telemetry-page.ts |
Abstracts document access and page lifecycle listeners. |
projects/ui-watchtower/src/lib/config/uwt-telemetry-common.config/uwt-telemetry-common.config.ts |
Centralizes identity, defaults, and configuration resolution. |
projects/ui-watchtower/src/lib/config/uwt-telemetry-common.config/uwt-telemetry-common.config.spec.ts |
Covers shared configuration defaults. |
projects/ui-watchtower/src/lib/config/uwt-scenario-telemetry.config/uwt-scenario-telemetry.config.ts |
Defines shared scenario settings. |
projects/ui-watchtower/src/lib/config/uwt-scenario-telemetry.config/uwt-scenario-telemetry.config.spec.ts |
Covers scenario configuration defaults. |
projects/ui-watchtower/src/lib/config/uwt-log.config/uwt-log.config.ts |
Defines shared logging settings. |
projects/ui-watchtower/src/lib/config/uwt-log.config/uwt-log.config.spec.ts |
Covers logging configuration defaults. |
projects/ui-watchtower/src/lib/config/uwt-bi-telemetry.config/uwt-bi-telemetry.config.ts |
Defines shared business-event settings. |
projects/ui-watchtower/src/lib/config/uwt-bi-telemetry.config/uwt-bi-telemetry.config.spec.ts |
Covers business-event configuration defaults. |
projects/ui-watchtower/rxjs/tsconfig.lib.json |
Configures the optional RxJS entry point. |
projects/ui-watchtower/rxjs/src/public-api.ts |
Exposes the RxJS integration separately. |
projects/ui-watchtower/rxjs/src/lib/uwt-scenario-operators/uwt-scenario-operators.ts |
Implements shared observable scenario settlement. |
projects/ui-watchtower/rxjs/ng-package.json |
Packages the RxJS secondary entry point. |
projects/ui-watchtower/rum/tsconfig.lib.json |
Configures the optional RUM entry point. |
projects/ui-watchtower/rum/src/public-api.ts |
Exposes the RUM sink and credential contracts. |
projects/ui-watchtower/rum/src/lib/uwt-rum-telemetry.sink/uwt-rum-telemetry.sink.spec.ts |
Covers RUM startup, reporting, and disposal. |
projects/ui-watchtower/rum/ng-package.json |
Packages the RUM secondary entry point. |
projects/ui-watchtower/package.json |
Declares the core package and optional peers. |
projects/ui-watchtower/ng-package.json |
Defines core package output. |
projects/ui-watchtower/jest.config.js |
Adds framework-free tests and coverage thresholds. |
projects/ngx-ui-watchtower/type-tests/tsconfig.json |
Configures Angular consumer compatibility checks. |
projects/ngx-ui-watchtower/type-tests/tsconfig.augmented.json |
Isolates augmented Angular registry checks. |
projects/ngx-ui-watchtower/type-tests/empty-registry.ts |
Checks Angular name fallbacks without augmentation. |
projects/ngx-ui-watchtower/type-tests/augmented.ts |
Checks existing Angular registry declarations. |
projects/ngx-ui-watchtower/tsconfig.spec.json |
Allows adapter tests to include core sources. |
projects/ngx-ui-watchtower/tsconfig.lib.json |
Resolves core imports against built declarations. |
projects/ngx-ui-watchtower/src/public-api.ts |
Re-exports shared contracts while preserving Angular exports. |
projects/ngx-ui-watchtower/src/lib/utils/uwt-telemetry-safe.util/uwt-telemetry-safe.util.ts |
Supplies Angular platform, zone, and reporting helpers. |
projects/ngx-ui-watchtower/src/lib/utils/uwt-telemetry-safe.util/uwt-telemetry-safe.util.spec.ts |
Retains adapter-specific suppression tests. |
projects/ngx-ui-watchtower/src/lib/sinks/uwt-telemetry/uwt-noop-telemetry.sink/uwt-noop-telemetry.sink.ts |
Makes the core no-op sink injectable. |
projects/ngx-ui-watchtower/src/lib/sinks/uwt-broadcast/uwt-broadcast.wire.fixture.json |
Records the broadcast compatibility fixture. |
projects/ngx-ui-watchtower/src/lib/sinks/uwt-broadcast/uwt-broadcast-telemetry.sink.ts |
Wraps the core broadcast sink with Angular injection. |
projects/ngx-ui-watchtower/src/lib/services/uwt-scenario-telemetry.service/uwt-scenario-telemetry.service.spec.ts |
Checks teardown and subscriber-dependent record copying. |
projects/ngx-ui-watchtower/src/lib/services/uwt-logger.service/uwt-logger.service.spec.ts |
Updates logging tests to target shared core logic. |
projects/ngx-ui-watchtower/src/lib/services/uwt-bi-telemetry.service/uwt-bi-telemetry.service.ts |
Delegates business-event tracking to the core. |
projects/ngx-ui-watchtower/src/lib/services/uwt-bi-telemetry.service/uwt-bi-telemetry.service.spec.ts |
Uses core contracts in adapter tracking tests. |
projects/ngx-ui-watchtower/src/lib/scenario/uwt-scenario-operators/uwt-scenario-operators.ts |
Delegates RxJS integration with Angular reporting. |
projects/ngx-ui-watchtower/src/lib/providers/uwt-telemetry-common.providers/uwt-telemetry-enabled.spec.ts |
Uses core contracts in disabled-mode tests. |
projects/ngx-ui-watchtower/src/lib/providers/uwt-telemetry-common.providers/uwt-telemetry-common.providers.ts |
Uses shared defaults and provides one broadcast connection. |
projects/ngx-ui-watchtower/src/lib/providers/uwt-telemetry-common.providers/uwt-telemetry-common.providers.spec.ts |
Updates provider tests to shared contracts. |
projects/ngx-ui-watchtower/src/lib/providers/uwt-noop-log-api.provider/uwt-noop-log-api.provider.ts |
Makes the core no-op log provider injectable. |
projects/ngx-ui-watchtower/src/lib/providers/uwt-log-api.provider/uwt-log-api.provider.ts |
Keeps the Angular token for the core log contract. |
projects/ngx-ui-watchtower/src/lib/providers/uwt-broadcast-log-api.provider/uwt-broadcast-log-api.provider.ts |
Wraps core broadcast logging with Angular zone hooks. |
projects/ngx-ui-watchtower/src/lib/providers/uwt-broadcast-log-api.provider/uwt-broadcast-log-api.provider.spec.ts |
Uses core log records in adapter tests. |
projects/ngx-ui-watchtower/src/lib/config/uwt-telemetry-common.config/uwt-telemetry-common.config.ts |
Retains Angular tokens for shared configuration types. |
projects/ngx-ui-watchtower/src/lib/config/uwt-scenario-telemetry.config/uwt-scenario-telemetry.config.ts |
Retains the scenario configuration injection token. |
projects/ngx-ui-watchtower/src/lib/config/uwt-log.config/uwt-log.config.ts |
Retains the logging configuration injection token. |
projects/ngx-ui-watchtower/src/lib/config/uwt-bi-telemetry.config/uwt-bi-telemetry.config.ts |
Retains the business-event configuration injection token. |
projects/ngx-ui-watchtower/rum/tsconfig.spec.json |
Allows RUM tests to include core sources. |
projects/ngx-ui-watchtower/rum/tsconfig.lib.json |
Expands RUM type-checking scope for core sources. |
projects/ngx-ui-watchtower/rum/src/lib/uwt-rum-telemetry.sink/uwt-rum-telemetry.sink.spec.ts |
Uses the core session utility in RUM tests. |
projects/ngx-ui-watchtower/rum/src/lib/uwt-rum-internal.util/uwt-rum-internal.util.ts |
Keeps only Angular-specific RUM helpers. |
projects/ngx-ui-watchtower/README.md |
Explains the adapter relationship and compatibility. |
projects/ngx-ui-watchtower/package.json |
Adds the core as a regular dependency. |
projects/ngx-ui-watchtower/ng-package.json |
Allows the core dependency in adapter packaging. |
package.json |
Coordinates two-package builds and verification commands. |
package-lock.json |
Records the direct core test-transformer dependency. |
jest.config.js |
Scopes Angular tests and enforces coverage thresholds. |
docs/ADAPTERS.md |
Documents adapter wiring, lifecycle, testing, and releases. |
angular.json |
Registers the core library build. |
.gitignore |
Ignores API snapshot mismatch output. |
.github/workflows/release-please.yml |
Publishes both packages and supports release retries. |
.github/workflows/checks.yml |
Adds core coverage, API, smoke, and release checks. |
.eslintrc.js |
Enforces framework and optional-peer import boundaries. |
Review effort: Max
7 tasks
This was referenced Nov 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
UI Watchtower now ships as two packages from this repository:
@absaoss-cps/ui-watchtower(new). The telemetry engine: scenarios, BI events, logging, redaction and the shell/fragment broadcast protocol. It needs no framework and is used directly from plain JavaScript or TypeScript or any framework's app.@absaoss-cps/ngx-ui-watchtower. Now a thin Angular adapter over the core: providers, injectable services and Observables around the same engine. It installs the core as a regular dependency.There is one implementation of the engine and the protocol, in the core. The Angular package delegates to it.
Changes
Core (
projects/ui-watchtower)uwtCreateTelemetry(options)creates an engine withscenarios,bi,logging,setUserId,flushand an idempotentdispose(). Every call fails open; a missing identity (application, environment and version as strings), destination or log store throws when the engine is created.document(the global one by default,nullfor none). Nothing toucheswindowordocumenton import, and there is no global engine state.onSettled(listener)replaces the Observable inside the core, so the main entry point needs no RxJS.dispose()stops watching the page, settles in-flight scenarios as abandoned, and flushes. That is all it changes: something may still run while an application shuts down, and the destination and log store are the caller's, so scenarios, BI events and logs started afterwards work as before.enabled: falsewins over a shared connection, and so doesdispose(): they send nothing, a disposed provider answers queries with[]at once, and the connection stays open for its other users.runOutsidethat hands nothing back no longer runs a scheduled callback twice (the core and the Angular helper)..(engine, contracts, no-op and broadcast destinations),/rum(the AWS RUM sink;aws-rum-webis an optional peer, loaded lazily) and/rxjs(traceScenario;rxjsis an optional peer).@absaoss-cps/ui-watchtower.Angular adapter (
projects/ngx-ui-watchtower)/rum's sink are@Injectablesubclasses of the core's.settled$listens to the core only while it has subscribers, as before the extraction: no record is copied when nobody reads it.'broadcast'mode, the sink and the log provider share one channel per injector.Release and CI
^the new core (Release Please'snode-workspaceplugin). One release PR holds every package with changes.0.1.0(initial-version); the adapter continues from 0.4.0.ui-watchtower-v…andngx-ui-watchtower-v…; the oldv…tags stay.scripts/publish-packages.mjspublishes what was released, the core before the adapter. It skips versions npm already has, and stops before the adapter if the core fails. Rerunning the workflow on a release tag finishes a partial release.npm run api:check: public API snapshots;npm run smoke: the packed packages installed in a plain Node app, a TypeScript app and an unchanged Angular app;npm run release:check: Release Please replayed on the config: the first release, adapter-only and core changes, and the tags merging creates;npm run test:coveragefails below 90% on any metric, in either package (the core is at 98% statements, 95% branches);npm run test:release: the publish script and the workflow wiring.Tests
UwtScenario, the engine) raise its coverage from 80% to 98% statements; the review fixes each have a test that fails without them./rumentry's private copies of the Angular helpers against the main entry's, so they cannot drift apart.Docs
docs/ADAPTERS.mdguides writing an adapter for another framework.Logos
Compatibility
/rum,settled$,traceScenarioanddeclare module '@absaoss-cps/ngx-ui-watchtower'name declarations all work as before.dispose();UwtTelemetrySinkis now the core's plain abstract class, so it lost its Angular factory metadata. It is still the destination token and the base class for custom sinks.Before merging the release PR
Squash-merge this PR with its
feat:title: the release PR then proposes the core at0.1.0and the adapter at0.5.0.npm sets up trusted publishing only for a package that exists. Before merging that release PR, an
@absaoss-cpsowner publishes the core at0.1.0once by hand, from the release PR's branch, then adds its trusted publisher (GitHub Actions,AbsaOSS/ui-watchtower, workflowrelease-please.yml). The workflow then finds 0.1.0 on npm, skips it, and publishes the adapter. The exact commands are in the README's "Releases" section. If the release PR is merged first, publishing stops at the core; publish it from theui-watchtower-v0.1.0tag, then rerun the workflow on the release tag.Closes #35