@cratis/chronicle 6.33.0 → 6.35.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/ChronicleClient.ts +43 -35
- package/ChronicleOptions.ts +27 -1
- package/EventStore.ts +22 -12
- package/Metrics.ts +70 -96
- package/Tracing.ts +4 -2
- package/WellKnownTelemetryNames.ts +67 -0
- package/artifacts/validateArtifactSchemas.spec.ts +1 -1
- package/artifacts/withActivatedArtifact.ts +7 -5
- package/connection/ChronicleConnection.ts +18 -6
- package/connection/CompatibilityPreflight.ts +2 -1
- package/connection/KernelKeepAlive.ts +13 -7
- package/connection/TokenProvider.ts +3 -1
- package/connection/TraceContextMiddleware.ts +30 -0
- package/connection/for_ChronicleConnection/when_creating_clients/with_correlated_multi_host_callers.spec.ts +73 -0
- package/connection/for_OAuthTokenProvider/when_acquiring_tokens/with_http_instrumentation.spec.ts +102 -0
- package/connection/for_TraceContextMiddleware/when_calling/with_active_context.spec.ts +235 -0
- package/connection/for_TraceContextMiddleware/when_calling/with_grpc_instrumentation.spec.ts +102 -0
- package/correlation/CorrelationIdManager.ts +10 -0
- package/dist/ChronicleClient.d.ts.map +1 -1
- package/dist/ChronicleClient.js +45 -35
- package/dist/ChronicleClient.js.map +1 -1
- package/dist/ChronicleOptions.d.ts +8 -0
- package/dist/ChronicleOptions.d.ts.map +1 -1
- package/dist/ChronicleOptions.js +19 -1
- package/dist/ChronicleOptions.js.map +1 -1
- package/dist/EventStore.d.ts +3 -1
- package/dist/EventStore.d.ts.map +1 -1
- package/dist/EventStore.js +22 -12
- package/dist/EventStore.js.map +1 -1
- package/dist/Metrics.d.ts +23 -64
- package/dist/Metrics.d.ts.map +1 -1
- package/dist/Metrics.js +62 -92
- package/dist/Metrics.js.map +1 -1
- package/dist/Tracing.d.ts +1 -1
- package/dist/Tracing.d.ts.map +1 -1
- package/dist/Tracing.js +4 -2
- package/dist/Tracing.js.map +1 -1
- package/dist/WellKnownTelemetryNames.d.ts +65 -0
- package/dist/WellKnownTelemetryNames.d.ts.map +1 -0
- package/dist/WellKnownTelemetryNames.js +67 -0
- package/dist/WellKnownTelemetryNames.js.map +1 -0
- package/dist/artifacts/withActivatedArtifact.d.ts +2 -1
- package/dist/artifacts/withActivatedArtifact.d.ts.map +1 -1
- package/dist/artifacts/withActivatedArtifact.js +5 -4
- package/dist/artifacts/withActivatedArtifact.js.map +1 -1
- package/dist/connection/ChronicleConnection.d.ts +5 -0
- package/dist/connection/ChronicleConnection.d.ts.map +1 -1
- package/dist/connection/ChronicleConnection.js +13 -6
- package/dist/connection/ChronicleConnection.js.map +1 -1
- package/dist/connection/CompatibilityPreflight.d.ts.map +1 -1
- package/dist/connection/CompatibilityPreflight.js +2 -1
- package/dist/connection/CompatibilityPreflight.js.map +1 -1
- package/dist/connection/KernelKeepAlive.d.ts +3 -1
- package/dist/connection/KernelKeepAlive.d.ts.map +1 -1
- package/dist/connection/KernelKeepAlive.js +10 -7
- package/dist/connection/KernelKeepAlive.js.map +1 -1
- package/dist/connection/TokenProvider.d.ts.map +1 -1
- package/dist/connection/TokenProvider.js +3 -1
- package/dist/connection/TokenProvider.js.map +1 -1
- package/dist/connection/TraceContextMiddleware.d.ts +4 -0
- package/dist/connection/TraceContextMiddleware.d.ts.map +1 -0
- package/dist/connection/TraceContextMiddleware.js +30 -0
- package/dist/connection/TraceContextMiddleware.js.map +1 -0
- package/dist/correlation/CorrelationIdManager.d.ts +4 -0
- package/dist/correlation/CorrelationIdManager.d.ts.map +1 -1
- package/dist/correlation/CorrelationIdManager.js +8 -0
- package/dist/correlation/CorrelationIdManager.js.map +1 -1
- package/dist/eventSequences/EventLog.d.ts +2 -1
- package/dist/eventSequences/EventLog.d.ts.map +1 -1
- package/dist/eventSequences/EventLog.js +2 -2
- package/dist/eventSequences/EventLog.js.map +1 -1
- package/dist/eventSequences/EventSequence.d.ts +4 -1
- package/dist/eventSequences/EventSequence.d.ts.map +1 -1
- package/dist/eventSequences/EventSequence.js +63 -80
- package/dist/eventSequences/EventSequence.js.map +1 -1
- package/dist/eventStoreSubscriptions/EventStoreSubscriptions.d.ts.map +1 -1
- package/dist/eventStoreSubscriptions/EventStoreSubscriptions.js +3 -4
- package/dist/eventStoreSubscriptions/EventStoreSubscriptions.js.map +1 -1
- package/dist/events/handles.d.ts +12 -0
- package/dist/events/handles.d.ts.map +1 -0
- package/dist/events/handles.js +33 -0
- package/dist/events/handles.js.map +1 -0
- package/dist/events/index.d.ts +1 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +1 -0
- package/dist/events/index.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/logging/ChronicleLogEntry.d.ts +11 -0
- package/dist/logging/ChronicleLogEntry.d.ts.map +1 -0
- package/dist/logging/ChronicleLogEntry.js +4 -0
- package/dist/logging/ChronicleLogEntry.js.map +1 -0
- package/dist/logging/ChronicleLogLevel.d.ts +9 -0
- package/dist/logging/ChronicleLogLevel.d.ts.map +1 -0
- package/dist/logging/ChronicleLogLevel.js +12 -0
- package/dist/logging/ChronicleLogLevel.js.map +1 -0
- package/dist/logging/DiagChronicleLogger.d.ts +7 -0
- package/dist/logging/DiagChronicleLogger.d.ts.map +1 -0
- package/dist/logging/DiagChronicleLogger.js +10 -0
- package/dist/logging/DiagChronicleLogger.js.map +1 -0
- package/dist/logging/IChronicleLogger.d.ts +7 -0
- package/dist/logging/IChronicleLogger.d.ts.map +1 -0
- package/dist/logging/IChronicleLogger.js +4 -0
- package/dist/logging/IChronicleLogger.js.map +1 -0
- package/dist/logging/createLogger.d.ts +10 -0
- package/dist/logging/createLogger.d.ts.map +1 -0
- package/dist/logging/createLogger.js +55 -0
- package/dist/logging/createLogger.js.map +1 -0
- package/dist/observation/EventHandler.d.ts +7 -0
- package/dist/observation/EventHandler.d.ts.map +1 -0
- package/dist/observation/EventHandler.js +4 -0
- package/dist/observation/EventHandler.js.map +1 -0
- package/dist/observation/createHandlerInstanceValidator.d.ts +4 -0
- package/dist/observation/createHandlerInstanceValidator.d.ts.map +1 -0
- package/dist/observation/createHandlerInstanceValidator.js +40 -0
- package/dist/observation/createHandlerInstanceValidator.js.map +1 -0
- package/dist/observation/getEventHandlers.d.ts +5 -0
- package/dist/observation/getEventHandlers.d.ts.map +1 -0
- package/dist/observation/getEventHandlers.js +40 -0
- package/dist/observation/getEventHandlers.js.map +1 -0
- package/dist/observation/getInstanceMethods.d.ts +4 -0
- package/dist/observation/getInstanceMethods.d.ts.map +1 -0
- package/dist/observation/getInstanceMethods.js +29 -0
- package/dist/observation/getInstanceMethods.js.map +1 -0
- package/dist/projections/Projections.d.ts.map +1 -1
- package/dist/projections/Projections.js +4 -3
- package/dist/projections/Projections.js.map +1 -1
- package/dist/reactors/ReactorDispatcher.d.ts.map +1 -1
- package/dist/reactors/ReactorDispatcher.js +27 -32
- package/dist/reactors/ReactorDispatcher.js.map +1 -1
- package/dist/reactors/Reactors.d.ts +1 -0
- package/dist/reactors/Reactors.d.ts.map +1 -1
- package/dist/reactors/Reactors.js +49 -34
- package/dist/reactors/Reactors.js.map +1 -1
- package/dist/reactors/index.d.ts +1 -0
- package/dist/reactors/index.d.ts.map +1 -1
- package/dist/reactors/index.js +1 -0
- package/dist/reactors/index.js.map +1 -1
- package/dist/reducers/ReducerEventDispatcher.d.ts +1 -0
- package/dist/reducers/ReducerEventDispatcher.d.ts.map +1 -1
- package/dist/reducers/ReducerEventDispatcher.js +5 -17
- package/dist/reducers/ReducerEventDispatcher.js.map +1 -1
- package/dist/reducers/ReducerEventHandler.d.ts +3 -6
- package/dist/reducers/ReducerEventHandler.d.ts.map +1 -1
- package/dist/reducers/Reducers.d.ts +1 -0
- package/dist/reducers/Reducers.d.ts.map +1 -1
- package/dist/reducers/Reducers.js +47 -32
- package/dist/reducers/Reducers.js.map +1 -1
- package/dist/reducers/index.d.ts +1 -0
- package/dist/reducers/index.d.ts.map +1 -1
- package/dist/reducers/index.js +1 -0
- package/dist/reducers/index.js.map +1 -1
- package/dist/seeding/EventSeeding.d.ts.map +1 -1
- package/dist/seeding/EventSeeding.js +4 -3
- package/dist/seeding/EventSeeding.js.map +1 -1
- package/dist/telemetry/ChronicleTelemetryOptions.d.ts +11 -0
- package/dist/telemetry/ChronicleTelemetryOptions.d.ts.map +1 -0
- package/dist/telemetry/ChronicleTelemetryOptions.js +4 -0
- package/dist/telemetry/ChronicleTelemetryOptions.js.map +1 -0
- package/dist/telemetry/observeOperation.d.ts +6 -0
- package/dist/telemetry/observeOperation.d.ts.map +1 -0
- package/dist/telemetry/observeOperation.js +23 -0
- package/dist/telemetry/observeOperation.js.map +1 -0
- package/dist/telemetry/runInBackgroundContext.d.ts +3 -0
- package/dist/telemetry/runInBackgroundContext.d.ts.map +1 -0
- package/dist/telemetry/runInBackgroundContext.js +9 -0
- package/dist/telemetry/runInBackgroundContext.js.map +1 -0
- package/dist/telemetry/spanAttributes.d.ts +14 -0
- package/dist/telemetry/spanAttributes.d.ts.map +1 -0
- package/dist/telemetry/spanAttributes.js +47 -0
- package/dist/telemetry/spanAttributes.js.map +1 -0
- package/dist/testing/ReactorScenario.d.ts +1 -0
- package/dist/testing/ReactorScenario.d.ts.map +1 -1
- package/dist/testing/ReactorScenario.js +9 -1
- package/dist/testing/ReactorScenario.js.map +1 -1
- package/dist/testing/ReducerReadModelProcessor.d.ts.map +1 -1
- package/dist/testing/ReducerReadModelProcessor.js +1 -0
- package/dist/testing/ReducerReadModelProcessor.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/eventSequences/EventLog.ts +4 -2
- package/eventSequences/EventSequence.ts +64 -81
- package/eventStoreSubscriptions/EventStoreSubscriptions.ts +5 -5
- package/events/for_handles/when_decorating_a_method.legacy.spec.ts +91 -0
- package/events/for_handles/when_decorating_a_method.standard.spec.ts +102 -0
- package/events/handles.ts +37 -0
- package/events/index.ts +1 -0
- package/for_ChronicleClient/when_registering_artifacts/with_invalid_handler_mappings.spec.ts +142 -0
- package/for_ChronicleClient/when_starting_background_work/with_a_correlated_caller.spec.ts +150 -0
- package/for_ChronicleOptions/when_configuring_telemetry/with_event_source_identifiers.spec.ts +44 -0
- package/index.ts +7 -1
- package/logging/ChronicleLogEntry.ts +14 -0
- package/logging/ChronicleLogLevel.ts +11 -0
- package/logging/DiagChronicleLogger.ts +13 -0
- package/logging/IChronicleLogger.ts +10 -0
- package/logging/createLogger.ts +50 -0
- package/logging/for_ChronicleLogger/when_logging/with_client_owned_sinks.spec.ts +96 -0
- package/observation/EventHandler.ts +9 -0
- package/observation/createHandlerInstanceValidator.ts +42 -0
- package/observation/for_getEventHandlers/when_discovering_handlers.spec.ts +137 -0
- package/observation/for_getEventHandlers/when_reobserving_explicit_handlers.spec.ts +73 -0
- package/observation/getEventHandlers.ts +43 -0
- package/observation/getInstanceMethods.ts +29 -0
- package/package.json +8 -2
- package/projections/Projections.ts +4 -3
- package/reactors/ReactorDispatcher.ts +26 -30
- package/reactors/Reactors.ts +55 -37
- package/reactors/decorators.standard.spec.ts +8 -0
- package/reactors/for_ReactorDispatcher/when_selecting_explicit_handlers.spec.ts +64 -0
- package/reactors/for_Reactors/when_activating_a_field_override.spec.ts +62 -0
- package/reactors/for_Reactors/when_delivering/with_activation.spec.ts +14 -14
- package/reactors/for_Reactors/when_delivering_to_instance_handlers.spec.ts +108 -0
- package/reactors/for_Reactors/when_observing_explicit_handlers.legacy.spec.ts +77 -0
- package/reactors/for_Reactors/when_registering_explicit_handlers.spec.ts +53 -0
- package/reactors/index.ts +1 -0
- package/reducers/ReducerEventDispatcher.ts +5 -16
- package/reducers/ReducerEventHandler.ts +4 -6
- package/reducers/Reducers.ts +50 -35
- package/reducers/for_ReducerEventDispatcher/when_invoking_an_explicit_handler.spec.ts +51 -0
- package/reducers/for_ReducerEventDispatcher/when_invoking_instance_handlers.spec.ts +69 -0
- package/reducers/for_Reducers/when_activating_a_field_override.spec.ts +63 -0
- package/reducers/for_Reducers/when_observing_explicit_handlers.legacy.spec.ts +73 -0
- package/reducers/for_Reducers/when_registering_explicit_handlers.spec.ts +57 -0
- package/reducers/index.ts +1 -0
- package/seeding/EventSeeding.ts +6 -4
- package/telemetry/ChronicleTelemetryOptions.ts +8 -0
- package/telemetry/for_ChronicleTelemetry/given/a_telemetry_session.fixture.ts +36 -0
- package/telemetry/for_ChronicleTelemetry/given/an_event_sequence.fixture.ts +29 -0
- package/telemetry/for_ChronicleTelemetry/when_appending/with_shared_and_legacy_attributes.spec.ts +58 -0
- package/telemetry/for_ChronicleTelemetry/when_appending/without_an_sdk.spec.ts +15 -0
- package/telemetry/for_ChronicleTelemetry/when_documenting/with_public_names.spec.ts +15 -0
- package/telemetry/for_ChronicleTelemetry/when_recording_failures/with_sensitive_exception_details.spec.ts +34 -0
- package/telemetry/for_ChronicleTelemetry/when_recording_identifiers/with_per_client_privacy.spec.ts +92 -0
- package/telemetry/for_ChronicleTelemetry/when_recording_metrics/with_legacy_overlap.spec.ts +40 -0
- package/telemetry/for_ChronicleTelemetry/when_recording_sequence_numbers/with_integer_precision.spec.ts +23 -0
- package/telemetry/observeOperation.ts +25 -0
- package/telemetry/runInBackgroundContext.ts +10 -0
- package/telemetry/spanAttributes.ts +49 -0
- package/testing/ReactorScenario.ts +9 -1
- package/testing/ReducerReadModelProcessor.ts +1 -0
- package/testing/for_ReactorScenario/when_delivering_to_an_explicit_handler.spec.ts +100 -0
- package/testing/for_ReducerReadModelProcessor/when_an_instance_field_hides_a_handler.spec.ts +29 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
/** Public telemetry names. Legacy names remain available during the minor-release overlap. */
|
|
5
|
+
export const WellKnownTelemetryNames = {
|
|
6
|
+
scope: 'Cratis.Chronicle.Client',
|
|
7
|
+
legacyScope: '@cratis/chronicle',
|
|
8
|
+
attributes: {
|
|
9
|
+
correlationId: 'cratis.correlation_id',
|
|
10
|
+
eventStore: 'cratis.event_store.name',
|
|
11
|
+
namespace: 'cratis.event_store.namespace',
|
|
12
|
+
eventSequenceId: 'cratis.event_sequence.id',
|
|
13
|
+
sequenceNumber: 'cratis.event_sequence.number',
|
|
14
|
+
eventTypeId: 'cratis.event_type.id',
|
|
15
|
+
eventTypeGeneration: 'cratis.event_type.generation',
|
|
16
|
+
eventSourceType: 'cratis.event_source.type',
|
|
17
|
+
eventSourceId: 'cratis.event_source.id',
|
|
18
|
+
eventCount: 'cratis.event.count',
|
|
19
|
+
errorType: 'error.type',
|
|
20
|
+
exceptionType: 'exception.type'
|
|
21
|
+
},
|
|
22
|
+
legacyAttributes: {
|
|
23
|
+
eventStore: 'chronicle.event_store',
|
|
24
|
+
namespace: 'chronicle.namespace',
|
|
25
|
+
eventSequenceId: 'chronicle.event_sequence_id',
|
|
26
|
+
sequenceNumber: 'chronicle.sequence_number',
|
|
27
|
+
eventTypeId: 'chronicle.event_type_id',
|
|
28
|
+
eventTypeGeneration: 'chronicle.event_type_generation',
|
|
29
|
+
eventSourceId: 'chronicle.event_source_id',
|
|
30
|
+
eventCount: 'chronicle.events_count',
|
|
31
|
+
hasEvents: 'chronicle.has_events',
|
|
32
|
+
eventStreamType: 'chronicle.event_stream_type',
|
|
33
|
+
eventStreamId: 'chronicle.event_stream_id'
|
|
34
|
+
},
|
|
35
|
+
spans: {
|
|
36
|
+
append: 'chronicle.event_sequences.append',
|
|
37
|
+
appendMany: 'chronicle.event_sequences.append_many',
|
|
38
|
+
getTailSequenceNumber: 'chronicle.event_sequences.get_tail_sequence_number',
|
|
39
|
+
hasEventsFor: 'chronicle.event_sequences.has_events_for',
|
|
40
|
+
getForEventSourceIdAndEventTypes: 'chronicle.event_sequences.get_for_event_source_id_and_event_types',
|
|
41
|
+
getFromSequenceNumber: 'chronicle.event_sequences.get_from_sequence_number',
|
|
42
|
+
redact: 'chronicle.event_sequences.redact',
|
|
43
|
+
redactForEventSource: 'chronicle.event_sequences.redact_for_event_source',
|
|
44
|
+
completeStream: 'chronicle.event_sequences.complete_stream',
|
|
45
|
+
getEventStore: 'chronicle.client.get_event_store',
|
|
46
|
+
getEventStores: 'chronicle.client.get_event_stores',
|
|
47
|
+
getNamespaces: 'chronicle.event_store.get_namespaces'
|
|
48
|
+
},
|
|
49
|
+
metrics: {
|
|
50
|
+
eventsAppended: 'cratis.chronicle.event_sequence.appended',
|
|
51
|
+
batchAppendsPerformed: 'cratis.chronicle.event_sequence.batch_appends',
|
|
52
|
+
eventStoreRetrievals: 'cratis.chronicle.event_store.retrievals',
|
|
53
|
+
appendDuration: 'cratis.chronicle.event_sequence.append_duration',
|
|
54
|
+
appendManyDuration: 'cratis.chronicle.event_sequence.append_many_duration',
|
|
55
|
+
constraintViolations: 'cratis.chronicle.event_sequence.constraint_violations',
|
|
56
|
+
appendErrors: 'cratis.chronicle.event_sequence.append_errors'
|
|
57
|
+
},
|
|
58
|
+
legacyMetrics: {
|
|
59
|
+
eventsAppended: 'chronicle.events.appended',
|
|
60
|
+
batchAppendsPerformed: 'chronicle.events.batch_appends',
|
|
61
|
+
eventStoreRetrievals: 'chronicle.client.event_store_retrievals',
|
|
62
|
+
appendDuration: 'chronicle.events.append_duration',
|
|
63
|
+
appendManyDuration: 'chronicle.events.append_many_duration',
|
|
64
|
+
constraintViolations: 'chronicle.events.constraint_violations',
|
|
65
|
+
appendErrors: 'chronicle.events.append_errors'
|
|
66
|
+
}
|
|
67
|
+
} as const;
|
|
@@ -35,7 +35,7 @@ describe('artifact schema preflight', () => {
|
|
|
35
35
|
it('blocks every Kernel registration when preflight fails', async () => {
|
|
36
36
|
const register = vi.fn();
|
|
37
37
|
const connection = new Proxy({}, {
|
|
38
|
-
get: () => new Proxy({}, { get: () => register })
|
|
38
|
+
get: (_target, property) => property === 'logger' ? undefined : new Proxy({}, { get: () => register })
|
|
39
39
|
}) as ChronicleConnection;
|
|
40
40
|
const lifecycle = { onDisconnected: vi.fn(), onConnected: vi.fn() } as unknown as ConnectionLifecycle;
|
|
41
41
|
const store = new EventStore(new EventStoreName('Test'), EventStoreNamespaceName.default, connection, lifecycle, 'sink');
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Copyright (c) Cratis. All rights reserved.
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { createLogger } from '../logging/createLogger.js';
|
|
5
|
+
import type { IChronicleLogger } from '../logging/IChronicleLogger.js';
|
|
5
6
|
import type { Constructor } from '@cratis/fundamentals';
|
|
6
7
|
import type { ActivatedArtifact } from './ActivatedArtifact.js';
|
|
7
8
|
import type { ArtifactActivationContext } from './ArtifactActivationContext.js';
|
|
@@ -9,12 +10,11 @@ import type { ArtifactInvocationContext } from './ArtifactInvocationContext.js';
|
|
|
9
10
|
import { ArtifactCompletionFailed } from './ArtifactCompletionFailed.js';
|
|
10
11
|
import type { ClientArtifactsActivator } from './ClientArtifactsActivator.js';
|
|
11
12
|
|
|
12
|
-
const logger = diag.createComponentLogger({ namespace: '@cratis/chronicle/artifacts' });
|
|
13
|
-
|
|
14
13
|
/** Activates once per delivery and always releases the lease before acknowledgement. */
|
|
15
14
|
export async function withActivatedArtifact<T, R>(
|
|
16
15
|
type: Constructor<T>, context: ArtifactActivationContext, activator: ClientArtifactsActivator,
|
|
17
|
-
callback: (artifact: ActivatedArtifact<T>) => Promise<R
|
|
16
|
+
callback: (artifact: ActivatedArtifact<T>) => Promise<R>,
|
|
17
|
+
logger?: IChronicleLogger
|
|
18
18
|
): Promise<R> {
|
|
19
19
|
const artifact = await activator(type, context);
|
|
20
20
|
try {
|
|
@@ -38,7 +38,9 @@ export async function withActivatedArtifact<T, R>(
|
|
|
38
38
|
try {
|
|
39
39
|
await artifact.dispose?.();
|
|
40
40
|
} catch (error) {
|
|
41
|
-
logger.error('Error disposing activated artifact', {
|
|
41
|
+
createLogger('@cratis/chronicle/artifacts', logger).error('Error disposing activated artifact', {
|
|
42
|
+
kind: context.kind, artifactId: context.artifactId, error
|
|
43
|
+
});
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
}
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
4
|
import { status, type Channel, type ChannelCredentials, type ChannelOptions } from '@grpc/grpc-js';
|
|
5
|
-
import {
|
|
5
|
+
import { createLogger } from '../logging/createLogger.js';
|
|
6
|
+
import type { IChronicleLogger } from '../logging/IChronicleLogger.js';
|
|
7
|
+
import { traceContextMiddleware } from './TraceContextMiddleware.js';
|
|
8
|
+
import { runInBackgroundContext } from '../telemetry/runInBackgroundContext.js';
|
|
6
9
|
import {
|
|
7
10
|
ConnectionServiceDefinition,
|
|
8
11
|
ConstraintsDefinition,
|
|
@@ -46,6 +49,9 @@ import { ITokenProvider, NoOpTokenProvider, OAuthTokenProvider } from './TokenPr
|
|
|
46
49
|
* Configuration options for Chronicle connection.
|
|
47
50
|
*/
|
|
48
51
|
export interface ChronicleConnectionOptions {
|
|
52
|
+
/** Optional client-owned diagnostic sink; absent preserves the diag adapter. */
|
|
53
|
+
logger?: IChronicleLogger;
|
|
54
|
+
|
|
49
55
|
/**
|
|
50
56
|
* The connection string used to connect to Chronicle.
|
|
51
57
|
*/
|
|
@@ -120,7 +126,7 @@ export class ChronicleConnection implements ChronicleServices {
|
|
|
120
126
|
this._addressResolver = new ChronicleServerAddressResolver();
|
|
121
127
|
this._loadBalancerStrategy = createLoadBalancerStrategy(this._connectionString.loadBalancer, this._connectionString.skipTlsValidation);
|
|
122
128
|
|
|
123
|
-
this._clientsReady = this.createClients();
|
|
129
|
+
this._clientsReady = runInBackgroundContext(() => this.createClients());
|
|
124
130
|
// Building the initial channel is async (address resolution + load balancer
|
|
125
131
|
// selection), so the constructor cannot await it. Real failures still surface to
|
|
126
132
|
// callers that await connect()/resetChannel(); this only prevents an unhandled
|
|
@@ -128,6 +134,11 @@ export class ChronicleConnection implements ChronicleServices {
|
|
|
128
134
|
this._clientsReady.catch(() => {});
|
|
129
135
|
}
|
|
130
136
|
|
|
137
|
+
/** The diagnostic sink shared by services owned by this connection. */
|
|
138
|
+
get logger(): IChronicleLogger | undefined {
|
|
139
|
+
return this._options.logger;
|
|
140
|
+
}
|
|
141
|
+
|
|
131
142
|
get connectionString(): ChronicleConnectionString {
|
|
132
143
|
return this._connectionString;
|
|
133
144
|
}
|
|
@@ -243,7 +254,7 @@ export class ChronicleConnection implements ChronicleServices {
|
|
|
243
254
|
}
|
|
244
255
|
|
|
245
256
|
this._isConnected = false;
|
|
246
|
-
this._clientsReady = this.createClients();
|
|
257
|
+
this._clientsReady = runInBackgroundContext(() => this.createClients());
|
|
247
258
|
await this._clientsReady;
|
|
248
259
|
}
|
|
249
260
|
|
|
@@ -283,7 +294,8 @@ export class ChronicleConnection implements ChronicleServices {
|
|
|
283
294
|
|
|
284
295
|
this._channel = createChannel(serverAddress, credentials, channelOptions);
|
|
285
296
|
|
|
286
|
-
|
|
297
|
+
// nice-grpc invokes the last middleware first: auth retries re-enter propagation.
|
|
298
|
+
const factory = createClientFactory().use(traceContextMiddleware).use(this.createAuthMiddleware(tokenProvider));
|
|
287
299
|
this._connections = factory.create(ConnectionServiceDefinition, this._channel);
|
|
288
300
|
this._compatibility = new CompatibilityPreflight(this._connections, this._options.connectTimeout ?? 10_000);
|
|
289
301
|
const eventSequenceFactory = factory.use(this._compatibility.middleware());
|
|
@@ -360,7 +372,7 @@ export class ChronicleConnection implements ChronicleServices {
|
|
|
360
372
|
|
|
361
373
|
private createAuthMiddleware(tokenProvider: ITokenProvider): ClientMiddleware {
|
|
362
374
|
const connectionString = this._connectionString;
|
|
363
|
-
const logger =
|
|
375
|
+
const logger = createLogger('@cratis/chronicle/ChronicleConnection', this.logger);
|
|
364
376
|
const loggedFailures = new WeakSet<Error>();
|
|
365
377
|
|
|
366
378
|
return async function* authMiddleware(call, options) {
|
|
@@ -373,7 +385,7 @@ export class ChronicleConnection implements ChronicleServices {
|
|
|
373
385
|
tokenFailure = error instanceof Error ? error : new Error(String(error));
|
|
374
386
|
if (!loggedFailures.has(tokenFailure)) {
|
|
375
387
|
loggedFailures.add(tokenFailure);
|
|
376
|
-
logger.warn('Failed to obtain OAuth2 token; sending RPC without authorization', { error: tokenFailure
|
|
388
|
+
logger.warn('Failed to obtain OAuth2 token; sending RPC without authorization', { error: tokenFailure });
|
|
377
389
|
}
|
|
378
390
|
}
|
|
379
391
|
if (!token) tokenFailure ??= tokenProvider.lastTokenFailure;
|
|
@@ -6,6 +6,7 @@ import { chronicleDescriptorSet, type ConnectionServiceClient } from '@cratis/ch
|
|
|
6
6
|
import { ClientError, Status, type ClientMiddleware } from 'nice-grpc-common';
|
|
7
7
|
import { IncompatibleChronicleServer } from './IncompatibleChronicleServer.js';
|
|
8
8
|
import { clientVersion } from './clientVersion.js';
|
|
9
|
+
import { runInBackgroundContext } from '../telemetry/runInBackgroundContext.js';
|
|
9
10
|
|
|
10
11
|
const require = createRequire(import.meta.url);
|
|
11
12
|
const protocolVersion = (require('@cratis/chronicle.contracts/package.json') as { version: string }).version;
|
|
@@ -19,7 +20,7 @@ export class CompatibilityPreflight {
|
|
|
19
20
|
/** Shares in-flight checks and caches verdicts for this channel; transient failures can be retried. */
|
|
20
21
|
verify(): Promise<void> {
|
|
21
22
|
if (!this._verification) {
|
|
22
|
-
const verification = this.check().catch(error => {
|
|
23
|
+
const verification = runInBackgroundContext(() => this.check()).catch(error => {
|
|
23
24
|
if (!(error instanceof IncompatibleChronicleServer) && this._verification === verification) {
|
|
24
25
|
this._verification = undefined;
|
|
25
26
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Copyright (c) Cratis. All rights reserved.
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { createLogger } from '../logging/createLogger.js';
|
|
5
|
+
import { runInBackgroundContext } from '../telemetry/runInBackgroundContext.js';
|
|
6
|
+
import type { IChronicleLogger } from '../logging/IChronicleLogger.js';
|
|
5
7
|
import type { ConnectRequest } from '@cratis/chronicle.contracts';
|
|
6
8
|
|
|
7
9
|
/**
|
|
@@ -49,9 +51,7 @@ export class KernelKeepAlive {
|
|
|
49
51
|
/** How long a single answer may take before the connection is considered dead. */
|
|
50
52
|
static readonly defaultAnswerTimeoutMs = 5000;
|
|
51
53
|
|
|
52
|
-
private readonly _logger
|
|
53
|
-
namespace: '@cratis/chronicle/KernelKeepAlive'
|
|
54
|
-
});
|
|
54
|
+
private readonly _logger: ReturnType<typeof createLogger>;
|
|
55
55
|
|
|
56
56
|
private readonly _idleTimeoutMs: number;
|
|
57
57
|
private readonly _answerTimeoutMs: number;
|
|
@@ -65,8 +65,10 @@ export class KernelKeepAlive {
|
|
|
65
65
|
constructor(
|
|
66
66
|
private readonly connections: IKeepAliveConnections,
|
|
67
67
|
private readonly onConnectionLost: (reason: string, error: unknown) => void,
|
|
68
|
-
timeouts: KeepAliveTimeouts = {}
|
|
68
|
+
timeouts: KeepAliveTimeouts = {},
|
|
69
|
+
logger?: IChronicleLogger
|
|
69
70
|
) {
|
|
71
|
+
this._logger = createLogger('@cratis/chronicle/KernelKeepAlive', logger);
|
|
70
72
|
this._idleTimeoutMs = timeouts.idleTimeoutMs ?? KernelKeepAlive.defaultIdleTimeoutMs;
|
|
71
73
|
this._answerTimeoutMs = timeouts.answerTimeoutMs ?? KernelKeepAlive.defaultAnswerTimeoutMs;
|
|
72
74
|
}
|
|
@@ -79,7 +81,11 @@ export class KernelKeepAlive {
|
|
|
79
81
|
* @param request - The connect request identifying this client.
|
|
80
82
|
* @param signal - Aborted to stop the keep-alive entirely.
|
|
81
83
|
*/
|
|
82
|
-
|
|
84
|
+
start(request: ConnectRequest, signal: AbortSignal): Promise<void> {
|
|
85
|
+
return runInBackgroundContext(() => this.openStream(request, signal));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private async openStream(request: ConnectRequest, signal: AbortSignal): Promise<void> {
|
|
83
89
|
const stream = this.connections.connect(request, { signal });
|
|
84
90
|
const iterator = stream[Symbol.asyncIterator]();
|
|
85
91
|
|
|
@@ -136,7 +142,7 @@ export class KernelKeepAlive {
|
|
|
136
142
|
private connectionLost(reason: string, error: unknown): void {
|
|
137
143
|
this._logger.warn('Kernel keep-alive lost the connection', {
|
|
138
144
|
reason,
|
|
139
|
-
error
|
|
145
|
+
error
|
|
140
146
|
});
|
|
141
147
|
this.onConnectionLost(reason, error);
|
|
142
148
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
4
|
import { fetchOAuthAccessToken, OAuthTokenHttpError, type OAuthTokenResponse } from './fetchOAuthAccessToken.js';
|
|
5
|
+
import { runInBackgroundContext } from '../telemetry/runInBackgroundContext.js';
|
|
5
6
|
|
|
6
7
|
// Refresh once the token has less than this long left before it expires.
|
|
7
8
|
const TOKEN_REFRESH_MARGIN_MS = 60_000;
|
|
@@ -99,7 +100,8 @@ export class OAuthTokenProvider implements ITokenProvider {
|
|
|
99
100
|
return undefined;
|
|
100
101
|
}
|
|
101
102
|
|
|
102
|
-
|
|
103
|
+
// Acquisition is shared client-owned work, not part of the caller's business trace.
|
|
104
|
+
this._refreshPromise = runInBackgroundContext(() => this.fetchAndCacheAccessToken());
|
|
103
105
|
try {
|
|
104
106
|
return await this._refreshPromise;
|
|
105
107
|
} finally {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { context, propagation } from '@opentelemetry/api';
|
|
5
|
+
import { Metadata, type ClientMiddleware, type ClientMiddlewareCall, type CallOptions } from 'nice-grpc-common';
|
|
6
|
+
import { correlationIdManager } from '../correlation/index.js';
|
|
7
|
+
import { WellKnownTelemetryNames } from '../WellKnownTelemetryNames.js';
|
|
8
|
+
|
|
9
|
+
/** Injects host-configured propagation for every RPC without mutating caller metadata or baggage. */
|
|
10
|
+
export const traceContextMiddleware: ClientMiddleware = async function* <Request, Response>(call: ClientMiddlewareCall<Request, Response>, options: CallOptions) {
|
|
11
|
+
const metadata = options.metadata ? Metadata(options.metadata) : Metadata();
|
|
12
|
+
// These headers belong to the active context, never to a stale caller-supplied carrier.
|
|
13
|
+
for (const field of new Set(['traceparent', 'tracestate', 'baggage', ...propagation.fields()])) metadata.delete(field);
|
|
14
|
+
const active = context.active();
|
|
15
|
+
const key = WellKnownTelemetryNames.attributes.correlationId;
|
|
16
|
+
const correlation = correlationIdManager.scoped?.toString() ?? propagation.getBaggage(active)?.getEntry(key)?.value;
|
|
17
|
+
const filtered = propagation.setBaggage(active, propagation.createBaggage(correlation ? { [key]: { value: correlation } } : {}));
|
|
18
|
+
propagation.inject(filtered, metadata, { set: (carrier, name, value) => carrier.set(name, value) });
|
|
19
|
+
const iterator: AsyncGenerator<Response, Response | void, undefined> = context.with(filtered, () => call.next(call.request, { ...options, metadata }));
|
|
20
|
+
// Async generators execute on each advance, not at creation. Bind all advances,
|
|
21
|
+
// including cancellation/error cleanup, so gRPC instrumentation cannot restore
|
|
22
|
+
// the caller's forbidden baggage. context.with restores the consumer's scope.
|
|
23
|
+
const downstream: AsyncIterableIterator<Response, Response | void, undefined> = {
|
|
24
|
+
[Symbol.asyncIterator]() { return this; },
|
|
25
|
+
next: value => context.with(filtered, () => iterator.next(value)),
|
|
26
|
+
return: value => context.with(filtered, () => iterator.return(value)),
|
|
27
|
+
throw: error => context.with(filtered, () => iterator.throw(error))
|
|
28
|
+
};
|
|
29
|
+
return yield* downstream;
|
|
30
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { afterEach, beforeEach, chai, describe, it, vi } from 'vitest';
|
|
5
|
+
import { context, propagation, trace, type Context } from '@opentelemetry/api';
|
|
6
|
+
import { createServer, type ServiceImplementation } from 'nice-grpc';
|
|
7
|
+
import { ConnectionServiceDefinition } from '@cratis/chronicle.contracts';
|
|
8
|
+
import { ChronicleConnection } from '../../ChronicleConnection.js';
|
|
9
|
+
import { CorrelationId, correlationIdManager } from '../../../correlation/index.js';
|
|
10
|
+
import { telemetrySession } from '../../../telemetry/for_ChronicleTelemetry/given/a_telemetry_session.fixture.js';
|
|
11
|
+
|
|
12
|
+
const should = chai.should();
|
|
13
|
+
const telemetry = telemetrySession();
|
|
14
|
+
let server: ReturnType<typeof createServer>;
|
|
15
|
+
let connection: ChronicleConnection;
|
|
16
|
+
let probes: { url: string; method: string; active: Context; correlation: CorrelationId | undefined; headers: Record<string, string> }[];
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
probes = [];
|
|
20
|
+
server = createServer();
|
|
21
|
+
const unused = async () => { throw new Error('Unexpected RPC'); };
|
|
22
|
+
server.add(ConnectionServiceDefinition, {
|
|
23
|
+
...Object.fromEntries(Object.keys(ConnectionServiceDefinition.methods).map(name => [name, unused])),
|
|
24
|
+
checkCompatibility: async () => ({ IsCompatible: true, Incompatibilities: [], ServerVersion: 'test' })
|
|
25
|
+
} as ServiceImplementation<typeof ConnectionServiceDefinition>);
|
|
26
|
+
const port = await server.listen('127.0.0.1:0');
|
|
27
|
+
vi.spyOn(globalThis, 'fetch').mockImplementation(async (input, options) => {
|
|
28
|
+
await Promise.resolve();
|
|
29
|
+
const active = context.active();
|
|
30
|
+
const headers: Record<string, string> = {};
|
|
31
|
+
propagation.inject(active, headers);
|
|
32
|
+
const url = String(input);
|
|
33
|
+
probes.push({ url, method: options?.method ?? 'GET', active, correlation: correlationIdManager.scoped, headers });
|
|
34
|
+
return new Response(url.includes(`:${port}/`) ? '0' : '1');
|
|
35
|
+
});
|
|
36
|
+
const correlation = new CorrelationId('constructing-business');
|
|
37
|
+
const span = telemetry.traces.getTracer('host').startSpan('constructing-caller');
|
|
38
|
+
const active = propagation.setBaggage(trace.setSpan(context.active(), span), propagation.createBaggage({
|
|
39
|
+
'cratis.correlation_id': { value: correlation.toString() }, email: { value: 'private@example.com' }
|
|
40
|
+
}));
|
|
41
|
+
try {
|
|
42
|
+
await context.with(active, () => correlationIdManager.run(correlation, async () => {
|
|
43
|
+
connection = new ChronicleConnection({
|
|
44
|
+
connectionString: `chronicle://127.0.0.1:${port},127.0.0.1:1?disableTls=true&apiKey=test`
|
|
45
|
+
});
|
|
46
|
+
await connection.connect();
|
|
47
|
+
await connection.resetChannel();
|
|
48
|
+
context.active().should.equal(active);
|
|
49
|
+
correlationIdManager.scoped!.should.equal(correlation);
|
|
50
|
+
}));
|
|
51
|
+
} finally { span.end(); }
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
afterEach(async () => {
|
|
55
|
+
connection?.dispose();
|
|
56
|
+
await server?.shutdown();
|
|
57
|
+
vi.restoreAllMocks();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('when constructing and resetting a multi-host connection inside a business context', () => {
|
|
61
|
+
it('should detach both count probes and reservation on every client creation', () => {
|
|
62
|
+
probes.should.have.lengthOf(6);
|
|
63
|
+
probes.map(probe => probe.method).should.deep.equal(['GET', 'GET', 'POST', 'GET', 'GET', 'POST']);
|
|
64
|
+
probes.filter(probe => probe.url.endsWith('/connections/count')).should.have.lengthOf(4);
|
|
65
|
+
probes.filter(probe => probe.url.endsWith('/connections/reserve')).should.have.lengthOf(2);
|
|
66
|
+
for (const probe of probes) {
|
|
67
|
+
should.equal(trace.getSpanContext(probe.active), undefined);
|
|
68
|
+
should.equal(propagation.getBaggage(probe.active), undefined);
|
|
69
|
+
should.equal(probe.correlation, undefined);
|
|
70
|
+
probe.headers.should.deep.equal({});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
package/connection/for_OAuthTokenProvider/when_acquiring_tokens/with_http_instrumentation.spec.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { afterAll, beforeAll, beforeEach, chai, describe, it } from 'vitest';
|
|
5
|
+
import { context, propagation, trace } from '@opentelemetry/api';
|
|
6
|
+
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
|
|
7
|
+
import type { IncomingHttpHeaders, Server } from 'node:http';
|
|
8
|
+
import type { AddressInfo } from 'node:net';
|
|
9
|
+
import { createRequire, syncBuiltinESMExports } from 'node:module';
|
|
10
|
+
import type { OAuthTokenProvider } from '../../TokenProvider.js';
|
|
11
|
+
import { CorrelationId, correlationIdManager } from '../../../correlation/index.js';
|
|
12
|
+
import { telemetrySession } from '../../../telemetry/for_ChronicleTelemetry/given/a_telemetry_session.fixture.js';
|
|
13
|
+
|
|
14
|
+
const should = chai.should();
|
|
15
|
+
const telemetry = telemetrySession();
|
|
16
|
+
const correlations: Array<CorrelationId | undefined> = [];
|
|
17
|
+
const instrumentation = new HttpInstrumentation({
|
|
18
|
+
enabled: false,
|
|
19
|
+
disableIncomingRequestInstrumentation: true,
|
|
20
|
+
requestHook: () => { correlations.push(correlationIdManager.scoped); }
|
|
21
|
+
});
|
|
22
|
+
let server: Server;
|
|
23
|
+
let Provider: typeof OAuthTokenProvider;
|
|
24
|
+
let endpoint: string;
|
|
25
|
+
let lifetime: number;
|
|
26
|
+
let requests: number;
|
|
27
|
+
let received: IncomingHttpHeaders[];
|
|
28
|
+
|
|
29
|
+
beforeAll(async () => {
|
|
30
|
+
instrumentation.setTracerProvider(telemetry.traces);
|
|
31
|
+
instrumentation.enable();
|
|
32
|
+
// Vitest does not install the host's ESM loader hooks. Trigger the real require hook
|
|
33
|
+
// and synchronize the patched built-in exports before loading the provider's transport.
|
|
34
|
+
const { createServer } = createRequire(import.meta.url)('node:http') as typeof import('node:http');
|
|
35
|
+
syncBuiltinESMExports();
|
|
36
|
+
Provider = (await import('../../TokenProvider.js')).OAuthTokenProvider;
|
|
37
|
+
server = createServer((request, response) => {
|
|
38
|
+
received.push(request.headers);
|
|
39
|
+
request.resume();
|
|
40
|
+
response.writeHead(200, { 'content-type': 'application/json' });
|
|
41
|
+
response.end(JSON.stringify({ access_token: `token-${++requests}`, expires_in: lifetime }));
|
|
42
|
+
});
|
|
43
|
+
await new Promise<void>(resolve => server.listen(0, '127.0.0.1', resolve));
|
|
44
|
+
endpoint = `http://127.0.0.1:${(server.address() as AddressInfo).port}/connect/token`;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
afterAll(async () => {
|
|
48
|
+
instrumentation.disable();
|
|
49
|
+
syncBuiltinESMExports();
|
|
50
|
+
if (server) await new Promise<void>((resolve, reject) => server.close(error => error ? reject(error) : resolve()));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
for (const acquisition of ['initial', 'expiring', 'forced'] as const) {
|
|
54
|
+
describe(`when ${acquisition} token acquisition is shared by correlated callers`, () => {
|
|
55
|
+
let callerTraceIds: string[];
|
|
56
|
+
let tokens: Array<string | undefined>;
|
|
57
|
+
beforeEach(async () => {
|
|
58
|
+
received = [];
|
|
59
|
+
requests = 0;
|
|
60
|
+
lifetime = acquisition === 'expiring' ? 30 : 3600;
|
|
61
|
+
const provider = new Provider(endpoint, 'client', 'secret');
|
|
62
|
+
if (acquisition !== 'initial') await provider.getAccessToken();
|
|
63
|
+
received.length = 0;
|
|
64
|
+
correlations.length = 0;
|
|
65
|
+
telemetry.spans.reset();
|
|
66
|
+
callerTraceIds = [];
|
|
67
|
+
const pending = ['first', 'second'].map((caller, index) => {
|
|
68
|
+
const correlation = new CorrelationId(`${caller}-business`);
|
|
69
|
+
const span = telemetry.traces.getTracer('host').startSpan(caller);
|
|
70
|
+
callerTraceIds.push(span.spanContext().traceId);
|
|
71
|
+
const active = propagation.setBaggage(trace.setSpan(context.active(), span), propagation.createBaggage({
|
|
72
|
+
'cratis.correlation_id': { value: correlation.toString() },
|
|
73
|
+
email: { value: 'private@example.com' },
|
|
74
|
+
'cratis.tenant.id': { value: 'private-tenant' }
|
|
75
|
+
}));
|
|
76
|
+
return context.with(active, () => correlationIdManager.run(correlation, async () => {
|
|
77
|
+
try {
|
|
78
|
+
const token = await (index === 0 && acquisition === 'forced' ? provider.refresh() : provider.getAccessToken());
|
|
79
|
+
context.active().should.equal(active);
|
|
80
|
+
correlationIdManager.scoped!.should.equal(correlation);
|
|
81
|
+
return token;
|
|
82
|
+
} finally { span.end(); }
|
|
83
|
+
}));
|
|
84
|
+
});
|
|
85
|
+
tokens = await Promise.all(pending);
|
|
86
|
+
});
|
|
87
|
+
it('should send one shared request without caller trace or baggage', () => {
|
|
88
|
+
received.should.have.lengthOf(1);
|
|
89
|
+
should.equal(received[0].baggage, undefined);
|
|
90
|
+
for (const traceId of callerTraceIds) String(received[0].traceparent).should.not.contain(traceId);
|
|
91
|
+
const token = acquisition === 'initial' ? 'token-1' : 'token-2';
|
|
92
|
+
tokens.should.deep.equal([token, token]);
|
|
93
|
+
});
|
|
94
|
+
it('should let enabled HTTP instrumentation create a detached root span', () => {
|
|
95
|
+
const spans = telemetry.spans.getFinishedSpans().filter(span => span.instrumentationScope.name === '@opentelemetry/instrumentation-http');
|
|
96
|
+
spans.should.have.lengthOf(1);
|
|
97
|
+
should.equal(spans[0].parentSpanContext, undefined);
|
|
98
|
+
String(received[0].traceparent).should.contain(spans[0].spanContext().traceId);
|
|
99
|
+
correlations.should.deep.equal([undefined]);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|