@equinor/fusion-framework-module-analytics 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +147 -130
- package/dist/esm/AnalyticsConfigurator.js +22 -17
- package/dist/esm/AnalyticsConfigurator.js.map +1 -1
- package/dist/esm/AnalyticsProvider.js +39 -18
- package/dist/esm/AnalyticsProvider.js.map +1 -1
- package/dist/esm/adapters/ConsoleAnalyticsAdapter.js +15 -1
- package/dist/esm/adapters/ConsoleAnalyticsAdapter.js.map +1 -1
- package/dist/esm/adapters/FusionAnalyticsAdapter.js +32 -3
- package/dist/esm/adapters/FusionAnalyticsAdapter.js.map +1 -1
- package/dist/esm/adapters/index.js.map +1 -1
- package/dist/esm/collectors/AppLoadedCollector.js +21 -5
- package/dist/esm/collectors/AppLoadedCollector.js.map +1 -1
- package/dist/esm/collectors/AppSelectedCollector.js +17 -5
- package/dist/esm/collectors/AppSelectedCollector.js.map +1 -1
- package/dist/esm/collectors/BaseCollector.js +48 -3
- package/dist/esm/collectors/BaseCollector.js.map +1 -1
- package/dist/esm/collectors/ContextSelectedCollector.js +20 -5
- package/dist/esm/collectors/ContextSelectedCollector.js.map +1 -1
- package/dist/esm/collectors/index.js.map +1 -1
- package/dist/esm/collectors/utils/extractAppMetadata.js +25 -4
- package/dist/esm/collectors/utils/extractAppMetadata.js.map +1 -1
- package/dist/esm/collectors/utils/extractContextMetadata.js +13 -2
- package/dist/esm/collectors/utils/extractContextMetadata.js.map +1 -1
- package/dist/esm/enable-analytics.js +18 -3
- package/dist/esm/enable-analytics.js.map +1 -1
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.js +26 -4
- package/dist/esm/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.js.map +1 -1
- package/dist/esm/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.js +36 -7
- package/dist/esm/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.js.map +1 -1
- package/dist/esm/logExporters/index.js +8 -0
- package/dist/esm/logExporters/index.js.map +1 -1
- package/dist/esm/module.js +8 -8
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/AnalyticsConfigurator.d.ts +22 -17
- package/dist/types/AnalyticsConfigurator.interface.d.ts +41 -12
- package/dist/types/AnalyticsProvider.d.ts +32 -18
- package/dist/types/AnalyticsProvider.interface.d.ts +28 -6
- package/dist/types/adapters/AnalyticsAdapter.interface.d.ts +15 -2
- package/dist/types/adapters/ConsoleAnalyticsAdapter.d.ts +15 -1
- package/dist/types/adapters/FusionAnalyticsAdapter.d.ts +32 -3
- package/dist/types/adapters/index.d.ts +8 -0
- package/dist/types/collectors/AnalyticsCollector.interface.d.ts +11 -2
- package/dist/types/collectors/AppLoadedCollector.d.ts +20 -2
- package/dist/types/collectors/AppSelectedCollector.d.ts +16 -2
- package/dist/types/collectors/BaseCollector.d.ts +58 -3
- package/dist/types/collectors/ContextSelectedCollector.d.ts +19 -2
- package/dist/types/collectors/index.d.ts +8 -0
- package/dist/types/collectors/utils/extractAppMetadata.d.ts +27 -0
- package/dist/types/collectors/utils/extractContextMetadata.d.ts +14 -0
- package/dist/types/enable-analytics.d.ts +19 -3
- package/dist/types/index.d.ts +18 -0
- package/dist/types/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.d.ts +21 -3
- package/dist/types/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.d.ts +24 -1
- package/dist/types/logExporters/index.d.ts +8 -0
- package/dist/types/module.d.ts +15 -15
- package/dist/types/types.d.ts +38 -7
- package/dist/types/version.d.ts +1 -1
- package/package.json +11 -11
- package/src/AnalyticsConfigurator.interface.ts +41 -12
- package/src/AnalyticsConfigurator.ts +22 -17
- package/src/AnalyticsProvider.interface.ts +28 -6
- package/src/AnalyticsProvider.ts +39 -18
- package/src/adapters/AnalyticsAdapter.interface.ts +15 -2
- package/src/adapters/ConsoleAnalyticsAdapter.ts +15 -1
- package/src/adapters/FusionAnalyticsAdapter.ts +32 -3
- package/src/adapters/index.ts +8 -0
- package/src/collectors/AnalyticsCollector.interface.ts +11 -2
- package/src/collectors/AppLoadedCollector.ts +21 -5
- package/src/collectors/AppSelectedCollector.ts +17 -5
- package/src/collectors/BaseCollector.ts +58 -3
- package/src/collectors/ContextSelectedCollector.ts +20 -5
- package/src/collectors/index.ts +8 -0
- package/src/collectors/utils/extractAppMetadata.ts +27 -4
- package/src/collectors/utils/extractContextMetadata.ts +14 -2
- package/src/enable-analytics.ts +19 -3
- package/src/index.ts +19 -0
- package/src/logExporters/fusionOTLPLogExporter/FusionOTLPLogExporter.ts +26 -4
- package/src/logExporters/fusionOTLPLogExporter/HttpClientExporterTransport.ts +36 -7
- package/src/logExporters/index.ts +8 -0
- package/src/module.ts +15 -15
- package/src/types.ts +39 -8
- package/src/version.ts +1 -1
|
@@ -4,36 +4,41 @@ import type { IAnalyticsCollector } from './collectors/AnalyticsCollector.interf
|
|
|
4
4
|
import type { IAnalyticsAdapter } from './adapters/AnalyticsAdapter.interface.js';
|
|
5
5
|
import type { AnalyticsEvent } from './types.js';
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* The `AnalyticsConfigurator` class extends `BaseConfigBuilder` to provide a fluent API for
|
|
10
|
-
* setting up analytics adapters and collectors.
|
|
7
|
+
* Default {@link IAnalyticsConfigurator} implementation for registering analytics adapters and collectors.
|
|
11
8
|
*
|
|
12
9
|
* @remarks
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
10
|
+
* Extends `BaseConfigBuilder` to resolve adapter and collector factories
|
|
11
|
+
* asynchronously at module-initialisation time using RxJS `mergeMap`. Each
|
|
12
|
+
* registered factory is invoked with the module’s `ConfigBuilderCallbackArgs`
|
|
13
|
+
* so it can resolve dependencies from the framework before returning its
|
|
14
|
+
* adapter or collector instance.
|
|
15
|
+
*
|
|
16
|
+
* Use {@link AnalyticsConfigurator.setAdapter | setAdapter} and
|
|
17
|
+
* {@link AnalyticsConfigurator.setCollector | setCollector} to register
|
|
18
|
+
* components. Both methods return `this` for fluent chaining.
|
|
16
19
|
*
|
|
17
|
-
* @see
|
|
18
|
-
* @see
|
|
20
|
+
* @see {@link IAnalyticsConfigurator}
|
|
21
|
+
* @see {@link BaseConfigBuilder}
|
|
19
22
|
*/
|
|
20
23
|
export declare class AnalyticsConfigurator extends BaseConfigBuilder<AnalyticsConfig> implements IAnalyticsConfigurator {
|
|
21
24
|
#private;
|
|
22
25
|
constructor();
|
|
23
26
|
/**
|
|
24
|
-
* Registers
|
|
27
|
+
* Registers an analytics collector factory.
|
|
25
28
|
*
|
|
26
|
-
* @
|
|
27
|
-
* @param
|
|
28
|
-
* @
|
|
29
|
+
* @template T - The concrete analytics event type the collector emits.
|
|
30
|
+
* @param identifier - Unique key for the collector.
|
|
31
|
+
* @param callback - Factory that receives module-resolution args and returns a collector.
|
|
32
|
+
* @returns `this` for method chaining.
|
|
29
33
|
*/
|
|
30
34
|
setCollector<T extends AnalyticsEvent>(identifier: string, callback: ConfigBuilderCallback<IAnalyticsCollector<T>>): this;
|
|
31
35
|
/**
|
|
32
|
-
* Registers
|
|
36
|
+
* Registers an analytics adapter factory.
|
|
33
37
|
*
|
|
34
|
-
* @
|
|
35
|
-
* @param
|
|
36
|
-
* @
|
|
38
|
+
* @template T - The concrete analytics event type the adapter handles.
|
|
39
|
+
* @param identifier - Unique key for the adapter.
|
|
40
|
+
* @param callback - Factory that receives module-resolution args and returns an adapter.
|
|
41
|
+
* @returns `this` for method chaining.
|
|
37
42
|
*/
|
|
38
43
|
setAdapter<T extends AnalyticsEvent>(identifier: string, callback: ConfigBuilderCallback<IAnalyticsAdapter<T>>): this;
|
|
39
44
|
}
|
|
@@ -3,36 +3,65 @@ import type { IAnalyticsCollector } from './collectors/AnalyticsCollector.interf
|
|
|
3
3
|
import type { IAnalyticsAdapter } from './adapters/AnalyticsAdapter.interface.js';
|
|
4
4
|
import type { AnalyticsEvent } from './types.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Resolved analytics configuration containing the instantiated collectors and adapters.
|
|
7
7
|
*
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* This type is the output of the configuration stage. The module’s `initialize`
|
|
10
|
+
* function receives the resolved `AnalyticsConfig` and passes it to
|
|
11
|
+
* {@link AnalyticsProvider}.
|
|
10
12
|
*/
|
|
11
13
|
export type AnalyticsConfig = {
|
|
14
|
+
/** Record of analytics collectors keyed by a unique identifier. */
|
|
12
15
|
collectors: Record<string, IAnalyticsCollector>;
|
|
16
|
+
/** Record of analytics adapters keyed by a unique identifier. */
|
|
13
17
|
adapters: Record<string, IAnalyticsAdapter>;
|
|
14
18
|
};
|
|
15
19
|
/**
|
|
16
|
-
*
|
|
20
|
+
* Configuration-time interface for registering analytics adapters and collectors.
|
|
17
21
|
*
|
|
18
|
-
*
|
|
22
|
+
* @remarks
|
|
23
|
+
* Obtain an instance of this interface inside the callback passed to
|
|
24
|
+
* {@link enableAnalytics}. Use {@link IAnalyticsConfigurator.setAdapter | setAdapter}
|
|
25
|
+
* and {@link IAnalyticsConfigurator.setCollector | setCollector} to register
|
|
26
|
+
* components. Both methods support method chaining.
|
|
19
27
|
*
|
|
20
|
-
* @
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* enableAnalytics(configurator, (builder) => {
|
|
31
|
+
* builder
|
|
32
|
+
* .setAdapter('console', async () => new ConsoleAnalyticsAdapter())
|
|
33
|
+
* .setCollector('context-selected', async (args) => {
|
|
34
|
+
* const ctx = await args.requireInstance('context');
|
|
35
|
+
* const app = await args.requireInstance('app');
|
|
36
|
+
* return new ContextSelectedCollector(ctx, app);
|
|
37
|
+
* });
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
21
40
|
*/
|
|
22
41
|
export interface IAnalyticsConfigurator {
|
|
23
42
|
/**
|
|
24
|
-
*
|
|
43
|
+
* Registers an analytics collector factory identified by a unique key.
|
|
25
44
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
45
|
+
* The factory callback receives module-resolution arguments so it can
|
|
46
|
+
* resolve dependencies (e.g. context or app providers) before returning
|
|
47
|
+
* the collector instance.
|
|
48
|
+
*
|
|
49
|
+
* @template T - The concrete analytics event type the collector emits.
|
|
50
|
+
* @param identifier - Unique key for this collector.
|
|
51
|
+
* @param callBack - Async factory that returns the collector instance.
|
|
28
52
|
* @returns The configurator instance for method chaining.
|
|
29
53
|
*/
|
|
30
54
|
setCollector<T extends AnalyticsEvent>(identifier: string, callBack: ConfigBuilderCallback<IAnalyticsCollector<T>>): this;
|
|
31
55
|
/**
|
|
32
|
-
*
|
|
56
|
+
* Registers an analytics adapter factory identified by a unique key.
|
|
57
|
+
*
|
|
58
|
+
* The factory callback receives module-resolution arguments so it can
|
|
59
|
+
* resolve dependencies (e.g. service-discovery HTTP clients) before
|
|
60
|
+
* returning the adapter instance.
|
|
33
61
|
*
|
|
34
|
-
* @
|
|
35
|
-
* @param
|
|
62
|
+
* @template T - The concrete analytics event type the adapter handles.
|
|
63
|
+
* @param identifier - Unique key for this adapter.
|
|
64
|
+
* @param callback - Async factory that returns the adapter instance.
|
|
36
65
|
* @returns The configurator instance for method chaining.
|
|
37
66
|
*/
|
|
38
67
|
setAdapter<T extends AnalyticsEvent>(identifier: string, callback: ConfigBuilderCallback<IAnalyticsAdapter<T>>): this;
|
|
@@ -4,42 +4,56 @@ import type { IAnalyticsProvider } from './AnalyticsProvider.interface.js';
|
|
|
4
4
|
import type { AnalyticsEvent } from './types.js';
|
|
5
5
|
import { type ObservableInput, Subscription } from 'rxjs';
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Runtime analytics provider that collects events from collectors and dispatches
|
|
8
|
+
* them to adapters.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* Created by the analytics module during initialisation. The provider:
|
|
12
|
+
*
|
|
13
|
+
* 1. Initialises all registered adapters and collectors.
|
|
14
|
+
* 2. Subscribes to every collector and merges their events into a shared stream.
|
|
15
|
+
* 3. Forwards each emitted event to every registered adapter via
|
|
16
|
+
* {@link IAnalyticsAdapter.registerAnalytic}.
|
|
17
|
+
*
|
|
18
|
+
* Consumers can also push ad-hoc events with {@link AnalyticsProvider.trackAnalytic}
|
|
19
|
+
* or subscribe an observable stream with {@link AnalyticsProvider.trackAnalytic$}.
|
|
11
20
|
*
|
|
12
|
-
* @typeParam AnalyticsConfig - The configuration type for analytics.
|
|
13
|
-
* @implements IAnalyticsProvider
|
|
14
21
|
* @extends BaseModuleProvider<AnalyticsConfig>
|
|
22
|
+
* @implements IAnalyticsProvider
|
|
15
23
|
*/
|
|
16
24
|
export declare class AnalyticsProvider extends BaseModuleProvider<AnalyticsConfig> implements IAnalyticsProvider {
|
|
17
25
|
#private;
|
|
18
26
|
constructor(config: AnalyticsConfig);
|
|
19
27
|
/**
|
|
20
|
-
*
|
|
28
|
+
* Initialises all adapters and collectors, then wires collector output into
|
|
29
|
+
* the adapter pipeline.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* Initialisation is idempotent within the module lifecycle — the module calls
|
|
33
|
+
* this once during `module.initialize`. Steps:
|
|
34
|
+
*
|
|
35
|
+
* 1. Initialise all collectors (via `Promise.allSettled`).
|
|
36
|
+
* 2. Initialise all adapters (via `Promise.allSettled`).
|
|
37
|
+
* 3. Subscribe to each collector and forward events into the shared subject.
|
|
38
|
+
* 4. Subscribe to the shared subject and dispatch to every adapter.
|
|
21
39
|
*
|
|
22
|
-
*
|
|
23
|
-
* 1. Storing the provided adapters
|
|
24
|
-
* 2. Initializing all adapters
|
|
25
|
-
* 3. Storing the provided collectors
|
|
26
|
-
* 4. Initializing all collectors
|
|
27
|
-
* 5. Setting up subscription for analytics processing
|
|
40
|
+
* All subscriptions are registered as teardowns on the base provider.
|
|
28
41
|
*
|
|
29
|
-
* @returns A promise that resolves when
|
|
42
|
+
* @returns A promise that resolves when all adapters and collectors are initialised.
|
|
30
43
|
*/
|
|
31
44
|
initialize(): Promise<void>;
|
|
32
45
|
/**
|
|
33
|
-
*
|
|
46
|
+
* Pushes a single analytics event to all registered adapters.
|
|
34
47
|
*
|
|
35
|
-
* @param event - The analytics event to track
|
|
48
|
+
* @param event - The analytics event to track.
|
|
36
49
|
*/
|
|
37
50
|
trackAnalytic(event: AnalyticsEvent): void;
|
|
38
51
|
/**
|
|
39
|
-
*
|
|
52
|
+
* Subscribes to an observable stream of analytics events and forwards each
|
|
53
|
+
* emission to all registered adapters.
|
|
40
54
|
*
|
|
41
|
-
* @param analytic$ - Observable input stream of
|
|
42
|
-
* @returns
|
|
55
|
+
* @param analytic$ - Observable input stream of analytics events.
|
|
56
|
+
* @returns A {@link DisposableSubscription} supporting both `unsubscribe()` and `Symbol.dispose`.
|
|
43
57
|
*/
|
|
44
58
|
trackAnalytic$(analytic$: ObservableInput<AnalyticsEvent>): Disposable & Subscription;
|
|
45
59
|
}
|
|
@@ -1,20 +1,42 @@
|
|
|
1
1
|
import type { ObservableInput, Subscription } from 'rxjs';
|
|
2
2
|
import type { AnalyticsEvent } from './types.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Public interface for the analytics provider exposed by the `analytics` module.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Use `trackAnalytic` to push a single event or `trackAnalytic$` to forward
|
|
8
|
+
* an observable stream of events. Both methods route events to all registered
|
|
9
|
+
* adapters.
|
|
5
10
|
*/
|
|
6
11
|
export interface IAnalyticsProvider {
|
|
7
12
|
/**
|
|
8
|
-
*
|
|
13
|
+
* Pushes a single analytics event to all registered adapters.
|
|
9
14
|
*
|
|
10
|
-
* @param event - The
|
|
15
|
+
* @param event - The analytics event to track.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* provider.trackAnalytic({
|
|
20
|
+
* name: 'button-click',
|
|
21
|
+
* value: 'save',
|
|
22
|
+
* attributes: { page: 'settings' },
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
11
25
|
*/
|
|
12
26
|
trackAnalytic(event: AnalyticsEvent): void;
|
|
13
27
|
/**
|
|
14
|
-
*
|
|
28
|
+
* Subscribes to an observable stream of analytics events and forwards each
|
|
29
|
+
* emission to all registered adapters.
|
|
30
|
+
*
|
|
31
|
+
* @param analytic$ - Observable input stream of analytics events.
|
|
32
|
+
* @returns A combined `Disposable & Subscription` handle for cleanup.
|
|
15
33
|
*
|
|
16
|
-
* @
|
|
17
|
-
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const sub = provider.trackAnalytic$(myEvent$);
|
|
37
|
+
* // later
|
|
38
|
+
* sub.unsubscribe();
|
|
39
|
+
* ```
|
|
18
40
|
*/
|
|
19
41
|
trackAnalytic$(analytic$: ObservableInput<AnalyticsEvent>): Disposable & Subscription;
|
|
20
42
|
}
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import type { AnalyticsEvent } from '../types.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Contract for an analytics adapter that receives events and exports them to a backend.
|
|
4
4
|
*
|
|
5
|
-
* @
|
|
5
|
+
* @remarks
|
|
6
|
+
* Implement this interface to create a custom adapter. Register it via
|
|
7
|
+
* {@link IAnalyticsConfigurator.setAdapter}. The adapter must also implement
|
|
8
|
+
* `Disposable` for resource cleanup.
|
|
9
|
+
*
|
|
10
|
+
* @template T - The analytics event type handled by the adapter, defaults to {@link AnalyticsEvent}.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* class MyAdapter implements IAnalyticsAdapter {
|
|
15
|
+
* registerAnalytic(event) { fetch('/analytics', { method: 'POST', body: JSON.stringify(event) }); }
|
|
16
|
+
* [Symbol.dispose]() { /* cleanup *\/ }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
6
19
|
*/
|
|
7
20
|
export interface IAnalyticsAdapter<T extends AnalyticsEvent = AnalyticsEvent> extends Disposable {
|
|
8
21
|
/**
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import type { IAnalyticsAdapter } from './AnalyticsAdapter.interface.js';
|
|
2
2
|
import type { AnalyticsEvent } from '../types.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Analytics adapter that logs every event to the browser console.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Useful during development and debugging. Each event is logged with the
|
|
8
|
+
* prefix `Analytics::Adapter::Console`.
|
|
9
|
+
*
|
|
10
|
+
* @template T - Analytics event type, defaults to {@link AnalyticsEvent}.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { ConsoleAnalyticsAdapter } from '@equinor/fusion-framework-module-analytics/adapters';
|
|
15
|
+
*
|
|
16
|
+
* builder.setAdapter('console', async () => new ConsoleAnalyticsAdapter());
|
|
17
|
+
* ```
|
|
5
18
|
*/
|
|
6
19
|
export declare class ConsoleAnalyticsAdapter<T extends AnalyticsEvent = AnalyticsEvent> implements IAnalyticsAdapter {
|
|
20
|
+
/** Logs the event to the console. */
|
|
7
21
|
registerAnalytic(event: T): Promise<void> | void;
|
|
8
22
|
[Symbol.dispose](): void;
|
|
9
23
|
}
|
|
@@ -3,17 +3,46 @@ import type { AnalyticsEvent } from '../types.js';
|
|
|
3
3
|
import { type ReadableLogRecord } from '@opentelemetry/sdk-logs';
|
|
4
4
|
import type { OTLPExporterBase } from '@opentelemetry/otlp-exporter-base';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Analytics adapter that forwards events to an OpenTelemetry log exporter.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* Uses `@opentelemetry/sdk-logs` to batch and export log records through the
|
|
10
|
+
* provided {@link OTLPExporterBase} transport. Each analytics event is mapped
|
|
11
|
+
* to an OTLP `LogRecord` with severity `INFO`.
|
|
12
|
+
*
|
|
13
|
+
* Resource attributes automatically include the module version, a unique
|
|
14
|
+
* session ID (UUIDv7), and the portal ID supplied at construction time.
|
|
15
|
+
*
|
|
16
|
+
* @template T - Analytics event type, defaults to {@link AnalyticsEvent}.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { FusionAnalyticsAdapter } from '@equinor/fusion-framework-module-analytics/adapters';
|
|
21
|
+
* import { OTLPLogExporter } from '@equinor/fusion-framework-module-analytics/logExporters';
|
|
22
|
+
*
|
|
23
|
+
* builder.setAdapter('fusion-log', async () => {
|
|
24
|
+
* const logExporter = new OTLPLogExporter({ url: '/v1/logs' });
|
|
25
|
+
* return new FusionAnalyticsAdapter({ portalId: 'my-portal', logExporter });
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @see {@link OTLPExporterBase}
|
|
10
30
|
*/
|
|
11
31
|
export declare class FusionAnalyticsAdapter<T extends AnalyticsEvent = AnalyticsEvent> implements IAnalyticsAdapter {
|
|
12
32
|
#private;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new `FusionAnalyticsAdapter`.
|
|
35
|
+
*
|
|
36
|
+
* @param args - Construction options.
|
|
37
|
+
* @param args.portalId - Portal identifier attached to every exported log record.
|
|
38
|
+
* @param args.logExporter - An OTLP-compatible log exporter for transport.
|
|
39
|
+
*/
|
|
13
40
|
constructor(args: {
|
|
14
41
|
portalId: string;
|
|
15
42
|
logExporter: OTLPExporterBase<ReadableLogRecord[]>;
|
|
16
43
|
});
|
|
44
|
+
/** Maps an analytics event to an OTLP `LogRecord` and emits it via the logger. */
|
|
17
45
|
registerAnalytic(event: T): Promise<void> | void;
|
|
46
|
+
/** Shuts down the log exporter and logger provider, flushing remaining records. */
|
|
18
47
|
[Symbol.dispose](): void;
|
|
19
48
|
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-exports for built-in analytics adapters.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Import from `'@equinor/fusion-framework-module-analytics/adapters'`.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
1
9
|
export { IAnalyticsAdapter } from './AnalyticsAdapter.interface.js';
|
|
2
10
|
export { ConsoleAnalyticsAdapter } from './ConsoleAnalyticsAdapter.js';
|
|
3
11
|
export { FusionAnalyticsAdapter } from './FusionAnalyticsAdapter.js';
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import type { Subscribable } from 'rxjs';
|
|
2
2
|
import type { AnalyticsEvent } from '../types.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Contract for an analytics collector that observes application state and emits
|
|
5
|
+
* structured analytics events.
|
|
5
6
|
*
|
|
6
|
-
* @
|
|
7
|
+
* @remarks
|
|
8
|
+
* Implement this interface (or extend {@link BaseCollector}) to create a custom
|
|
9
|
+
* collector. Register it via {@link IAnalyticsConfigurator.setCollector}.
|
|
10
|
+
*
|
|
11
|
+
* The collector must be `Subscribable` so the provider can listen for emitted
|
|
12
|
+
* events. Optionally implement `initialize` for async setup (e.g. resolving
|
|
13
|
+
* module dependencies).
|
|
14
|
+
*
|
|
15
|
+
* @template T - Analytics event type emitted by this collector, defaults to {@link AnalyticsEvent}.
|
|
7
16
|
*/
|
|
8
17
|
export interface IAnalyticsCollector<T extends AnalyticsEvent = AnalyticsEvent> extends Subscribable<T> {
|
|
9
18
|
/**
|
|
@@ -6,13 +6,31 @@ import type { AppModuleProvider } from '@equinor/fusion-framework-module-app';
|
|
|
6
6
|
import type { IEventModuleProvider } from '@equinor/fusion-framework-module-event';
|
|
7
7
|
import { type ObservableInput } from 'rxjs';
|
|
8
8
|
/**
|
|
9
|
-
* Collector
|
|
10
|
-
*
|
|
9
|
+
* Collector that emits an analytics event whenever an application’s modules
|
|
10
|
+
* finish loading.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* Listens to the framework `onAppModulesLoaded` event, extracts application
|
|
14
|
+
* manifest metadata, and includes the current context (if available) in the
|
|
15
|
+
* event attributes.
|
|
16
|
+
*
|
|
17
|
+
* Register via:
|
|
18
|
+
* ```ts
|
|
19
|
+
* builder.setCollector('app-loaded', async (args) => {
|
|
20
|
+
* const event = await args.requireInstance('event');
|
|
21
|
+
* const app = await args.requireInstance('app');
|
|
22
|
+
* return new AppLoadedCollector(event, app);
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
11
25
|
*/
|
|
12
26
|
export declare class AppLoadedCollector extends BaseCollector<AppItemType, {
|
|
13
27
|
context?: ContextItemType;
|
|
14
28
|
}> implements IAnalyticsCollector {
|
|
15
29
|
#private;
|
|
30
|
+
/**
|
|
31
|
+
* @param eventProvider - Fusion event module provider to listen for app-loaded events.
|
|
32
|
+
* @param appProvider - Fusion app module provider for fallback manifest data.
|
|
33
|
+
*/
|
|
16
34
|
constructor(eventProvider: IEventModuleProvider, appProvider: AppModuleProvider);
|
|
17
35
|
_initialize(): ObservableInput<{
|
|
18
36
|
value: AppItemType;
|
|
@@ -4,13 +4,27 @@ import { BaseCollector } from './BaseCollector.js';
|
|
|
4
4
|
import { type AppKeyType } from './utils/extractAppMetadata.js';
|
|
5
5
|
import type { AppModuleProvider } from '@equinor/fusion-framework-module-app';
|
|
6
6
|
/**
|
|
7
|
-
* Collector
|
|
8
|
-
*
|
|
7
|
+
* Collector that emits an analytics event whenever the active Fusion application changes.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Listens to `AppModuleProvider.current$`, pairs consecutive values, and emits
|
|
11
|
+
* both the new and previous app key metadata.
|
|
12
|
+
*
|
|
13
|
+
* Register via:
|
|
14
|
+
* ```ts
|
|
15
|
+
* builder.setCollector('app-selected', async (args) => {
|
|
16
|
+
* const app = await args.requireInstance('app');
|
|
17
|
+
* return new AppSelectedCollector(app);
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
9
20
|
*/
|
|
10
21
|
export declare class AppSelectedCollector extends BaseCollector<AppKeyType, {
|
|
11
22
|
previous?: AppKeyType;
|
|
12
23
|
}> implements IAnalyticsCollector {
|
|
13
24
|
#private;
|
|
25
|
+
/**
|
|
26
|
+
* @param appProvider - Fusion app module provider to observe.
|
|
27
|
+
*/
|
|
14
28
|
constructor(appProvider: AppModuleProvider);
|
|
15
29
|
_initialize(): ObservableInput<{
|
|
16
30
|
value: AppKeyType;
|
|
@@ -3,25 +3,80 @@ import type { IAnalyticsCollector } from './AnalyticsCollector.interface.js';
|
|
|
3
3
|
import { type ObservableInput, type Observer, type Unsubscribable } from 'rxjs';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Creates a Zod schema for validating {@link AnalyticsEvent} instances with
|
|
7
|
+
* typed value and attributes.
|
|
8
|
+
*
|
|
9
|
+
* @template TValue - Schema type for the event body.
|
|
10
|
+
* @template TAttr - Schema type for the event attributes.
|
|
11
|
+
* @param value - Zod schema validating the event body.
|
|
12
|
+
* @param attributes - Zod schema validating the event attributes.
|
|
13
|
+
* @returns A Zod object schema matching `{ name, value, attributes? }`.
|
|
7
14
|
*/
|
|
8
15
|
export declare const createSchema: <TValue = AnyValue, TAttr = AnyValueMap>(value: z.ZodSchema<TValue>, attributes: z.ZodSchema<TAttr>) => z.ZodObject<{
|
|
9
16
|
name: z.ZodString;
|
|
10
17
|
value: z.ZodType<TValue, unknown, z.core.$ZodTypeInternals<TValue, unknown>>;
|
|
11
18
|
attributes: z.ZodOptional<z.ZodType<TAttr, unknown, z.core.$ZodTypeInternals<TAttr, unknown>>>;
|
|
12
19
|
}, z.core.$strip>;
|
|
20
|
+
/** Inferred Zod schema type produced by {@link createSchema}. */
|
|
13
21
|
export type CollectorSchema<TValue = AnyValue, TAttr = AnyValueMap> = ReturnType<typeof createSchema<TValue, TAttr>>;
|
|
14
22
|
/**
|
|
15
|
-
*
|
|
16
|
-
* emitting.
|
|
23
|
+
* Abstract base class for analytics collectors that validates events against a
|
|
24
|
+
* Zod schema before emitting.
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* Subclasses implement {@link BaseCollector._initialize | _initialize} to return
|
|
28
|
+
* an observable of raw `{ value, attributes }` objects. `BaseCollector` wraps
|
|
29
|
+
* each emission with the collector name, validates it against the supplied schema,
|
|
30
|
+
* and publishes through an internal `Subject`.
|
|
31
|
+
*
|
|
32
|
+
* @template TValue - The event body type.
|
|
33
|
+
* @template TAttr - The event attributes type.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* class MyCollector extends BaseCollector<string, { page: string }> {
|
|
38
|
+
* constructor() {
|
|
39
|
+
* super('my-event', createSchema(z.string(), z.object({ page: z.string() })));
|
|
40
|
+
* }
|
|
41
|
+
* _initialize() {
|
|
42
|
+
* return of({ value: 'hello', attributes: { page: '/home' } });
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
17
46
|
*/
|
|
18
47
|
export declare abstract class BaseCollector<TValue extends AnyValue, TAttr extends AnyValueMap = AnyValueMap> implements IAnalyticsCollector<AnalyticsEvent<TValue, TAttr>> {
|
|
19
48
|
#private;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new `BaseCollector`.
|
|
51
|
+
*
|
|
52
|
+
* @param name - Event name assigned to every emission (e.g. `'context-selected'`).
|
|
53
|
+
* @param schema - Zod schema used to validate each event before publishing.
|
|
54
|
+
*/
|
|
20
55
|
constructor(name: string, schema: CollectorSchema<TValue, TAttr>);
|
|
56
|
+
/**
|
|
57
|
+
* Returns an observable source of raw `{ value, attributes }` objects.
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* Subclasses implement this to provide the domain-specific event stream.
|
|
61
|
+
* The base class wraps the output with the collector name and validates it.
|
|
62
|
+
*
|
|
63
|
+
* @returns An observable input of value/attribute pairs.
|
|
64
|
+
*/
|
|
21
65
|
abstract _initialize(): ObservableInput<{
|
|
22
66
|
value: TValue;
|
|
23
67
|
attributes: TAttr;
|
|
24
68
|
}>;
|
|
69
|
+
/**
|
|
70
|
+
* Subscribes to the source returned by {@link BaseCollector._initialize},
|
|
71
|
+
* validates each emission with the Zod schema, and publishes through the
|
|
72
|
+
* internal subject.
|
|
73
|
+
*/
|
|
25
74
|
initialize(): Promise<void> | void;
|
|
75
|
+
/**
|
|
76
|
+
* Subscribes an observer to the validated event stream.
|
|
77
|
+
*
|
|
78
|
+
* @param observer - Partial observer receiving validated events.
|
|
79
|
+
* @returns An `Unsubscribable` handle.
|
|
80
|
+
*/
|
|
26
81
|
subscribe(observer: Partial<Observer<z.infer<CollectorSchema<TValue, TAttr>>>>): Unsubscribable;
|
|
27
82
|
}
|
|
@@ -5,14 +5,31 @@ import type { AppModuleProvider } from '@equinor/fusion-framework-module-app';
|
|
|
5
5
|
import { BaseCollector } from './BaseCollector.js';
|
|
6
6
|
import { type ContextItemType } from './utils/extractContextMetadata.js';
|
|
7
7
|
/**
|
|
8
|
-
* Collector
|
|
9
|
-
*
|
|
8
|
+
* Collector that emits an analytics event whenever the active Fusion context changes.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* Listens to `IContextProvider.currentContext$`, de-duplicates by context ID,
|
|
12
|
+
* pairs consecutive values, and emits both the new and previous context
|
|
13
|
+
* metadata. The current application key is included in attributes.
|
|
14
|
+
*
|
|
15
|
+
* Register via:
|
|
16
|
+
* ```ts
|
|
17
|
+
* builder.setCollector('context-selected', async (args) => {
|
|
18
|
+
* const ctx = await args.requireInstance('context');
|
|
19
|
+
* const app = await args.requireInstance('app');
|
|
20
|
+
* return new ContextSelectedCollector(ctx, app);
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
10
23
|
*/
|
|
11
24
|
export declare class ContextSelectedCollector extends BaseCollector<ContextItemType, {
|
|
12
25
|
previous?: ContextItemType;
|
|
13
26
|
appKey?: string;
|
|
14
27
|
}> implements IAnalyticsCollector {
|
|
15
28
|
#private;
|
|
29
|
+
/**
|
|
30
|
+
* @param contextProvider - Fusion context module provider to observe.
|
|
31
|
+
* @param appProvider - Fusion app module provider for the current app key.
|
|
32
|
+
*/
|
|
16
33
|
constructor(contextProvider: IContextProvider, appProvider: AppModuleProvider);
|
|
17
34
|
_initialize(): ObservableInput<{
|
|
18
35
|
value: ContextItemType;
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-exports for built-in analytics collectors.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Import from `'@equinor/fusion-framework-module-analytics/collectors'`.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
1
9
|
export { IAnalyticsCollector } from './AnalyticsCollector.interface.js';
|
|
2
10
|
export { ContextSelectedCollector } from './ContextSelectedCollector.js';
|
|
3
11
|
export { AppSelectedCollector } from './AppSelectedCollector.js';
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { AppManifest, CurrentApp } from '@equinor/fusion-framework-module-app';
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for an object containing an optional `appKey` string.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Used by {@link AppSelectedCollector} to validate the event body.
|
|
8
|
+
*/
|
|
3
9
|
export declare const appKeySchema: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
4
10
|
appKey: z.ZodOptional<z.ZodString>;
|
|
5
11
|
}, z.core.$strip>>>;
|
|
12
|
+
/**
|
|
13
|
+
* Zod schema for a Fusion application metadata object.
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* Validates core app fields (appKey, displayName, type) and optional build
|
|
17
|
+
* and category information. Used by {@link AppLoadedCollector}.
|
|
18
|
+
*/
|
|
6
19
|
export declare const appSchema: z.ZodOptional<z.ZodObject<{
|
|
7
20
|
appKey: z.ZodString;
|
|
8
21
|
displayName: z.ZodString;
|
|
@@ -11,7 +24,21 @@ export declare const appSchema: z.ZodOptional<z.ZodObject<{
|
|
|
11
24
|
buildVersion: z.ZodOptional<z.ZodString>;
|
|
12
25
|
buildTag: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
13
26
|
}, z.core.$strip>>;
|
|
27
|
+
/** Inferred type from {@link appKeySchema}. */
|
|
14
28
|
export type AppKeyType = z.infer<typeof appKeySchema>;
|
|
29
|
+
/** Inferred type from {@link appSchema}. */
|
|
15
30
|
export type AppItemType = z.infer<typeof appSchema>;
|
|
31
|
+
/**
|
|
32
|
+
* Extracts app-key metadata from a `CurrentApp` instance.
|
|
33
|
+
*
|
|
34
|
+
* @param app - The current app object.
|
|
35
|
+
* @returns An object containing the optional `appKey`.
|
|
36
|
+
*/
|
|
16
37
|
export declare const extractAppKeyMetadata: (app: CurrentApp) => z.input<typeof appKeySchema>;
|
|
38
|
+
/**
|
|
39
|
+
* Extracts detailed app metadata from an `AppManifest` for analytics events.
|
|
40
|
+
*
|
|
41
|
+
* @param app - The application manifest.
|
|
42
|
+
* @returns An object with appKey, displayName, type, and optional build/category info.
|
|
43
|
+
*/
|
|
17
44
|
export declare const extractAppMetadata: (app: AppManifest) => z.input<typeof appSchema>;
|