@jaak.ai/stamps 2.2.0-dev.1 → 2.2.0-dev.10

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.
Files changed (26) hide show
  1. package/dist/cjs/jaak-stamps.cjs.entry.js +592 -3098
  2. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  3. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  4. package/dist/collection/components/my-component/my-component.js +19 -6
  5. package/dist/collection/components/my-component/my-component.js.map +1 -1
  6. package/dist/collection/services/LicenseValidationService.js +2 -2
  7. package/dist/collection/services/LicenseValidationService.js.map +1 -1
  8. package/dist/collection/services/TracingService.js +130 -78
  9. package/dist/collection/services/TracingService.js.map +1 -1
  10. package/dist/collection/services/interfaces/ITracingService.js.map +1 -1
  11. package/dist/components/jaak-stamps.js +592 -3098
  12. package/dist/components/jaak-stamps.js.map +1 -1
  13. package/dist/esm/jaak-stamps.entry.js +592 -3098
  14. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  15. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  16. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  17. package/dist/jaak-stamps-webcomponent/p-37281823.entry.js +7 -0
  18. package/dist/jaak-stamps-webcomponent/p-37281823.entry.js.map +1 -0
  19. package/dist/types/components/my-component/my-component.d.ts +1 -1
  20. package/dist/types/components.d.ts +2 -2
  21. package/dist/types/services/LicenseValidationService.d.ts +1 -1
  22. package/dist/types/services/TracingService.d.ts +6 -1
  23. package/dist/types/services/interfaces/ITracingService.d.ts +5 -0
  24. package/package.json +1 -1
  25. package/dist/jaak-stamps-webcomponent/p-8c49893d.entry.js +0 -7
  26. package/dist/jaak-stamps-webcomponent/p-8c49893d.entry.js.map +0 -1
@@ -1180,7 +1180,7 @@ class DetectionService {
1180
1180
  */
1181
1181
  /** only globals that common to node and browsers are allowed */
1182
1182
  // eslint-disable-next-line node/no-unsupported-features/es-builtins, no-undef
1183
- var _globalThis$2 = typeof globalThis === 'object'
1183
+ var _globalThis$1 = typeof globalThis === 'object'
1184
1184
  ? globalThis
1185
1185
  : typeof self === 'object'
1186
1186
  ? self
@@ -1206,7 +1206,7 @@ var _globalThis$2 = typeof globalThis === 'object'
1206
1206
  * limitations under the License.
1207
1207
  */
1208
1208
  // this is autogenerated file, see scripts/version-update.js
1209
- var VERSION$4 = '1.9.0';
1209
+ var VERSION$2 = '1.9.0';
1210
1210
 
1211
1211
  /*
1212
1212
  * Copyright The OpenTelemetry Authors
@@ -1323,7 +1323,7 @@ function _makeCompatibilityCheck(ownVersion) {
1323
1323
  *
1324
1324
  * @param version version of the API requesting an instance of the global API
1325
1325
  */
1326
- var isCompatible = _makeCompatibilityCheck(VERSION$4);
1326
+ var isCompatible = _makeCompatibilityCheck(VERSION$2);
1327
1327
 
1328
1328
  /*
1329
1329
  * Copyright The OpenTelemetry Authors
@@ -1340,14 +1340,14 @@ var isCompatible = _makeCompatibilityCheck(VERSION$4);
1340
1340
  * See the License for the specific language governing permissions and
1341
1341
  * limitations under the License.
1342
1342
  */
1343
- var major = VERSION$4.split('.')[0];
1343
+ var major = VERSION$2.split('.')[0];
1344
1344
  var GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for("opentelemetry.js.api." + major);
1345
- var _global$1 = _globalThis$2;
1345
+ var _global$1 = _globalThis$1;
1346
1346
  function registerGlobal(type, instance, diag, allowOverride) {
1347
1347
  var _a;
1348
1348
  if (allowOverride === void 0) { allowOverride = false; }
1349
1349
  var api = (_global$1[GLOBAL_OPENTELEMETRY_API_KEY] = (_a = _global$1[GLOBAL_OPENTELEMETRY_API_KEY]) !== null && _a !== void 0 ? _a : {
1350
- version: VERSION$4,
1350
+ version: VERSION$2,
1351
1351
  });
1352
1352
  if (!allowOverride && api[type]) {
1353
1353
  // already registered an API of this type
@@ -1355,14 +1355,14 @@ function registerGlobal(type, instance, diag, allowOverride) {
1355
1355
  diag.error(err.stack || err.message);
1356
1356
  return false;
1357
1357
  }
1358
- if (api.version !== VERSION$4) {
1358
+ if (api.version !== VERSION$2) {
1359
1359
  // All registered APIs must be of the same version exactly
1360
- var err = new Error("@opentelemetry/api: Registration of version v" + api.version + " for " + type + " does not match previously registered API v" + VERSION$4);
1360
+ var err = new Error("@opentelemetry/api: Registration of version v" + api.version + " for " + type + " does not match previously registered API v" + VERSION$2);
1361
1361
  diag.error(err.stack || err.message);
1362
1362
  return false;
1363
1363
  }
1364
1364
  api[type] = instance;
1365
- diag.debug("@opentelemetry/api: Registered a global for " + type + " v" + VERSION$4 + ".");
1365
+ diag.debug("@opentelemetry/api: Registered a global for " + type + " v" + VERSION$2 + ".");
1366
1366
  return true;
1367
1367
  }
1368
1368
  function getGlobal(type) {
@@ -1374,7 +1374,7 @@ function getGlobal(type) {
1374
1374
  return (_b = _global$1[GLOBAL_OPENTELEMETRY_API_KEY]) === null || _b === void 0 ? void 0 : _b[type];
1375
1375
  }
1376
1376
  function unregisterGlobal(type, diag) {
1377
- diag.debug("@opentelemetry/api: Unregistering a global for " + type + " v" + VERSION$4 + ".");
1377
+ diag.debug("@opentelemetry/api: Unregistering a global for " + type + " v" + VERSION$2 + ".");
1378
1378
  var api = _global$1[GLOBAL_OPENTELEMETRY_API_KEY];
1379
1379
  if (api) {
1380
1380
  delete api[type];
@@ -3610,41 +3610,6 @@ function getNumberFromEnv(_) {
3610
3610
  return undefined;
3611
3611
  }
3612
3612
 
3613
- /*
3614
- * Copyright The OpenTelemetry Authors
3615
- *
3616
- * Licensed under the Apache License, Version 2.0 (the "License");
3617
- * you may not use this file except in compliance with the License.
3618
- * You may obtain a copy of the License at
3619
- *
3620
- * https://www.apache.org/licenses/LICENSE-2.0
3621
- *
3622
- * Unless required by applicable law or agreed to in writing, software
3623
- * distributed under the License is distributed on an "AS IS" BASIS,
3624
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3625
- * See the License for the specific language governing permissions and
3626
- * limitations under the License.
3627
- */
3628
- // Updates to this file should also be replicated to @opentelemetry/api too.
3629
- /**
3630
- * - globalThis (New standard)
3631
- * - self (Will return the current window instance for supported browsers)
3632
- * - window (fallback for older browser implementations)
3633
- * - global (NodeJS implementation)
3634
- * - <object> (When all else fails)
3635
- */
3636
- /** only globals that common to node and browsers are allowed */
3637
- // eslint-disable-next-line n/no-unsupported-features/es-builtins, no-undef
3638
- const _globalThis$1 = typeof globalThis === 'object'
3639
- ? globalThis
3640
- : typeof self === 'object'
3641
- ? self
3642
- : typeof window === 'object'
3643
- ? window
3644
- : typeof global === 'object'
3645
- ? global
3646
- : {};
3647
-
3648
3613
  /*
3649
3614
  * Copyright The OpenTelemetry Authors
3650
3615
  *
@@ -3678,7 +3643,7 @@ const otperformance = performance;
3678
3643
  * limitations under the License.
3679
3644
  */
3680
3645
  // this is autogenerated file, see scripts/version-update.js
3681
- const VERSION$3 = '2.2.0';
3646
+ const VERSION$1 = '2.2.0';
3682
3647
 
3683
3648
  /*
3684
3649
  * Copyright The OpenTelemetry Authors
@@ -3704,35 +3669,6 @@ const VERSION$3 = '2.2.0';
3704
3669
  * @example handled
3705
3670
  * @example unhandled
3706
3671
  */
3707
- /**
3708
- * Describes a class of error the operation ended with.
3709
- *
3710
- * @example timeout
3711
- * @example java.net.UnknownHostException
3712
- * @example server_certificate_invalid
3713
- * @example 500
3714
- *
3715
- * @note The `error.type` **SHOULD** be predictable, and **SHOULD** have low cardinality.
3716
- *
3717
- * When `error.type` is set to a type (e.g., an exception type), its
3718
- * canonical class name identifying the type within the artifact **SHOULD** be used.
3719
- *
3720
- * Instrumentations **SHOULD** document the list of errors they report.
3721
- *
3722
- * The cardinality of `error.type` within one instrumentation library **SHOULD** be low.
3723
- * Telemetry consumers that aggregate data from multiple instrumentation libraries and applications
3724
- * should be prepared for `error.type` to have high cardinality at query time when no
3725
- * additional filters are applied.
3726
- *
3727
- * If the operation has completed successfully, instrumentations **SHOULD NOT** set `error.type`.
3728
- *
3729
- * If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes),
3730
- * it's **RECOMMENDED** to:
3731
- *
3732
- * - Use a domain-specific attribute
3733
- * - Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not.
3734
- */
3735
- const ATTR_ERROR_TYPE = 'error.type';
3736
3672
  /**
3737
3673
  * The exception message.
3738
3674
  *
@@ -3753,64 +3689,6 @@ const ATTR_EXCEPTION_STACKTRACE = 'exception.stacktrace';
3753
3689
  * @example OSError
3754
3690
  */
3755
3691
  const ATTR_EXCEPTION_TYPE = 'exception.type';
3756
- /**
3757
- * HTTP request method.
3758
- *
3759
- * @example GET
3760
- * @example POST
3761
- * @example HEAD
3762
- *
3763
- * @note HTTP request method value **SHOULD** be "known" to the instrumentation.
3764
- * By default, this convention defines "known" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods),
3765
- * the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html)
3766
- * and the QUERY method defined in [httpbis-safe-method-w-body](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/?include_text=1).
3767
- *
3768
- * If the HTTP request method is not known to instrumentation, it **MUST** set the `http.request.method` attribute to `_OTHER`.
3769
- *
3770
- * If the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it **MUST** provide a way to override
3771
- * the list of known HTTP methods. If this override is done via environment variable, then the environment variable **MUST** be named
3772
- * OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods
3773
- * (this list **MUST** be a full override of the default known method, it is not a list of known methods in addition to the defaults).
3774
- *
3775
- * HTTP method names are case-sensitive and `http.request.method` attribute value **MUST** match a known HTTP method name exactly.
3776
- * Instrumentations for specific web frameworks that consider HTTP methods to be case insensitive, **SHOULD** populate a canonical equivalent.
3777
- * Tracing instrumentations that do so, **MUST** also set `http.request.method_original` to the original value.
3778
- */
3779
- const ATTR_HTTP_REQUEST_METHOD = 'http.request.method';
3780
- /**
3781
- * Original HTTP method sent by the client in the request line.
3782
- *
3783
- * @example GeT
3784
- * @example ACL
3785
- * @example foo
3786
- */
3787
- const ATTR_HTTP_REQUEST_METHOD_ORIGINAL = 'http.request.method_original';
3788
- /**
3789
- * [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6).
3790
- *
3791
- * @example 200
3792
- */
3793
- const ATTR_HTTP_RESPONSE_STATUS_CODE = 'http.response.status_code';
3794
- /**
3795
- * Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name.
3796
- *
3797
- * @example example.com
3798
- * @example 10.1.2.80
3799
- * @example /tmp/my.sock
3800
- *
3801
- * @note When observed from the client side, and when communicating through an intermediary, `server.address` **SHOULD** represent the server address behind any intermediaries, for example proxies, if it's available.
3802
- */
3803
- const ATTR_SERVER_ADDRESS = 'server.address';
3804
- /**
3805
- * Server port number.
3806
- *
3807
- * @example 80
3808
- * @example 8080
3809
- * @example 443
3810
- *
3811
- * @note When observed from the client side, and when communicating through an intermediary, `server.port` **SHOULD** represent the server port behind any intermediaries, for example proxies, if it's available.
3812
- */
3813
- const ATTR_SERVER_PORT = 'server.port';
3814
3692
  /**
3815
3693
  * Logical name of the service.
3816
3694
  *
@@ -3846,45 +3724,6 @@ const ATTR_TELEMETRY_SDK_NAME = 'telemetry.sdk.name';
3846
3724
  * @example 1.2.3
3847
3725
  */
3848
3726
  const ATTR_TELEMETRY_SDK_VERSION = 'telemetry.sdk.version';
3849
- /**
3850
- * Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)
3851
- *
3852
- * @example https://www.foo.bar/search?q=OpenTelemetry#SemConv
3853
- * @example //localhost
3854
- *
3855
- * @note For network calls, URL usually has `scheme://host[:port][path][?query][#fragment]` format, where the fragment
3856
- * is not transmitted over HTTP, but if it is known, it **SHOULD** be included nevertheless.
3857
- *
3858
- * `url.full` **MUST NOT** contain credentials passed via URL in form of `https://username:password@www.example.com/`.
3859
- * In such case username and password **SHOULD** be redacted and attribute's value **SHOULD** be `https://REDACTED:REDACTED@www.example.com/`.
3860
- *
3861
- * `url.full` **SHOULD** capture the absolute URL when it is available (or can be reconstructed).
3862
- *
3863
- * Sensitive content provided in `url.full` **SHOULD** be scrubbed when instrumentations can identify it.
3864
- *
3865
- *
3866
- * Query string values for the following keys **SHOULD** be redacted by default and replaced by the
3867
- * value `REDACTED`:
3868
- *
3869
- * - [`AWSAccessKeyId`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth)
3870
- * - [`Signature`](https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html#RESTAuthenticationQueryStringAuth)
3871
- * - [`sig`](https://learn.microsoft.com/azure/storage/common/storage-sas-overview#sas-token)
3872
- * - [`X-Goog-Signature`](https://cloud.google.com/storage/docs/access-control/signed-urls)
3873
- *
3874
- * This list is subject to change over time.
3875
- *
3876
- * When a query string value is redacted, the query string key **SHOULD** still be preserved, e.g.
3877
- * `https://www.example.com/path?color=blue&sig=REDACTED`.
3878
- */
3879
- const ATTR_URL_FULL = 'url.full';
3880
- /**
3881
- * Value of the [HTTP User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) header sent by the client.
3882
- *
3883
- * @example CERN-LineMode/2.15 libwww/2.17b3
3884
- * @example Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1
3885
- * @example YourApp/1.0.0 grpc-java-okhttp/1.27.2
3886
- */
3887
- const ATTR_USER_AGENT_ORIGINAL = 'user_agent.original';
3888
3727
 
3889
3728
  /*
3890
3729
  * Copyright The OpenTelemetry Authors
@@ -3935,7 +3774,7 @@ const SDK_INFO = {
3935
3774
  [ATTR_TELEMETRY_SDK_NAME]: 'opentelemetry',
3936
3775
  [ATTR_PROCESS_RUNTIME_NAME]: 'browser',
3937
3776
  [ATTR_TELEMETRY_SDK_LANGUAGE]: TELEMETRY_SDK_LANGUAGE_VALUE_WEBJS,
3938
- [ATTR_TELEMETRY_SDK_VERSION]: VERSION$3,
3777
+ [ATTR_TELEMETRY_SDK_VERSION]: VERSION$1,
3939
3778
  };
3940
3779
 
3941
3780
  /*
@@ -3986,33 +3825,6 @@ function hrTime(performanceNow) {
3986
3825
  const now = millisToHrTime(typeof performanceNow === 'number' ? performanceNow : otperformance.now());
3987
3826
  return addHrTimes(timeOrigin, now);
3988
3827
  }
3989
- /**
3990
- *
3991
- * Converts a TimeInput to an HrTime, defaults to _hrtime().
3992
- * @param time
3993
- */
3994
- function timeInputToHrTime(time) {
3995
- // process.hrtime
3996
- if (isTimeInputHrTime(time)) {
3997
- return time;
3998
- }
3999
- else if (typeof time === 'number') {
4000
- // Must be a performance.now() if it's smaller than process start time.
4001
- if (time < getTimeOrigin()) {
4002
- return hrTime(time);
4003
- }
4004
- else {
4005
- // epoch milliseconds or performance.timeOrigin
4006
- return millisToHrTime(time);
4007
- }
4008
- }
4009
- else if (time instanceof Date) {
4010
- return millisToHrTime(time.getTime());
4011
- }
4012
- else {
4013
- throw TypeError('Invalid input type');
4014
- }
4015
- }
4016
3828
  /**
4017
3829
  * Returns a duration of two hrTime.
4018
3830
  * @param startTime
@@ -4325,7 +4137,7 @@ class TraceState {
4325
4137
  */
4326
4138
  const TRACE_PARENT_HEADER = 'traceparent';
4327
4139
  const TRACE_STATE_HEADER = 'tracestate';
4328
- const VERSION$2 = '00';
4140
+ const VERSION = '00';
4329
4141
  const VERSION_PART = '(?!ff)[\\da-f]{2}';
4330
4142
  const TRACE_ID_PART = '(?![0]{32})[\\da-f]{32}';
4331
4143
  const PARENT_ID_PART = '(?![0]{16})[\\da-f]{16}';
@@ -4369,7 +4181,7 @@ class W3CTraceContextPropagator {
4369
4181
  isTracingSuppressed(context) ||
4370
4182
  !isSpanContextValid(spanContext))
4371
4183
  return;
4372
- const traceParent = `${VERSION$2}-${spanContext.traceId}-${spanContext.spanId}-0${Number(spanContext.traceFlags || TraceFlags.NONE).toString(16)}`;
4184
+ const traceParent = `${VERSION}-${spanContext.traceId}-${spanContext.spanId}-0${Number(spanContext.traceFlags || TraceFlags.NONE).toString(16)}`;
4373
4185
  setter.set(carrier, TRACE_PARENT_HEADER, traceParent);
4374
4186
  if (spanContext.traceState) {
4375
4187
  setter.set(carrier, TRACE_STATE_HEADER, spanContext.traceState.serialize());
@@ -4714,46 +4526,6 @@ function shouldMerge(one, two) {
4714
4526
  return true;
4715
4527
  }
4716
4528
 
4717
- /*
4718
- * Copyright The OpenTelemetry Authors
4719
- *
4720
- * Licensed under the Apache License, Version 2.0 (the "License");
4721
- * you may not use this file except in compliance with the License.
4722
- * You may obtain a copy of the License at
4723
- *
4724
- * https://www.apache.org/licenses/LICENSE-2.0
4725
- *
4726
- * Unless required by applicable law or agreed to in writing, software
4727
- * distributed under the License is distributed on an "AS IS" BASIS,
4728
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4729
- * See the License for the specific language governing permissions and
4730
- * limitations under the License.
4731
- */
4732
- function urlMatches(url, urlToMatch) {
4733
- if (typeof urlToMatch === 'string') {
4734
- return url === urlToMatch;
4735
- }
4736
- else {
4737
- return !!url.match(urlToMatch);
4738
- }
4739
- }
4740
- /**
4741
- * Check if {@param url} should be ignored when comparing against {@param ignoredUrls}
4742
- * @param url
4743
- * @param ignoredUrls
4744
- */
4745
- function isUrlIgnored(url, ignoredUrls) {
4746
- if (!ignoredUrls) {
4747
- return false;
4748
- }
4749
- for (const ignoreUrl of ignoredUrls) {
4750
- if (urlMatches(url, ignoreUrl)) {
4751
- return true;
4752
- }
4753
- }
4754
- return false;
4755
- }
4756
-
4757
4529
  /*
4758
4530
  * Copyright The OpenTelemetry Authors
4759
4531
  *
@@ -6557,288 +6329,6 @@ class WebTracerProvider extends BasicTracerProvider {
6557
6329
  * See the License for the specific language governing permissions and
6558
6330
  * limitations under the License.
6559
6331
  */
6560
- var PerformanceTimingNames;
6561
- (function (PerformanceTimingNames) {
6562
- PerformanceTimingNames["CONNECT_END"] = "connectEnd";
6563
- PerformanceTimingNames["CONNECT_START"] = "connectStart";
6564
- PerformanceTimingNames["DECODED_BODY_SIZE"] = "decodedBodySize";
6565
- PerformanceTimingNames["DOM_COMPLETE"] = "domComplete";
6566
- PerformanceTimingNames["DOM_CONTENT_LOADED_EVENT_END"] = "domContentLoadedEventEnd";
6567
- PerformanceTimingNames["DOM_CONTENT_LOADED_EVENT_START"] = "domContentLoadedEventStart";
6568
- PerformanceTimingNames["DOM_INTERACTIVE"] = "domInteractive";
6569
- PerformanceTimingNames["DOMAIN_LOOKUP_END"] = "domainLookupEnd";
6570
- PerformanceTimingNames["DOMAIN_LOOKUP_START"] = "domainLookupStart";
6571
- PerformanceTimingNames["ENCODED_BODY_SIZE"] = "encodedBodySize";
6572
- PerformanceTimingNames["FETCH_START"] = "fetchStart";
6573
- PerformanceTimingNames["LOAD_EVENT_END"] = "loadEventEnd";
6574
- PerformanceTimingNames["LOAD_EVENT_START"] = "loadEventStart";
6575
- PerformanceTimingNames["NAVIGATION_START"] = "navigationStart";
6576
- PerformanceTimingNames["REDIRECT_END"] = "redirectEnd";
6577
- PerformanceTimingNames["REDIRECT_START"] = "redirectStart";
6578
- PerformanceTimingNames["REQUEST_START"] = "requestStart";
6579
- PerformanceTimingNames["RESPONSE_END"] = "responseEnd";
6580
- PerformanceTimingNames["RESPONSE_START"] = "responseStart";
6581
- PerformanceTimingNames["SECURE_CONNECTION_START"] = "secureConnectionStart";
6582
- PerformanceTimingNames["START_TIME"] = "startTime";
6583
- PerformanceTimingNames["UNLOAD_EVENT_END"] = "unloadEventEnd";
6584
- PerformanceTimingNames["UNLOAD_EVENT_START"] = "unloadEventStart";
6585
- })(PerformanceTimingNames || (PerformanceTimingNames = {}));
6586
-
6587
- /*
6588
- * Copyright The OpenTelemetry Authors
6589
- *
6590
- * Licensed under the Apache License, Version 2.0 (the "License");
6591
- * you may not use this file except in compliance with the License.
6592
- * You may obtain a copy of the License at
6593
- *
6594
- * https://www.apache.org/licenses/LICENSE-2.0
6595
- *
6596
- * Unless required by applicable law or agreed to in writing, software
6597
- * distributed under the License is distributed on an "AS IS" BASIS,
6598
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6599
- * See the License for the specific language governing permissions and
6600
- * limitations under the License.
6601
- */
6602
- /*
6603
- * This file contains a copy of unstable semantic convention definitions
6604
- * used by this package.
6605
- * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv
6606
- */
6607
- /**
6608
- * Deprecated, use `http.response.header.<key>` instead.
6609
- *
6610
- * @example 3495
6611
- *
6612
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
6613
- *
6614
- * @deprecated Replaced by `http.response.header.<key>`.
6615
- */
6616
- const ATTR_HTTP_RESPONSE_CONTENT_LENGTH = 'http.response_content_length';
6617
- /**
6618
- * Deprecated, use `http.response.body.size` instead.
6619
- *
6620
- * @example 5493
6621
- *
6622
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
6623
- *
6624
- * @deprecated Replace by `http.response.body.size`.
6625
- */
6626
- const ATTR_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED = 'http.response_content_length_uncompressed';
6627
-
6628
- /*
6629
- * Copyright The OpenTelemetry Authors
6630
- *
6631
- * Licensed under the Apache License, Version 2.0 (the "License");
6632
- * you may not use this file except in compliance with the License.
6633
- * You may obtain a copy of the License at
6634
- *
6635
- * https://www.apache.org/licenses/LICENSE-2.0
6636
- *
6637
- * Unless required by applicable law or agreed to in writing, software
6638
- * distributed under the License is distributed on an "AS IS" BASIS,
6639
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6640
- * See the License for the specific language governing permissions and
6641
- * limitations under the License.
6642
- */
6643
- // Used to normalize relative URLs
6644
- let urlNormalizingAnchor;
6645
- function getUrlNormalizingAnchor() {
6646
- if (!urlNormalizingAnchor) {
6647
- urlNormalizingAnchor = document.createElement('a');
6648
- }
6649
- return urlNormalizingAnchor;
6650
- }
6651
- /**
6652
- * Helper function to be able to use enum as typed key in type and in interface when using forEach
6653
- * @param obj
6654
- * @param key
6655
- */
6656
- function hasKey(obj, key) {
6657
- return key in obj;
6658
- }
6659
- /**
6660
- * Helper function for starting an event on span based on {@link PerformanceEntries}
6661
- * @param span
6662
- * @param performanceName name of performance entry for time start
6663
- * @param entries
6664
- * @param ignoreZeros
6665
- */
6666
- function addSpanNetworkEvent(span, performanceName, entries, ignoreZeros = true) {
6667
- if (hasKey(entries, performanceName) &&
6668
- typeof entries[performanceName] === 'number' &&
6669
- !(ignoreZeros && entries[performanceName] === 0)) {
6670
- return span.addEvent(performanceName, entries[performanceName]);
6671
- }
6672
- return undefined;
6673
- }
6674
- /**
6675
- * Helper function for adding network events and content length attributes.
6676
- */
6677
- function addSpanNetworkEvents(span, resource, ignoreNetworkEvents = false, ignoreZeros, skipOldSemconvContentLengthAttrs) {
6678
- if (ignoreZeros === undefined) {
6679
- ignoreZeros = resource[PerformanceTimingNames.START_TIME] !== 0;
6680
- }
6681
- if (!ignoreNetworkEvents) {
6682
- addSpanNetworkEvent(span, PerformanceTimingNames.FETCH_START, resource, ignoreZeros);
6683
- addSpanNetworkEvent(span, PerformanceTimingNames.DOMAIN_LOOKUP_START, resource, ignoreZeros);
6684
- addSpanNetworkEvent(span, PerformanceTimingNames.DOMAIN_LOOKUP_END, resource, ignoreZeros);
6685
- addSpanNetworkEvent(span, PerformanceTimingNames.CONNECT_START, resource, ignoreZeros);
6686
- addSpanNetworkEvent(span, PerformanceTimingNames.SECURE_CONNECTION_START, resource, ignoreZeros);
6687
- addSpanNetworkEvent(span, PerformanceTimingNames.CONNECT_END, resource, ignoreZeros);
6688
- addSpanNetworkEvent(span, PerformanceTimingNames.REQUEST_START, resource, ignoreZeros);
6689
- addSpanNetworkEvent(span, PerformanceTimingNames.RESPONSE_START, resource, ignoreZeros);
6690
- addSpanNetworkEvent(span, PerformanceTimingNames.RESPONSE_END, resource, ignoreZeros);
6691
- }
6692
- if (!skipOldSemconvContentLengthAttrs) {
6693
- // This block adds content-length-related span attributes using the
6694
- // *old* HTTP semconv (v1.7.0).
6695
- const encodedLength = resource[PerformanceTimingNames.ENCODED_BODY_SIZE];
6696
- if (encodedLength !== undefined) {
6697
- span.setAttribute(ATTR_HTTP_RESPONSE_CONTENT_LENGTH, encodedLength);
6698
- }
6699
- const decodedLength = resource[PerformanceTimingNames.DECODED_BODY_SIZE];
6700
- // Spec: Not set if transport encoding not used (in which case encoded and decoded sizes match)
6701
- if (decodedLength !== undefined && encodedLength !== decodedLength) {
6702
- span.setAttribute(ATTR_HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED, decodedLength);
6703
- }
6704
- }
6705
- }
6706
- /**
6707
- * sort resources by startTime
6708
- * @param filteredResources
6709
- */
6710
- function sortResources(filteredResources) {
6711
- return filteredResources.slice().sort((a, b) => {
6712
- const valueA = a[PerformanceTimingNames.FETCH_START];
6713
- const valueB = b[PerformanceTimingNames.FETCH_START];
6714
- if (valueA > valueB) {
6715
- return 1;
6716
- }
6717
- else if (valueA < valueB) {
6718
- return -1;
6719
- }
6720
- return 0;
6721
- });
6722
- }
6723
- /** Returns the origin if present (if in browser context). */
6724
- function getOrigin() {
6725
- return typeof location !== 'undefined' ? location.origin : undefined;
6726
- }
6727
- /**
6728
- * Get closest performance resource ignoring the resources that have been
6729
- * already used.
6730
- * @param spanUrl
6731
- * @param startTimeHR
6732
- * @param endTimeHR
6733
- * @param resources
6734
- * @param ignoredResources
6735
- * @param initiatorType
6736
- */
6737
- function getResource(spanUrl, startTimeHR, endTimeHR, resources, ignoredResources = new WeakSet(), initiatorType) {
6738
- // de-relativize the URL before usage (does no harm to absolute URLs)
6739
- const parsedSpanUrl = parseUrl(spanUrl);
6740
- spanUrl = parsedSpanUrl.toString();
6741
- const filteredResources = filterResourcesForSpan(spanUrl, startTimeHR, endTimeHR, resources, ignoredResources, initiatorType);
6742
- if (filteredResources.length === 0) {
6743
- return {
6744
- mainRequest: undefined,
6745
- };
6746
- }
6747
- if (filteredResources.length === 1) {
6748
- return {
6749
- mainRequest: filteredResources[0],
6750
- };
6751
- }
6752
- const sorted = sortResources(filteredResources);
6753
- if (parsedSpanUrl.origin !== getOrigin() && sorted.length > 1) {
6754
- let corsPreFlightRequest = sorted[0];
6755
- let mainRequest = findMainRequest(sorted, corsPreFlightRequest[PerformanceTimingNames.RESPONSE_END], endTimeHR);
6756
- const responseEnd = corsPreFlightRequest[PerformanceTimingNames.RESPONSE_END];
6757
- const fetchStart = mainRequest[PerformanceTimingNames.FETCH_START];
6758
- // no corsPreFlightRequest
6759
- if (fetchStart < responseEnd) {
6760
- mainRequest = corsPreFlightRequest;
6761
- corsPreFlightRequest = undefined;
6762
- }
6763
- return {
6764
- corsPreFlightRequest,
6765
- mainRequest,
6766
- };
6767
- }
6768
- else {
6769
- return {
6770
- mainRequest: filteredResources[0],
6771
- };
6772
- }
6773
- }
6774
- /**
6775
- * Will find the main request skipping the cors pre flight requests
6776
- * @param resources
6777
- * @param corsPreFlightRequestEndTime
6778
- * @param spanEndTimeHR
6779
- */
6780
- function findMainRequest(resources, corsPreFlightRequestEndTime, spanEndTimeHR) {
6781
- const spanEndTime = hrTimeToNanoseconds(spanEndTimeHR);
6782
- const minTime = hrTimeToNanoseconds(timeInputToHrTime(corsPreFlightRequestEndTime));
6783
- let mainRequest = resources[1];
6784
- let bestGap;
6785
- const length = resources.length;
6786
- for (let i = 1; i < length; i++) {
6787
- const resource = resources[i];
6788
- const resourceStartTime = hrTimeToNanoseconds(timeInputToHrTime(resource[PerformanceTimingNames.FETCH_START]));
6789
- const resourceEndTime = hrTimeToNanoseconds(timeInputToHrTime(resource[PerformanceTimingNames.RESPONSE_END]));
6790
- const currentGap = spanEndTime - resourceEndTime;
6791
- if (resourceStartTime >= minTime && (!bestGap || currentGap < bestGap)) {
6792
- bestGap = currentGap;
6793
- mainRequest = resource;
6794
- }
6795
- }
6796
- return mainRequest;
6797
- }
6798
- /**
6799
- * Filter all resources that has started and finished according to span start time and end time.
6800
- * It will return the closest resource to a start time
6801
- * @param spanUrl
6802
- * @param startTimeHR
6803
- * @param endTimeHR
6804
- * @param resources
6805
- * @param ignoredResources
6806
- */
6807
- function filterResourcesForSpan(spanUrl, startTimeHR, endTimeHR, resources, ignoredResources, initiatorType) {
6808
- const startTime = hrTimeToNanoseconds(startTimeHR);
6809
- const endTime = hrTimeToNanoseconds(endTimeHR);
6810
- let filteredResources = resources.filter(resource => {
6811
- const resourceStartTime = hrTimeToNanoseconds(timeInputToHrTime(resource[PerformanceTimingNames.FETCH_START]));
6812
- const resourceEndTime = hrTimeToNanoseconds(timeInputToHrTime(resource[PerformanceTimingNames.RESPONSE_END]));
6813
- return (resource.initiatorType.toLowerCase() ===
6814
- (initiatorType || 'xmlhttprequest') &&
6815
- resource.name === spanUrl &&
6816
- resourceStartTime >= startTime &&
6817
- resourceEndTime <= endTime);
6818
- });
6819
- if (filteredResources.length > 0) {
6820
- filteredResources = filteredResources.filter(resource => {
6821
- return !ignoredResources.has(resource);
6822
- });
6823
- }
6824
- return filteredResources;
6825
- }
6826
- /**
6827
- * Parses url using URL constructor or fallback to anchor element.
6828
- * @param url
6829
- */
6830
- function parseUrl(url) {
6831
- if (typeof URL === 'function') {
6832
- return new URL(url, typeof document !== 'undefined'
6833
- ? document.baseURI
6834
- : typeof location !== 'undefined' // Some JS runtimes (e.g. Deno) don't define this
6835
- ? location.href
6836
- : undefined);
6837
- }
6838
- const element = getUrlNormalizingAnchor();
6839
- element.href = url;
6840
- return element;
6841
- }
6842
6332
  /**
6843
6333
  * Get element XPath
6844
6334
  * @param target - target element
@@ -6917,25 +6407,6 @@ function getNodeValue(target, optimised) {
6917
6407
  }
6918
6408
  return `/${nodeValue}`;
6919
6409
  }
6920
- /**
6921
- * Checks if trace headers should be propagated
6922
- * @param spanUrl
6923
- * @private
6924
- */
6925
- function shouldPropagateTraceHeaders(spanUrl, propagateTraceHeaderCorsUrls) {
6926
- let propagateTraceHeaderUrls = propagateTraceHeaderCorsUrls || [];
6927
- if (typeof propagateTraceHeaderUrls === 'string' ||
6928
- propagateTraceHeaderUrls instanceof RegExp) {
6929
- propagateTraceHeaderUrls = [propagateTraceHeaderUrls];
6930
- }
6931
- const parsedSpanUrl = parseUrl(spanUrl);
6932
- if (parsedSpanUrl.origin === getOrigin()) {
6933
- return true;
6934
- }
6935
- else {
6936
- return propagateTraceHeaderUrls.some(propagateTraceHeaderUrl => urlMatches(spanUrl, propagateTraceHeaderUrl));
6937
- }
6938
- }
6939
6410
 
6940
6411
  /*
6941
6412
  * Copyright The OpenTelemetry Authors
@@ -16265,21 +15736,6 @@ class InstrumentationBase extends InstrumentationAbstract {
16265
15736
  * @param execute - function to be executed
16266
15737
  * @param onFinish - callback to run when execute finishes
16267
15738
  */
16268
- function safeExecuteInTheMiddle(execute, onFinish, preventThrowingError) {
16269
- let error;
16270
- let result;
16271
- try {
16272
- result = execute();
16273
- }
16274
- catch (e) {
16275
- error = e;
16276
- }
16277
- finally {
16278
- onFinish(error, result);
16279
- // eslint-disable-next-line no-unsafe-finally
16280
- return result;
16281
- }
16282
- }
16283
15739
  /**
16284
15740
  * Checks if certain function has been already wrapped
16285
15741
  * @param func
@@ -16306,80 +15762,13 @@ function isWrapped(func) {
16306
15762
  * See the License for the specific language governing permissions and
16307
15763
  * limitations under the License.
16308
15764
  */
16309
- var SemconvStability;
16310
- (function (SemconvStability) {
16311
- /** Emit only stable semantic conventions. */
16312
- SemconvStability[SemconvStability["STABLE"] = 1] = "STABLE";
16313
- /** Emit only old semantic conventions. */
16314
- SemconvStability[SemconvStability["OLD"] = 2] = "OLD";
16315
- /** Emit both stable and old semantic conventions. */
16316
- SemconvStability[SemconvStability["DUPLICATE"] = 3] = "DUPLICATE";
16317
- })(SemconvStability || (SemconvStability = {}));
16318
- /**
16319
- * Determine the appropriate semconv stability for the given namespace.
16320
- *
16321
- * This will parse the given string of comma-separated values (often
16322
- * `process.env.OTEL_SEMCONV_STABILITY_OPT_IN`) looking for the `${namespace}`
16323
- * or `${namespace}/dup` tokens. This is a pattern defined by a number of
16324
- * non-normative semconv documents.
16325
- *
16326
- * For example:
16327
- * - namespace 'http': https://opentelemetry.io/docs/specs/semconv/non-normative/http-migration/
16328
- * - namespace 'database': https://opentelemetry.io/docs/specs/semconv/non-normative/database-migration/
16329
- * - namespace 'k8s': https://opentelemetry.io/docs/specs/semconv/non-normative/k8s-migration/
16330
- *
16331
- * Usage:
16332
- *
16333
- * import {SemconvStability, semconvStabilityFromStr} from '@opentelemetry/instrumentation';
16334
- *
16335
- * export class FooInstrumentation extends InstrumentationBase<FooInstrumentationConfig> {
16336
- * private _semconvStability: SemconvStability;
16337
- * constructor(config: FooInstrumentationConfig = {}) {
16338
- * super('@opentelemetry/instrumentation-foo', VERSION, config);
16339
- *
16340
- * // When supporting the OTEL_SEMCONV_STABILITY_OPT_IN envvar
16341
- * this._semconvStability = semconvStabilityFromStr(
16342
- * 'http',
16343
- * process.env.OTEL_SEMCONV_STABILITY_OPT_IN
16344
- * );
16345
- *
16346
- * // or when supporting a `semconvStabilityOptIn` config option (e.g. for
16347
- * // the web where there are no envvars).
16348
- * this._semconvStability = semconvStabilityFromStr(
16349
- * 'http',
16350
- * config?.semconvStabilityOptIn
16351
- * );
16352
- * }
16353
- * }
16354
- *
16355
- * // Then, to apply semconv, use the following or similar:
16356
- * if (this._semconvStability & SemconvStability.OLD) {
16357
- * // ...
16358
- * }
16359
- * if (this._semconvStability & SemconvStability.STABLE) {
16360
- * // ...
16361
- * }
16362
- *
16363
- */
16364
- function semconvStabilityFromStr(namespace, str) {
16365
- let semconvStability = SemconvStability.OLD;
16366
- // The same parsing of `str` as `getStringListFromEnv` from the core pkg.
16367
- const entries = str
16368
- ?.split(',')
16369
- .map(v => v.trim())
16370
- .filter(s => s !== '');
16371
- for (const entry of entries ?? []) {
16372
- if (entry.toLowerCase() === namespace + '/dup') {
16373
- // DUPLICATE takes highest precedence.
16374
- semconvStability = SemconvStability.DUPLICATE;
16375
- break;
16376
- }
16377
- else if (entry.toLowerCase() === namespace) {
16378
- semconvStability = SemconvStability.STABLE;
16379
- }
16380
- }
16381
- return semconvStability;
16382
- }
15765
+ var AttributeNames;
15766
+ (function (AttributeNames) {
15767
+ AttributeNames["EVENT_TYPE"] = "event_type";
15768
+ AttributeNames["TARGET_ELEMENT"] = "target_element";
15769
+ AttributeNames["TARGET_XPATH"] = "target_xpath";
15770
+ AttributeNames["HTTP_URL"] = "http.url";
15771
+ })(AttributeNames || (AttributeNames = {}));
16383
15772
 
16384
15773
  /*
16385
15774
  * Copyright The OpenTelemetry Authors
@@ -16396,117 +15785,9 @@ function semconvStabilityFromStr(namespace, str) {
16396
15785
  * See the License for the specific language governing permissions and
16397
15786
  * limitations under the License.
16398
15787
  */
16399
- /**
16400
- * https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md
16401
- */
16402
- var AttributeNames$3;
16403
- (function (AttributeNames) {
16404
- AttributeNames["COMPONENT"] = "component";
16405
- AttributeNames["HTTP_STATUS_TEXT"] = "http.status_text";
16406
- })(AttributeNames$3 || (AttributeNames$3 = {}));
16407
-
16408
- /*
16409
- * Copyright The OpenTelemetry Authors
16410
- *
16411
- * Licensed under the Apache License, Version 2.0 (the "License");
16412
- * you may not use this file except in compliance with the License.
16413
- * You may obtain a copy of the License at
16414
- *
16415
- * https://www.apache.org/licenses/LICENSE-2.0
16416
- *
16417
- * Unless required by applicable law or agreed to in writing, software
16418
- * distributed under the License is distributed on an "AS IS" BASIS,
16419
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16420
- * See the License for the specific language governing permissions and
16421
- * limitations under the License.
16422
- */
16423
- /*
16424
- * This file contains a copy of unstable semantic convention definitions
16425
- * used by this package.
16426
- * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv
16427
- */
16428
- /**
16429
- * Deprecated, use one of `server.address`, `client.address` or `http.request.header.host` instead, depending on the usage.
16430
- *
16431
- * @example www.example.org
16432
- *
16433
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
16434
- *
16435
- * @deprecated Replaced by one of `server.address`, `client.address` or `http.request.header.host`, depending on the usage.
16436
- */
16437
- const ATTR_HTTP_HOST$1 = 'http.host';
16438
- /**
16439
- * Deprecated, use `http.request.method` instead.
16440
- *
16441
- * @example GET
16442
- * @example POST
16443
- * @example HEAD
16444
- *
16445
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
16446
- *
16447
- * @deprecated Replaced by `http.request.method`.
16448
- */
16449
- const ATTR_HTTP_METHOD$1 = 'http.method';
16450
- /**
16451
- * The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.
16452
- *
16453
- * @example 3495
16454
- *
16455
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
16456
- */
16457
- const ATTR_HTTP_REQUEST_BODY_SIZE$1 = 'http.request.body.size';
16458
- /**
16459
- * Deprecated, use `http.request.body.size` instead.
16460
- *
16461
- * @example 5493
16462
- *
16463
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
16464
- *
16465
- * @deprecated Replaced by `http.request.body.size`.
16466
- */
16467
- const ATTR_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED$1 = 'http.request_content_length_uncompressed';
16468
- /**
16469
- * Deprecated, use `url.scheme` instead.
16470
- *
16471
- * @example http
16472
- * @example https
16473
- *
16474
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
16475
- *
16476
- * @deprecated Replaced by `url.scheme` instead.
16477
- */
16478
- const ATTR_HTTP_SCHEME$1 = 'http.scheme';
16479
- /**
16480
- * Deprecated, use `http.response.status_code` instead.
16481
- *
16482
- * @example 200
16483
- *
16484
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
16485
- *
16486
- * @deprecated Replaced by `http.response.status_code`.
16487
- */
16488
- const ATTR_HTTP_STATUS_CODE$1 = 'http.status_code';
16489
- /**
16490
- * Deprecated, use `url.full` instead.
16491
- *
16492
- * @example https://www.foo.bar/search?q=OpenTelemetry#SemConv
16493
- *
16494
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
16495
- *
16496
- * @deprecated Replaced by `url.full`.
16497
- */
16498
- const ATTR_HTTP_URL$2 = 'http.url';
16499
- /**
16500
- * Deprecated, use `user_agent.original` instead.
16501
- *
16502
- * @example CERN-LineMode/2.15 libwww/2.17b3
16503
- * @example Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1
16504
- *
16505
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
16506
- *
16507
- * @deprecated Replaced by `user_agent.original`.
16508
- */
16509
- const ATTR_HTTP_USER_AGENT$2 = 'http.user_agent';
15788
+ // this is autogenerated file, see scripts/version-update.js
15789
+ const PACKAGE_VERSION = '0.53.0';
15790
+ const PACKAGE_NAME = '@opentelemetry/instrumentation-user-interaction';
16510
15791
 
16511
15792
  /*
16512
15793
  * Copyright The OpenTelemetry Authors
@@ -16523,2375 +15804,532 @@ const ATTR_HTTP_USER_AGENT$2 = 'http.user_agent';
16523
15804
  * See the License for the specific language governing permissions and
16524
15805
  * limitations under the License.
16525
15806
  */
16526
- // Much of the logic here overlaps with the same utils file in opentelemetry-instrumentation-xml-http-request
16527
- // These may be unified in the future.
16528
- const DIAG_LOGGER$1 = diag.createComponentLogger({
16529
- namespace: '@opentelemetry/opentelemetry-instrumentation-fetch/utils',
16530
- });
16531
- /**
16532
- * Helper function to determine payload content length for fetch requests
16533
- *
16534
- * The fetch API is kinda messy: there are a couple of ways the body can be passed in.
16535
- *
16536
- * In all cases, the body param can be some variation of ReadableStream,
16537
- * and ReadableStreams can only be read once! We want to avoid consuming the body here,
16538
- * because that would mean that the body never gets sent with the actual fetch request.
16539
- *
16540
- * Either the first arg is a Request object, which can be cloned
16541
- * so we can clone that object and read the body of the clone
16542
- * without disturbing the original argument
16543
- * However, reading the body here can only be done async; the body() method returns a promise
16544
- * this means this entire function has to return a promise
16545
- *
16546
- * OR the first arg is a url/string
16547
- * in which case the second arg has type RequestInit
16548
- * RequestInit is NOT cloneable, but RequestInit.body is writable
16549
- * so we can chain it into ReadableStream.pipeThrough()
16550
- *
16551
- * ReadableStream.pipeThrough() lets us process a stream and returns a new stream
16552
- * So we can measure the body length as it passes through the pie, but need to attach
16553
- * the new stream to the original request
16554
- * so that the browser still has access to the body.
16555
- *
16556
- * @param body
16557
- * @returns promise that resolves to the content length of the body
16558
- */
16559
- function getFetchBodyLength(...args) {
16560
- if (args[0] instanceof URL || typeof args[0] === 'string') {
16561
- const requestInit = args[1];
16562
- if (!requestInit?.body) {
16563
- return Promise.resolve();
16564
- }
16565
- if (requestInit.body instanceof ReadableStream) {
16566
- const { body, length } = _getBodyNonDestructively(requestInit.body);
16567
- requestInit.body = body;
16568
- return length;
16569
- }
16570
- else {
16571
- return Promise.resolve(getXHRBodyLength$1(requestInit.body));
16572
- }
16573
- }
16574
- else {
16575
- const info = args[0];
16576
- if (!info?.body) {
16577
- return Promise.resolve();
16578
- }
16579
- return info
16580
- .clone()
16581
- .text()
16582
- .then(t => getByteLength$1(t));
16583
- }
16584
- }
16585
- function _getBodyNonDestructively(body) {
16586
- // can't read a ReadableStream without destroying it
16587
- // but we CAN pipe it through and return a new ReadableStream
16588
- // some (older) platforms don't expose the pipeThrough method and in that scenario, we're out of luck;
16589
- // there's no way to read the stream without consuming it.
16590
- if (!body.pipeThrough) {
16591
- DIAG_LOGGER$1.warn('Platform has ReadableStream but not pipeThrough!');
16592
- return {
16593
- body,
16594
- length: Promise.resolve(undefined),
16595
- };
16596
- }
16597
- let length = 0;
16598
- let resolveLength;
16599
- const lengthPromise = new Promise(resolve => {
16600
- resolveLength = resolve;
16601
- });
16602
- const transform = new TransformStream({
16603
- start() { },
16604
- async transform(chunk, controller) {
16605
- const bytearray = (await chunk);
16606
- length += bytearray.byteLength;
16607
- controller.enqueue(chunk);
16608
- },
16609
- flush() {
16610
- resolveLength(length);
16611
- },
16612
- });
16613
- return {
16614
- body: body.pipeThrough(transform),
16615
- length: lengthPromise,
16616
- };
16617
- }
16618
- function isDocument$1(value) {
16619
- return typeof Document !== 'undefined' && value instanceof Document;
16620
- }
16621
- /**
16622
- * Helper function to determine payload content length for XHR requests
16623
- * @param body
16624
- * @returns content length
16625
- */
16626
- function getXHRBodyLength$1(body) {
16627
- if (isDocument$1(body)) {
16628
- return new XMLSerializer().serializeToString(document).length;
16629
- }
16630
- // XMLHttpRequestBodyInit expands to the following:
16631
- if (typeof body === 'string') {
16632
- return getByteLength$1(body);
16633
- }
16634
- if (body instanceof Blob) {
16635
- return body.size;
16636
- }
16637
- if (body instanceof FormData) {
16638
- return getFormDataSize$1(body);
16639
- }
16640
- if (body instanceof URLSearchParams) {
16641
- return getByteLength$1(body.toString());
16642
- }
16643
- // ArrayBuffer | ArrayBufferView
16644
- if (body.byteLength !== undefined) {
16645
- return body.byteLength;
16646
- }
16647
- DIAG_LOGGER$1.warn('unknown body type');
16648
- return undefined;
16649
- }
16650
- const TEXT_ENCODER$1 = new TextEncoder();
16651
- function getByteLength$1(s) {
16652
- return TEXT_ENCODER$1.encode(s).byteLength;
16653
- }
16654
- function getFormDataSize$1(formData) {
16655
- let size = 0;
16656
- for (const [key, value] of formData.entries()) {
16657
- size += key.length;
16658
- if (value instanceof Blob) {
16659
- size += value.size;
16660
- }
16661
- else {
16662
- size += value.length;
16663
- }
16664
- }
16665
- return size;
15807
+ /// <reference types="zone.js" />
15808
+ const ZONE_CONTEXT_KEY = 'OT_ZONE_CONTEXT';
15809
+ const EVENT_NAVIGATION_NAME = 'Navigation:';
15810
+ const DEFAULT_EVENT_NAMES = ['click'];
15811
+ function defaultShouldPreventSpanCreation() {
15812
+ return false;
16666
15813
  }
16667
15814
  /**
16668
- * Normalize an HTTP request method string per `http.request.method` spec
16669
- * https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-client-span
16670
- */
16671
- function normalizeHttpRequestMethod$1(method) {
16672
- const knownMethods = getKnownMethods$1();
16673
- const methUpper = method.toUpperCase();
16674
- if (methUpper in knownMethods) {
16675
- return methUpper;
16676
- }
16677
- else {
16678
- return '_OTHER';
16679
- }
16680
- }
16681
- const DEFAULT_KNOWN_METHODS$1 = {
16682
- CONNECT: true,
16683
- DELETE: true,
16684
- GET: true,
16685
- HEAD: true,
16686
- OPTIONS: true,
16687
- PATCH: true,
16688
- POST: true,
16689
- PUT: true,
16690
- TRACE: true,
16691
- };
16692
- let knownMethods$1;
16693
- function getKnownMethods$1() {
16694
- if (knownMethods$1 === undefined) {
16695
- {
16696
- knownMethods$1 = DEFAULT_KNOWN_METHODS$1;
16697
- }
16698
- }
16699
- return knownMethods$1;
16700
- }
16701
- const HTTP_PORT_FROM_PROTOCOL$1 = {
16702
- 'https:': '443',
16703
- 'http:': '80',
16704
- };
16705
- function serverPortFromUrl$1(url) {
16706
- const serverPort = Number(url.port || HTTP_PORT_FROM_PROTOCOL$1[url.protocol]);
16707
- // Guard with `if (serverPort)` because `Number('') === 0`.
16708
- if (serverPort && !isNaN(serverPort)) {
16709
- return serverPort;
16710
- }
16711
- else {
16712
- return undefined;
16713
- }
16714
- }
16715
-
16716
- /*
16717
- * Copyright The OpenTelemetry Authors
16718
- *
16719
- * Licensed under the Apache License, Version 2.0 (the "License");
16720
- * you may not use this file except in compliance with the License.
16721
- * You may obtain a copy of the License at
16722
- *
16723
- * https://www.apache.org/licenses/LICENSE-2.0
16724
- *
16725
- * Unless required by applicable law or agreed to in writing, software
16726
- * distributed under the License is distributed on an "AS IS" BASIS,
16727
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16728
- * See the License for the specific language governing permissions and
16729
- * limitations under the License.
16730
- */
16731
- // this is autogenerated file, see scripts/version-update.js
16732
- const VERSION$1 = '0.208.0';
16733
-
16734
- /*
16735
- * Copyright The OpenTelemetry Authors
16736
- *
16737
- * Licensed under the Apache License, Version 2.0 (the "License");
16738
- * you may not use this file except in compliance with the License.
16739
- * You may obtain a copy of the License at
16740
- *
16741
- * https://www.apache.org/licenses/LICENSE-2.0
16742
- *
16743
- * Unless required by applicable law or agreed to in writing, software
16744
- * distributed under the License is distributed on an "AS IS" BASIS,
16745
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16746
- * See the License for the specific language governing permissions and
16747
- * limitations under the License.
15815
+ * This class represents a UserInteraction plugin for auto instrumentation.
15816
+ * If zone.js is available then it patches the zone otherwise it patches
15817
+ * addEventListener of HTMLElement
16748
15818
  */
16749
- // how long to wait for observer to collect information about resources
16750
- // this is needed as event "load" is called before observer
16751
- // hard to say how long it should really wait, seems like 300ms is
16752
- // safe enough
16753
- const OBSERVER_WAIT_TIME_MS$1 = 300;
16754
- const isNode = typeof process === 'object' && process.release?.name === 'node';
16755
- /**
16756
- * This class represents a fetch plugin for auto instrumentation
16757
- */
16758
- class FetchInstrumentation extends InstrumentationBase {
16759
- component = 'fetch';
16760
- version = VERSION$1;
16761
- moduleName = this.component;
16762
- _usedResources = new WeakSet();
16763
- _tasksCount = 0;
16764
- _semconvStability;
15819
+ class UserInteractionInstrumentation extends InstrumentationBase {
15820
+ version = PACKAGE_VERSION;
15821
+ moduleName = 'user-interaction';
15822
+ _spansData = new WeakMap();
15823
+ // for addEventListener/removeEventListener state
15824
+ _wrappedListeners = new WeakMap();
15825
+ // for event bubbling
15826
+ _eventsSpanMap = new WeakMap();
15827
+ _eventNames;
15828
+ _shouldPreventSpanCreation;
16765
15829
  constructor(config = {}) {
16766
- super('@opentelemetry/instrumentation-fetch', VERSION$1, config);
16767
- this._semconvStability = semconvStabilityFromStr('http', config?.semconvStabilityOptIn);
15830
+ super(PACKAGE_NAME, PACKAGE_VERSION, config);
15831
+ this._eventNames = new Set(config?.eventNames ?? DEFAULT_EVENT_NAMES);
15832
+ this._shouldPreventSpanCreation =
15833
+ typeof config?.shouldPreventSpanCreation === 'function'
15834
+ ? config.shouldPreventSpanCreation
15835
+ : defaultShouldPreventSpanCreation;
16768
15836
  }
16769
15837
  init() { }
16770
15838
  /**
16771
- * Add cors pre flight child span
16772
- * @param span
16773
- * @param corsPreFlightRequest
16774
- */
16775
- _addChildSpan(span, corsPreFlightRequest) {
16776
- const childSpan = this.tracer.startSpan('CORS Preflight', {
16777
- startTime: corsPreFlightRequest[PerformanceTimingNames.FETCH_START],
16778
- }, trace.setSpan(context.active(), span));
16779
- const skipOldSemconvContentLengthAttrs = !(this._semconvStability & SemconvStability.OLD);
16780
- addSpanNetworkEvents(childSpan, corsPreFlightRequest, this.getConfig().ignoreNetworkEvents, undefined, skipOldSemconvContentLengthAttrs);
16781
- childSpan.end(corsPreFlightRequest[PerformanceTimingNames.RESPONSE_END]);
16782
- }
16783
- /**
16784
- * Adds more attributes to span just before ending it
15839
+ * This will check if last task was timeout and will save the time to
15840
+ * fix the user interaction when nothing happens
15841
+ * This timeout comes from xhr plugin which is needed to collect information
15842
+ * about last xhr main request from observer
15843
+ * @param task
16785
15844
  * @param span
16786
- * @param response
16787
15845
  */
16788
- _addFinalSpanAttributes(span, response) {
16789
- const parsedUrl = parseUrl(response.url);
16790
- if (this._semconvStability & SemconvStability.OLD) {
16791
- span.setAttribute(ATTR_HTTP_STATUS_CODE$1, response.status);
16792
- if (response.statusText != null) {
16793
- span.setAttribute(AttributeNames$3.HTTP_STATUS_TEXT, response.statusText);
16794
- }
16795
- span.setAttribute(ATTR_HTTP_HOST$1, parsedUrl.host);
16796
- span.setAttribute(ATTR_HTTP_SCHEME$1, parsedUrl.protocol.replace(':', ''));
16797
- if (typeof navigator !== 'undefined') {
16798
- span.setAttribute(ATTR_HTTP_USER_AGENT$2, navigator.userAgent);
15846
+ _checkForTimeout(task, span) {
15847
+ const spanData = this._spansData.get(span);
15848
+ if (spanData) {
15849
+ if (task.source === 'setTimeout') {
15850
+ spanData.hrTimeLastTimeout = hrTime();
16799
15851
  }
16800
- }
16801
- if (this._semconvStability & SemconvStability.STABLE) {
16802
- span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, response.status);
16803
- // TODO: Set server.{address,port} at span creation for sampling decisions
16804
- // (a "SHOULD" requirement in semconv).
16805
- span.setAttribute(ATTR_SERVER_ADDRESS, parsedUrl.hostname);
16806
- const serverPort = serverPortFromUrl$1(parsedUrl);
16807
- if (serverPort) {
16808
- span.setAttribute(ATTR_SERVER_PORT, serverPort);
15852
+ else if (task.source !== 'Promise.then' &&
15853
+ task.source !== 'setTimeout') {
15854
+ spanData.hrTimeLastTimeout = undefined;
16809
15855
  }
16810
15856
  }
16811
15857
  }
16812
15858
  /**
16813
- * Add headers
16814
- * @param options
16815
- * @param spanUrl
15859
+ * Controls whether or not to create a span, based on the event type.
16816
15860
  */
16817
- _addHeaders(options, spanUrl) {
16818
- if (!shouldPropagateTraceHeaders(spanUrl, this.getConfig().propagateTraceHeaderCorsUrls)) {
16819
- const headers = {};
16820
- propagation.inject(context.active(), headers);
16821
- if (Object.keys(headers).length > 0) {
16822
- this._diag.debug('headers inject skipped due to CORS policy');
16823
- }
16824
- return;
15861
+ _allowEventName(eventName) {
15862
+ return this._eventNames.has(eventName);
15863
+ }
15864
+ /**
15865
+ * Creates a new span
15866
+ * @param element
15867
+ * @param eventName
15868
+ * @param parentSpan
15869
+ */
15870
+ _createSpan(element, eventName, parentSpan) {
15871
+ if (!(element instanceof HTMLElement)) {
15872
+ return undefined;
16825
15873
  }
16826
- if (options instanceof Request) {
16827
- propagation.inject(context.active(), options.headers, {
16828
- set: (h, k, v) => h.set(k, typeof v === 'string' ? v : String(v)),
16829
- });
15874
+ if (!element.getAttribute) {
15875
+ return undefined;
16830
15876
  }
16831
- else if (options.headers instanceof Headers) {
16832
- propagation.inject(context.active(), options.headers, {
16833
- set: (h, k, v) => h.set(k, typeof v === 'string' ? v : String(v)),
16834
- });
15877
+ if (element.hasAttribute('disabled')) {
15878
+ return undefined;
15879
+ }
15880
+ if (!this._allowEventName(eventName)) {
15881
+ return undefined;
16835
15882
  }
16836
- else if (options.headers instanceof Map) {
16837
- propagation.inject(context.active(), options.headers, {
16838
- set: (h, k, v) => h.set(k, typeof v === 'string' ? v : String(v)),
15883
+ const xpath = getElementXPath(element, true);
15884
+ try {
15885
+ const span = this.tracer.startSpan(eventName, {
15886
+ attributes: {
15887
+ [AttributeNames.EVENT_TYPE]: eventName,
15888
+ [AttributeNames.TARGET_ELEMENT]: element.tagName,
15889
+ [AttributeNames.TARGET_XPATH]: xpath,
15890
+ [AttributeNames.HTTP_URL]: window.location.href,
15891
+ },
15892
+ }, parentSpan
15893
+ ? trace.setSpan(context.active(), parentSpan)
15894
+ : undefined);
15895
+ if (this._shouldPreventSpanCreation(eventName, element, span) === true) {
15896
+ return undefined;
15897
+ }
15898
+ this._spansData.set(span, {
15899
+ taskCount: 0,
16839
15900
  });
15901
+ return span;
16840
15902
  }
16841
- else {
16842
- const headers = {};
16843
- propagation.inject(context.active(), headers);
16844
- options.headers = Object.assign({}, headers, options.headers || {});
15903
+ catch (e) {
15904
+ this._diag.error('failed to start create new user interaction span', e);
16845
15905
  }
15906
+ return undefined;
16846
15907
  }
16847
15908
  /**
16848
- * Clears the resource timings and all resources assigned with spans
16849
- * when {@link FetchPluginConfig.clearTimingResources} is
16850
- * set to true (default false)
16851
- * @private
15909
+ * Decrement number of tasks that left in zone,
15910
+ * This is needed to be able to end span when no more tasks left
15911
+ * @param span
16852
15912
  */
16853
- _clearResources() {
16854
- if (this._tasksCount === 0 && this.getConfig().clearTimingResources) {
16855
- performance.clearResourceTimings();
16856
- this._usedResources = new WeakSet();
16857
- }
16858
- }
16859
- /**
16860
- * Creates a new span
16861
- * @param url
16862
- * @param options
15913
+ _decrementTask(span) {
15914
+ const spanData = this._spansData.get(span);
15915
+ if (spanData) {
15916
+ spanData.taskCount--;
15917
+ if (spanData.taskCount === 0) {
15918
+ this._tryToEndSpan(span, spanData.hrTimeLastTimeout);
15919
+ }
15920
+ }
15921
+ }
15922
+ /**
15923
+ * Return the current span
15924
+ * @param zone
15925
+ * @private
16863
15926
  */
16864
- _createSpan(url, options = {}) {
16865
- if (isUrlIgnored(url, this.getConfig().ignoreUrls)) {
16866
- this._diag.debug('ignoring span as url matches ignored url');
16867
- return;
15927
+ _getCurrentSpan(zone) {
15928
+ const context = zone.get(ZONE_CONTEXT_KEY);
15929
+ if (context) {
15930
+ return trace.getSpan(context);
16868
15931
  }
16869
- let name = '';
16870
- const attributes = {};
16871
- if (this._semconvStability & SemconvStability.OLD) {
16872
- const method = (options.method || 'GET').toUpperCase();
16873
- name = `HTTP ${method}`;
16874
- attributes[AttributeNames$3.COMPONENT] = this.moduleName;
16875
- attributes[ATTR_HTTP_METHOD$1] = method;
16876
- attributes[ATTR_HTTP_URL$2] = url;
16877
- }
16878
- if (this._semconvStability & SemconvStability.STABLE) {
16879
- const origMethod = options.method;
16880
- const normMethod = normalizeHttpRequestMethod$1(options.method || 'GET');
16881
- if (!name) {
16882
- // The "old" span name wins if emitting both old and stable semconv
16883
- // ('http/dup').
16884
- name = normMethod;
16885
- }
16886
- attributes[ATTR_HTTP_REQUEST_METHOD] = normMethod;
16887
- if (normMethod !== origMethod) {
16888
- attributes[ATTR_HTTP_REQUEST_METHOD_ORIGINAL] = origMethod;
16889
- }
16890
- attributes[ATTR_URL_FULL] = url;
16891
- }
16892
- return this.tracer.startSpan(name, {
16893
- kind: SpanKind.CLIENT,
16894
- attributes,
16895
- });
15932
+ return context;
16896
15933
  }
16897
15934
  /**
16898
- * Finds appropriate resource and add network events to the span
15935
+ * Increment number of tasks that are run within the same zone.
15936
+ * This is needed to be able to end span when no more tasks left
16899
15937
  * @param span
16900
- * @param resourcesObserver
16901
- * @param endTime
16902
15938
  */
16903
- _findResourceAndAddNetworkEvents(span, resourcesObserver, endTime) {
16904
- let resources = resourcesObserver.entries;
16905
- if (!resources.length) {
16906
- if (!performance.getEntriesByType) {
16907
- return;
16908
- }
16909
- // fallback - either Observer is not available or it took longer
16910
- // then OBSERVER_WAIT_TIME_MS and observer didn't collect enough
16911
- // information
16912
- resources = performance.getEntriesByType('resource');
16913
- }
16914
- const resource = getResource(resourcesObserver.spanUrl, resourcesObserver.startTime, endTime, resources, this._usedResources, 'fetch');
16915
- if (resource.mainRequest) {
16916
- const mainRequest = resource.mainRequest;
16917
- this._markResourceAsUsed(mainRequest);
16918
- const corsPreFlightRequest = resource.corsPreFlightRequest;
16919
- if (corsPreFlightRequest) {
16920
- this._addChildSpan(span, corsPreFlightRequest);
16921
- this._markResourceAsUsed(corsPreFlightRequest);
16922
- }
16923
- const skipOldSemconvContentLengthAttrs = !(this._semconvStability & SemconvStability.OLD);
16924
- addSpanNetworkEvents(span, mainRequest, this.getConfig().ignoreNetworkEvents, undefined, skipOldSemconvContentLengthAttrs);
15939
+ _incrementTask(span) {
15940
+ const spanData = this._spansData.get(span);
15941
+ if (spanData) {
15942
+ spanData.taskCount++;
16925
15943
  }
16926
15944
  }
16927
15945
  /**
16928
- * Marks certain [resource]{@link PerformanceResourceTiming} when information
16929
- * from this is used to add events to span.
16930
- * This is done to avoid reusing the same resource again for next span
16931
- * @param resource
15946
+ * Returns true iff we should use the patched callback; false if it's already been patched
16932
15947
  */
16933
- _markResourceAsUsed(resource) {
16934
- this._usedResources.add(resource);
15948
+ addPatchedListener(on, type, listener, wrappedListener) {
15949
+ let listener2Type = this._wrappedListeners.get(listener);
15950
+ if (!listener2Type) {
15951
+ listener2Type = new Map();
15952
+ this._wrappedListeners.set(listener, listener2Type);
15953
+ }
15954
+ let element2patched = listener2Type.get(type);
15955
+ if (!element2patched) {
15956
+ element2patched = new Map();
15957
+ listener2Type.set(type, element2patched);
15958
+ }
15959
+ if (element2patched.has(on)) {
15960
+ return false;
15961
+ }
15962
+ element2patched.set(on, wrappedListener);
15963
+ return true;
16935
15964
  }
16936
15965
  /**
16937
- * Finish span, add attributes, network events etc.
16938
- * @param span
16939
- * @param spanData
16940
- * @param response
15966
+ * Returns the patched version of the callback (or undefined)
16941
15967
  */
16942
- _endSpan(span, spanData, response) {
16943
- const endTime = millisToHrTime(Date.now());
16944
- const performanceEndTime = hrTime();
16945
- this._addFinalSpanAttributes(span, response);
16946
- if (this._semconvStability & SemconvStability.STABLE) {
16947
- // https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#status
16948
- if (response.status >= 400) {
16949
- span.setStatus({ code: SpanStatusCode.ERROR });
16950
- span.setAttribute(ATTR_ERROR_TYPE, String(response.status));
15968
+ removePatchedListener(on, type, listener) {
15969
+ const listener2Type = this._wrappedListeners.get(listener);
15970
+ if (!listener2Type) {
15971
+ return undefined;
15972
+ }
15973
+ const element2patched = listener2Type.get(type);
15974
+ if (!element2patched) {
15975
+ return undefined;
15976
+ }
15977
+ const patched = element2patched.get(on);
15978
+ if (patched) {
15979
+ element2patched.delete(on);
15980
+ if (element2patched.size === 0) {
15981
+ listener2Type.delete(type);
15982
+ if (listener2Type.size === 0) {
15983
+ this._wrappedListeners.delete(listener);
15984
+ }
16951
15985
  }
16952
15986
  }
16953
- setTimeout(() => {
16954
- spanData.observer?.disconnect();
16955
- this._findResourceAndAddNetworkEvents(span, spanData, performanceEndTime);
16956
- this._tasksCount--;
16957
- this._clearResources();
16958
- span.end(endTime);
16959
- }, OBSERVER_WAIT_TIME_MS$1);
15987
+ return patched;
15988
+ }
15989
+ // utility method to deal with the Function|EventListener nature of addEventListener
15990
+ _invokeListener(listener, target, args) {
15991
+ if (typeof listener === 'function') {
15992
+ return listener.apply(target, args);
15993
+ }
15994
+ else {
15995
+ return listener.handleEvent(args[0]);
15996
+ }
16960
15997
  }
16961
15998
  /**
16962
- * Patches the constructor of fetch
15999
+ * This patches the addEventListener of HTMLElement to be able to
16000
+ * auto instrument the click events
16001
+ * This is done when zone is not available
16963
16002
  */
16964
- _patchConstructor() {
16965
- return original => {
16966
- const plugin = this;
16967
- return function patchConstructor(...args) {
16968
- const self = this;
16969
- const url = parseUrl(args[0] instanceof Request ? args[0].url : String(args[0])).href;
16970
- const options = args[0] instanceof Request ? args[0] : args[1] || {};
16971
- const createdSpan = plugin._createSpan(url, options);
16972
- if (!createdSpan) {
16973
- return original.apply(this, args);
16974
- }
16975
- const spanData = plugin._prepareSpanData(url);
16976
- if (plugin.getConfig().measureRequestSize) {
16977
- getFetchBodyLength(...args)
16978
- .then(bodyLength => {
16979
- if (!bodyLength)
16980
- return;
16981
- if (plugin._semconvStability & SemconvStability.OLD) {
16982
- createdSpan.setAttribute(ATTR_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED$1, bodyLength);
16983
- }
16984
- if (plugin._semconvStability & SemconvStability.STABLE) {
16985
- createdSpan.setAttribute(ATTR_HTTP_REQUEST_BODY_SIZE$1, bodyLength);
16986
- }
16987
- })
16988
- .catch(error => {
16989
- plugin._diag.warn('getFetchBodyLength', error);
16990
- });
16991
- }
16992
- function endSpanOnError(span, error) {
16993
- plugin._applyAttributesAfterFetch(span, options, error);
16994
- plugin._endSpan(span, spanData, {
16995
- status: error.status || 0,
16996
- statusText: error.message,
16997
- url,
16998
- });
16003
+ _patchAddEventListener() {
16004
+ const plugin = this;
16005
+ return (original) => {
16006
+ return function addEventListenerPatched(type, listener, useCapture) {
16007
+ // Forward calls with listener = null
16008
+ if (!listener) {
16009
+ return original.call(this, type, listener, useCapture);
16999
16010
  }
17000
- function endSpanOnSuccess(span, response) {
17001
- plugin._applyAttributesAfterFetch(span, options, response);
17002
- if (response.status >= 200 && response.status < 400) {
17003
- plugin._endSpan(span, spanData, response);
16011
+ // filter out null (typeof null === 'object')
16012
+ const once = useCapture && typeof useCapture === 'object' && useCapture.once;
16013
+ const patchedListener = function (...args) {
16014
+ let parentSpan;
16015
+ const event = args[0];
16016
+ const target = event?.target;
16017
+ if (event) {
16018
+ parentSpan = plugin._eventsSpanMap.get(event);
17004
16019
  }
17005
- else {
17006
- plugin._endSpan(span, spanData, {
17007
- status: response.status,
17008
- statusText: response.statusText,
17009
- url,
17010
- });
16020
+ if (once) {
16021
+ plugin.removePatchedListener(this, type, listener);
17011
16022
  }
17012
- }
17013
- function withCancelPropagation(body, readerClone) {
17014
- if (!body)
17015
- return null;
17016
- const reader = body.getReader();
17017
- return new ReadableStream({
17018
- async pull(controller) {
17019
- try {
17020
- const { value, done } = await reader.read();
17021
- if (done) {
17022
- reader.releaseLock();
17023
- controller.close();
17024
- }
17025
- else {
17026
- controller.enqueue(value);
17027
- }
17028
- }
17029
- catch (err) {
17030
- controller.error(err);
17031
- reader.cancel(err).catch(_ => { });
17032
- try {
17033
- reader.releaseLock();
17034
- }
17035
- catch {
17036
- // Spec reference:
17037
- // https://streams.spec.whatwg.org/#default-reader-release-lock
17038
- //
17039
- // releaseLock() only throws if called on an invalid reader
17040
- // (i.e. reader.[[stream]] is undefined, meaning the lock is already released
17041
- // or the reader was never associated). In normal use this cannot happen.
17042
- // This catch is defensive only.
17043
- }
17044
- }
17045
- },
17046
- cancel(reason) {
17047
- readerClone.cancel(reason).catch(_ => { });
17048
- return reader.cancel(reason);
17049
- },
17050
- });
17051
- }
17052
- function onSuccess(span, resolve, response) {
17053
- let proxiedResponse = null;
17054
- try {
17055
- // TODO: Switch to a consumer-driven model and drop `resClone`.
17056
- // Keeping eager consumption here to preserve current behavior and avoid breaking existing tests.
17057
- // Context: discussion in PR #5894 → https://github.com/open-telemetry/opentelemetry-js/pull/5894
17058
- const resClone = response.clone();
17059
- const body = resClone.body;
17060
- if (body) {
17061
- const reader = body.getReader();
17062
- const isNullBodyStatus =
17063
- // 101 responses and protocol upgrading is handled internally by the browser
17064
- response.status === 204 ||
17065
- response.status === 205 ||
17066
- response.status === 304;
17067
- const wrappedBody = isNullBodyStatus
17068
- ? null
17069
- : withCancelPropagation(response.body, reader);
17070
- proxiedResponse = new Response(wrappedBody, {
17071
- status: response.status,
17072
- statusText: response.statusText,
17073
- headers: response.headers,
17074
- });
17075
- const read = () => {
17076
- reader.read().then(({ done }) => {
17077
- if (done) {
17078
- endSpanOnSuccess(span, response);
17079
- }
17080
- else {
17081
- read();
17082
- }
17083
- }, error => {
17084
- endSpanOnError(span, error);
17085
- });
17086
- };
17087
- read();
17088
- }
17089
- else {
17090
- // some older browsers don't have .body implemented
17091
- endSpanOnSuccess(span, response);
16023
+ const span = plugin._createSpan(target, type, parentSpan);
16024
+ if (span) {
16025
+ if (event) {
16026
+ plugin._eventsSpanMap.set(event, span);
17092
16027
  }
16028
+ return context.with(trace.setSpan(context.active(), span), () => {
16029
+ const result = plugin._invokeListener(listener, this, args);
16030
+ // no zone so end span immediately
16031
+ span.end();
16032
+ return result;
16033
+ });
17093
16034
  }
17094
- finally {
17095
- resolve(proxiedResponse ?? response);
17096
- }
17097
- }
17098
- function onError(span, reject, error) {
17099
- try {
17100
- endSpanOnError(span, error);
17101
- }
17102
- finally {
17103
- reject(error);
16035
+ else {
16036
+ return plugin._invokeListener(listener, this, args);
17104
16037
  }
16038
+ };
16039
+ if (plugin.addPatchedListener(this, type, listener, patchedListener)) {
16040
+ return original.call(this, type, patchedListener, useCapture);
17105
16041
  }
17106
- return new Promise((resolve, reject) => {
17107
- return context.with(trace.setSpan(context.active(), createdSpan), () => {
17108
- plugin._addHeaders(options, url);
17109
- plugin._callRequestHook(createdSpan, options);
17110
- plugin._tasksCount++;
17111
- return original
17112
- .apply(self, options instanceof Request ? [options] : [url, options])
17113
- .then(onSuccess.bind(self, createdSpan, resolve), onError.bind(self, createdSpan, reject));
17114
- });
17115
- });
17116
16042
  };
17117
16043
  };
17118
16044
  }
17119
- _applyAttributesAfterFetch(span, request, result) {
17120
- const applyCustomAttributesOnSpan = this.getConfig().applyCustomAttributesOnSpan;
17121
- if (applyCustomAttributesOnSpan) {
17122
- safeExecuteInTheMiddle(() => applyCustomAttributesOnSpan(span, request, result), error => {
17123
- if (!error) {
17124
- return;
16045
+ /**
16046
+ * This patches the removeEventListener of HTMLElement to handle the fact that
16047
+ * we patched the original callbacks
16048
+ * This is done when zone is not available
16049
+ */
16050
+ _patchRemoveEventListener() {
16051
+ const plugin = this;
16052
+ return (original) => {
16053
+ return function removeEventListenerPatched(type, listener, useCapture) {
16054
+ const wrappedListener = plugin.removePatchedListener(this, type, listener);
16055
+ if (wrappedListener) {
16056
+ return original.call(this, type, wrappedListener, useCapture);
17125
16057
  }
17126
- this._diag.error('applyCustomAttributesOnSpan', error);
17127
- });
17128
- }
17129
- }
17130
- _callRequestHook(span, request) {
17131
- const requestHook = this.getConfig().requestHook;
17132
- if (requestHook) {
17133
- safeExecuteInTheMiddle(() => requestHook(span, request), error => {
17134
- if (!error) {
17135
- return;
16058
+ else {
16059
+ return original.call(this, type, listener, useCapture);
17136
16060
  }
17137
- this._diag.error('requestHook', error);
17138
- });
17139
- }
16061
+ };
16062
+ };
16063
+ }
16064
+ /**
16065
+ * Most browser provide event listener api via EventTarget in prototype chain.
16066
+ * Exception to this is IE 11 which has it on the prototypes closest to EventTarget:
16067
+ *
16068
+ * * - has addEventListener in IE
16069
+ * ** - has addEventListener in all other browsers
16070
+ * ! - missing in IE
16071
+ *
16072
+ * HTMLElement -> Element -> Node * -> EventTarget **! -> Object
16073
+ * Document -> Node * -> EventTarget **! -> Object
16074
+ * Window * -> WindowProperties ! -> EventTarget **! -> Object
16075
+ */
16076
+ _getPatchableEventTargets() {
16077
+ return window.EventTarget
16078
+ ? [EventTarget.prototype]
16079
+ : [Node.prototype, Window.prototype];
16080
+ }
16081
+ /**
16082
+ * Patches the history api
16083
+ */
16084
+ _patchHistoryApi() {
16085
+ this._unpatchHistoryApi();
16086
+ this._wrap(history, 'replaceState', this._patchHistoryMethod());
16087
+ this._wrap(history, 'pushState', this._patchHistoryMethod());
16088
+ this._wrap(history, 'back', this._patchHistoryMethod());
16089
+ this._wrap(history, 'forward', this._patchHistoryMethod());
16090
+ this._wrap(history, 'go', this._patchHistoryMethod());
17140
16091
  }
17141
16092
  /**
17142
- * Prepares a span data - needed later for matching appropriate network
17143
- * resources
17144
- * @param spanUrl
16093
+ * Patches the certain history api method
17145
16094
  */
17146
- _prepareSpanData(spanUrl) {
17147
- const startTime = hrTime();
17148
- const entries = [];
17149
- if (typeof PerformanceObserver !== 'function') {
17150
- return { entries, startTime, spanUrl };
17151
- }
17152
- const observer = new PerformanceObserver(list => {
17153
- const perfObsEntries = list.getEntries();
17154
- perfObsEntries.forEach(entry => {
17155
- if (entry.initiatorType === 'fetch' && entry.name === spanUrl) {
17156
- entries.push(entry);
16095
+ _patchHistoryMethod() {
16096
+ const plugin = this;
16097
+ return (original) => {
16098
+ return function patchHistoryMethod(...args) {
16099
+ const url = `${location.pathname}${location.hash}${location.search}`;
16100
+ const result = original.apply(this, args);
16101
+ const urlAfter = `${location.pathname}${location.hash}${location.search}`;
16102
+ if (url !== urlAfter) {
16103
+ plugin._updateInteractionName(urlAfter);
17157
16104
  }
17158
- });
17159
- });
17160
- observer.observe({
17161
- entryTypes: ['resource'],
17162
- });
17163
- return { entries, observer, startTime, spanUrl };
16105
+ return result;
16106
+ };
16107
+ };
17164
16108
  }
17165
16109
  /**
17166
- * implements enable function
16110
+ * unpatch the history api methods
17167
16111
  */
17168
- enable() {
17169
- if (isNode) {
17170
- // Node.js v18+ *does* have a global `fetch()`, but this package does not
17171
- // support instrumenting it.
17172
- this._diag.warn("this instrumentation is intended for web usage only, it does not instrument Node.js's fetch()");
17173
- return;
17174
- }
17175
- if (isWrapped(fetch)) {
17176
- this._unwrap(_globalThis$1, 'fetch');
17177
- this._diag.debug('removing previous patch for constructor');
17178
- }
17179
- this._wrap(_globalThis$1, 'fetch', this._patchConstructor());
16112
+ _unpatchHistoryApi() {
16113
+ if (isWrapped(history.replaceState))
16114
+ this._unwrap(history, 'replaceState');
16115
+ if (isWrapped(history.pushState))
16116
+ this._unwrap(history, 'pushState');
16117
+ if (isWrapped(history.back))
16118
+ this._unwrap(history, 'back');
16119
+ if (isWrapped(history.forward))
16120
+ this._unwrap(history, 'forward');
16121
+ if (isWrapped(history.go))
16122
+ this._unwrap(history, 'go');
17180
16123
  }
17181
16124
  /**
17182
- * implements unpatch function
16125
+ * Updates interaction span name
16126
+ * @param url
17183
16127
  */
17184
- disable() {
17185
- if (isNode) {
17186
- return;
17187
- }
17188
- this._unwrap(_globalThis$1, 'fetch');
17189
- this._usedResources = new WeakSet();
17190
- }
17191
- }
17192
-
17193
- /*
17194
- * Copyright The OpenTelemetry Authors
17195
- *
17196
- * Licensed under the Apache License, Version 2.0 (the "License");
17197
- * you may not use this file except in compliance with the License.
17198
- * You may obtain a copy of the License at
17199
- *
17200
- * https://www.apache.org/licenses/LICENSE-2.0
17201
- *
17202
- * Unless required by applicable law or agreed to in writing, software
17203
- * distributed under the License is distributed on an "AS IS" BASIS,
17204
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17205
- * See the License for the specific language governing permissions and
17206
- * limitations under the License.
17207
- */
17208
- /*
17209
- * This file contains a copy of unstable semantic convention definitions
17210
- * used by this package.
17211
- * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv
17212
- */
17213
- /**
17214
- * Deprecated, use one of `server.address`, `client.address` or `http.request.header.host` instead, depending on the usage.
17215
- *
17216
- * @example www.example.org
17217
- *
17218
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
17219
- *
17220
- * @deprecated Replaced by one of `server.address`, `client.address` or `http.request.header.host`, depending on the usage.
17221
- */
17222
- const ATTR_HTTP_HOST = 'http.host';
17223
- /**
17224
- * Deprecated, use `http.request.method` instead.
17225
- *
17226
- * @example GET
17227
- * @example POST
17228
- * @example HEAD
17229
- *
17230
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
17231
- *
17232
- * @deprecated Replaced by `http.request.method`.
17233
- */
17234
- const ATTR_HTTP_METHOD = 'http.method';
17235
- /**
17236
- * The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.
17237
- *
17238
- * @example 3495
17239
- *
17240
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
17241
- */
17242
- const ATTR_HTTP_REQUEST_BODY_SIZE = 'http.request.body.size';
17243
- /**
17244
- * Deprecated, use `http.request.body.size` instead.
17245
- *
17246
- * @example 5493
17247
- *
17248
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
17249
- *
17250
- * @deprecated Replaced by `http.request.body.size`.
17251
- */
17252
- const ATTR_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED = 'http.request_content_length_uncompressed';
17253
- /**
17254
- * Deprecated, use `url.scheme` instead.
17255
- *
17256
- * @example http
17257
- * @example https
17258
- *
17259
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
17260
- *
17261
- * @deprecated Replaced by `url.scheme` instead.
17262
- */
17263
- const ATTR_HTTP_SCHEME = 'http.scheme';
17264
- /**
17265
- * Deprecated, use `http.response.status_code` instead.
17266
- *
17267
- * @example 200
17268
- *
17269
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
17270
- *
17271
- * @deprecated Replaced by `http.response.status_code`.
17272
- */
17273
- const ATTR_HTTP_STATUS_CODE = 'http.status_code';
17274
- /**
17275
- * Deprecated, use `url.full` instead.
17276
- *
17277
- * @example https://www.foo.bar/search?q=OpenTelemetry#SemConv
17278
- *
17279
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
17280
- *
17281
- * @deprecated Replaced by `url.full`.
17282
- */
17283
- const ATTR_HTTP_URL$1 = 'http.url';
17284
- /**
17285
- * Deprecated, use `user_agent.original` instead.
17286
- *
17287
- * @example CERN-LineMode/2.15 libwww/2.17b3
17288
- * @example Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1
17289
- *
17290
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
17291
- *
17292
- * @deprecated Replaced by `user_agent.original`.
17293
- */
17294
- const ATTR_HTTP_USER_AGENT$1 = 'http.user_agent';
17295
-
17296
- /*
17297
- * Copyright The OpenTelemetry Authors
17298
- *
17299
- * Licensed under the Apache License, Version 2.0 (the "License");
17300
- * you may not use this file except in compliance with the License.
17301
- * You may obtain a copy of the License at
17302
- *
17303
- * https://www.apache.org/licenses/LICENSE-2.0
17304
- *
17305
- * Unless required by applicable law or agreed to in writing, software
17306
- * distributed under the License is distributed on an "AS IS" BASIS,
17307
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17308
- * See the License for the specific language governing permissions and
17309
- * limitations under the License.
17310
- */
17311
- var EventNames$1;
17312
- (function (EventNames) {
17313
- EventNames["METHOD_OPEN"] = "open";
17314
- EventNames["METHOD_SEND"] = "send";
17315
- EventNames["EVENT_ABORT"] = "abort";
17316
- EventNames["EVENT_ERROR"] = "error";
17317
- EventNames["EVENT_LOAD"] = "loaded";
17318
- EventNames["EVENT_TIMEOUT"] = "timeout";
17319
- })(EventNames$1 || (EventNames$1 = {}));
17320
-
17321
- /*
17322
- * Copyright The OpenTelemetry Authors
17323
- *
17324
- * Licensed under the Apache License, Version 2.0 (the "License");
17325
- * you may not use this file except in compliance with the License.
17326
- * You may obtain a copy of the License at
17327
- *
17328
- * https://www.apache.org/licenses/LICENSE-2.0
17329
- *
17330
- * Unless required by applicable law or agreed to in writing, software
17331
- * distributed under the License is distributed on an "AS IS" BASIS,
17332
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17333
- * See the License for the specific language governing permissions and
17334
- * limitations under the License.
17335
- */
17336
- // Much of the logic here overlaps with the same utils file in opentelemetry-instrumentation-fetch
17337
- // These may be unified in the future.
17338
- const DIAG_LOGGER = diag.createComponentLogger({
17339
- namespace: '@opentelemetry/opentelemetry-instrumentation-xml-http-request/utils',
17340
- });
17341
- function isDocument(value) {
17342
- return typeof Document !== 'undefined' && value instanceof Document;
17343
- }
17344
- /**
17345
- * Helper function to determine payload content length for XHR requests
17346
- * @param body
17347
- * @returns content length
17348
- */
17349
- function getXHRBodyLength(body) {
17350
- if (isDocument(body)) {
17351
- return new XMLSerializer().serializeToString(document).length;
17352
- }
17353
- // XMLHttpRequestBodyInit expands to the following:
17354
- if (typeof body === 'string') {
17355
- return getByteLength(body);
17356
- }
17357
- if (body instanceof Blob) {
17358
- return body.size;
17359
- }
17360
- if (body instanceof FormData) {
17361
- return getFormDataSize(body);
17362
- }
17363
- if (body instanceof URLSearchParams) {
17364
- return getByteLength(body.toString());
17365
- }
17366
- // ArrayBuffer | ArrayBufferView
17367
- if (body.byteLength !== undefined) {
17368
- return body.byteLength;
17369
- }
17370
- DIAG_LOGGER.warn('unknown body type');
17371
- return undefined;
17372
- }
17373
- const TEXT_ENCODER = new TextEncoder();
17374
- function getByteLength(s) {
17375
- return TEXT_ENCODER.encode(s).byteLength;
17376
- }
17377
- function getFormDataSize(formData) {
17378
- let size = 0;
17379
- for (const [key, value] of formData.entries()) {
17380
- size += key.length;
17381
- if (value instanceof Blob) {
17382
- size += value.size;
17383
- }
17384
- else {
17385
- size += value.length;
17386
- }
17387
- }
17388
- return size;
17389
- }
17390
- /**
17391
- * Normalize an HTTP request method string per `http.request.method` spec
17392
- * https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#http-client-span
17393
- */
17394
- function normalizeHttpRequestMethod(method) {
17395
- const knownMethods = getKnownMethods();
17396
- const methUpper = method.toUpperCase();
17397
- if (methUpper in knownMethods) {
17398
- return methUpper;
17399
- }
17400
- else {
17401
- return '_OTHER';
17402
- }
17403
- }
17404
- const DEFAULT_KNOWN_METHODS = {
17405
- CONNECT: true,
17406
- DELETE: true,
17407
- GET: true,
17408
- HEAD: true,
17409
- OPTIONS: true,
17410
- PATCH: true,
17411
- POST: true,
17412
- PUT: true,
17413
- TRACE: true,
17414
- };
17415
- let knownMethods;
17416
- function getKnownMethods() {
17417
- if (knownMethods === undefined) {
17418
- {
17419
- knownMethods = DEFAULT_KNOWN_METHODS;
17420
- }
17421
- }
17422
- return knownMethods;
17423
- }
17424
- const HTTP_PORT_FROM_PROTOCOL = {
17425
- 'https:': '443',
17426
- 'http:': '80',
17427
- };
17428
- function serverPortFromUrl(url) {
17429
- const serverPort = Number(url.port || HTTP_PORT_FROM_PROTOCOL[url.protocol]);
17430
- // Guard with `if (serverPort)` because `Number('') === 0`.
17431
- if (serverPort && !isNaN(serverPort)) {
17432
- return serverPort;
17433
- }
17434
- else {
17435
- return undefined;
17436
- }
17437
- }
17438
-
17439
- /*
17440
- * Copyright The OpenTelemetry Authors
17441
- *
17442
- * Licensed under the Apache License, Version 2.0 (the "License");
17443
- * you may not use this file except in compliance with the License.
17444
- * You may obtain a copy of the License at
17445
- *
17446
- * https://www.apache.org/licenses/LICENSE-2.0
17447
- *
17448
- * Unless required by applicable law or agreed to in writing, software
17449
- * distributed under the License is distributed on an "AS IS" BASIS,
17450
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17451
- * See the License for the specific language governing permissions and
17452
- * limitations under the License.
17453
- */
17454
- // this is autogenerated file, see scripts/version-update.js
17455
- const VERSION = '0.208.0';
17456
-
17457
- /*
17458
- * Copyright The OpenTelemetry Authors
17459
- *
17460
- * Licensed under the Apache License, Version 2.0 (the "License");
17461
- * you may not use this file except in compliance with the License.
17462
- * You may obtain a copy of the License at
17463
- *
17464
- * https://www.apache.org/licenses/LICENSE-2.0
17465
- *
17466
- * Unless required by applicable law or agreed to in writing, software
17467
- * distributed under the License is distributed on an "AS IS" BASIS,
17468
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17469
- * See the License for the specific language governing permissions and
17470
- * limitations under the License.
17471
- */
17472
- /**
17473
- * https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md
17474
- */
17475
- var AttributeNames$2;
17476
- (function (AttributeNames) {
17477
- AttributeNames["HTTP_STATUS_TEXT"] = "http.status_text";
17478
- })(AttributeNames$2 || (AttributeNames$2 = {}));
17479
-
17480
- /*
17481
- * Copyright The OpenTelemetry Authors
17482
- *
17483
- * Licensed under the Apache License, Version 2.0 (the "License");
17484
- * you may not use this file except in compliance with the License.
17485
- * You may obtain a copy of the License at
17486
- *
17487
- * https://www.apache.org/licenses/LICENSE-2.0
17488
- *
17489
- * Unless required by applicable law or agreed to in writing, software
17490
- * distributed under the License is distributed on an "AS IS" BASIS,
17491
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17492
- * See the License for the specific language governing permissions and
17493
- * limitations under the License.
17494
- */
17495
- // how long to wait for observer to collect information about resources
17496
- // this is needed as event "load" is called before observer
17497
- // hard to say how long it should really wait, seems like 300ms is
17498
- // safe enough
17499
- const OBSERVER_WAIT_TIME_MS = 300;
17500
- /**
17501
- * This class represents a XMLHttpRequest plugin for auto instrumentation
17502
- */
17503
- class XMLHttpRequestInstrumentation extends InstrumentationBase {
17504
- component = 'xml-http-request';
17505
- version = VERSION;
17506
- moduleName = this.component;
17507
- _tasksCount = 0;
17508
- _xhrMem = new WeakMap();
17509
- _usedResources = new WeakSet();
17510
- _semconvStability;
17511
- constructor(config = {}) {
17512
- super('@opentelemetry/instrumentation-xml-http-request', VERSION, config);
17513
- this._semconvStability = semconvStabilityFromStr('http', config?.semconvStabilityOptIn);
17514
- }
17515
- init() { }
17516
- /**
17517
- * Adds custom headers to XMLHttpRequest
17518
- * @param xhr
17519
- * @param spanUrl
17520
- * @private
17521
- */
17522
- _addHeaders(xhr, spanUrl) {
17523
- const url = parseUrl(spanUrl).href;
17524
- if (!shouldPropagateTraceHeaders(url, this.getConfig().propagateTraceHeaderCorsUrls)) {
17525
- const headers = {};
17526
- propagation.inject(context.active(), headers);
17527
- if (Object.keys(headers).length > 0) {
17528
- this._diag.debug('headers inject skipped due to CORS policy');
17529
- }
17530
- return;
17531
- }
17532
- const headers = {};
17533
- propagation.inject(context.active(), headers);
17534
- Object.keys(headers).forEach(key => {
17535
- xhr.setRequestHeader(key, String(headers[key]));
17536
- });
17537
- }
17538
- /**
17539
- * Add cors pre flight child span
17540
- * @param span
17541
- * @param corsPreFlightRequest
17542
- * @private
17543
- */
17544
- _addChildSpan(span, corsPreFlightRequest) {
17545
- context.with(trace.setSpan(context.active(), span), () => {
17546
- const childSpan = this.tracer.startSpan('CORS Preflight', {
17547
- startTime: corsPreFlightRequest[PerformanceTimingNames.FETCH_START],
17548
- });
17549
- const skipOldSemconvContentLengthAttrs = !(this._semconvStability & SemconvStability.OLD);
17550
- addSpanNetworkEvents(childSpan, corsPreFlightRequest, this.getConfig().ignoreNetworkEvents, undefined, skipOldSemconvContentLengthAttrs);
17551
- childSpan.end(corsPreFlightRequest[PerformanceTimingNames.RESPONSE_END]);
17552
- });
17553
- }
17554
- /**
17555
- * Add attributes when span is going to end
17556
- * @param span
17557
- * @param xhr
17558
- * @param spanUrl
17559
- * @private
17560
- */
17561
- _addFinalSpanAttributes(span, xhrMem, spanUrl) {
17562
- if (this._semconvStability & SemconvStability.OLD) {
17563
- if (xhrMem.status !== undefined) {
17564
- span.setAttribute(ATTR_HTTP_STATUS_CODE, xhrMem.status);
17565
- }
17566
- if (xhrMem.statusText !== undefined) {
17567
- span.setAttribute(AttributeNames$2.HTTP_STATUS_TEXT, xhrMem.statusText);
17568
- }
17569
- if (typeof spanUrl === 'string') {
17570
- const parsedUrl = parseUrl(spanUrl);
17571
- span.setAttribute(ATTR_HTTP_HOST, parsedUrl.host);
17572
- span.setAttribute(ATTR_HTTP_SCHEME, parsedUrl.protocol.replace(':', ''));
17573
- }
17574
- // @TODO do we want to collect this or it will be collected earlier once only or
17575
- // maybe when parent span is not available ?
17576
- span.setAttribute(ATTR_HTTP_USER_AGENT$1, navigator.userAgent);
17577
- }
17578
- if (this._semconvStability & SemconvStability.STABLE) {
17579
- if (xhrMem.status) {
17580
- // Intentionally exclude status=0, because XHR uses 0 for before a
17581
- // response is received and semconv says to only add the attribute if
17582
- // received a response.
17583
- span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, xhrMem.status);
17584
- }
17585
- }
17586
- }
17587
- _applyAttributesAfterXHR(span, xhr) {
17588
- const applyCustomAttributesOnSpan = this.getConfig().applyCustomAttributesOnSpan;
17589
- if (typeof applyCustomAttributesOnSpan === 'function') {
17590
- safeExecuteInTheMiddle(() => applyCustomAttributesOnSpan(span, xhr), error => {
17591
- if (!error) {
17592
- return;
17593
- }
17594
- this._diag.error('applyCustomAttributesOnSpan', error);
17595
- });
17596
- }
17597
- }
17598
- /**
17599
- * will collect information about all resources created
17600
- * between "send" and "end" with additional waiting for main resource
17601
- * @param xhr
17602
- * @param spanUrl
17603
- * @private
17604
- */
17605
- _addResourceObserver(xhr, spanUrl) {
17606
- const xhrMem = this._xhrMem.get(xhr);
17607
- if (!xhrMem ||
17608
- typeof PerformanceObserver !== 'function' ||
17609
- typeof PerformanceResourceTiming !== 'function') {
17610
- return;
17611
- }
17612
- xhrMem.createdResources = {
17613
- observer: new PerformanceObserver(list => {
17614
- const entries = list.getEntries();
17615
- const parsedUrl = parseUrl(spanUrl);
17616
- entries.forEach(entry => {
17617
- if (entry.initiatorType === 'xmlhttprequest' &&
17618
- entry.name === parsedUrl.href) {
17619
- if (xhrMem.createdResources) {
17620
- xhrMem.createdResources.entries.push(entry);
17621
- }
17622
- }
17623
- });
17624
- }),
17625
- entries: [],
17626
- };
17627
- xhrMem.createdResources.observer.observe({
17628
- entryTypes: ['resource'],
17629
- });
17630
- }
17631
- /**
17632
- * Clears the resource timings and all resources assigned with spans
17633
- * when {@link XMLHttpRequestInstrumentationConfig.clearTimingResources} is
17634
- * set to true (default false)
17635
- * @private
17636
- */
17637
- _clearResources() {
17638
- if (this._tasksCount === 0 && this.getConfig().clearTimingResources) {
17639
- otperformance.clearResourceTimings();
17640
- this._xhrMem = new WeakMap();
17641
- this._usedResources = new WeakSet();
17642
- }
17643
- }
17644
- /**
17645
- * Finds appropriate resource and add network events to the span
17646
- * @param span
17647
- */
17648
- _findResourceAndAddNetworkEvents(xhrMem, span, spanUrl, startTime, endTime) {
17649
- if (!spanUrl || !startTime || !endTime || !xhrMem.createdResources) {
17650
- return;
17651
- }
17652
- let resources = xhrMem.createdResources.entries;
17653
- if (!resources || !resources.length) {
17654
- // fallback - either Observer is not available or it took longer
17655
- // then OBSERVER_WAIT_TIME_MS and observer didn't collect enough
17656
- // information
17657
- // ts thinks this is the perf_hooks module, but it is the browser performance api
17658
- resources = otperformance.getEntriesByType('resource');
17659
- }
17660
- const resource = getResource(parseUrl(spanUrl).href, startTime, endTime, resources, this._usedResources);
17661
- if (resource.mainRequest) {
17662
- const mainRequest = resource.mainRequest;
17663
- this._markResourceAsUsed(mainRequest);
17664
- const corsPreFlightRequest = resource.corsPreFlightRequest;
17665
- if (corsPreFlightRequest) {
17666
- this._addChildSpan(span, corsPreFlightRequest);
17667
- this._markResourceAsUsed(corsPreFlightRequest);
17668
- }
17669
- const skipOldSemconvContentLengthAttrs = !(this._semconvStability & SemconvStability.OLD);
17670
- addSpanNetworkEvents(span, mainRequest, this.getConfig().ignoreNetworkEvents, undefined, skipOldSemconvContentLengthAttrs);
16128
+ _updateInteractionName(url) {
16129
+ const span = trace.getSpan(context.active());
16130
+ if (span && typeof span.updateName === 'function') {
16131
+ span.updateName(`${EVENT_NAVIGATION_NAME} ${url}`);
17671
16132
  }
17672
16133
  }
17673
16134
  /**
17674
- * Removes the previous information about span.
17675
- * This might happened when the same xhr is used again.
17676
- * @param xhr
17677
- * @private
17678
- */
17679
- _cleanPreviousSpanInformation(xhr) {
17680
- const xhrMem = this._xhrMem.get(xhr);
17681
- if (xhrMem) {
17682
- const callbackToRemoveEvents = xhrMem.callbackToRemoveEvents;
17683
- if (callbackToRemoveEvents) {
17684
- callbackToRemoveEvents();
17685
- }
17686
- this._xhrMem.delete(xhr);
17687
- }
17688
- }
17689
- /**
17690
- * Creates a new span when method "open" is called
17691
- * @param xhr
17692
- * @param url
17693
- * @param method
17694
- * @private
17695
- */
17696
- _createSpan(xhr, url, method) {
17697
- if (isUrlIgnored(url, this.getConfig().ignoreUrls)) {
17698
- this._diag.debug('ignoring span as url matches ignored url');
17699
- return;
17700
- }
17701
- let name = '';
17702
- const parsedUrl = parseUrl(url);
17703
- const attributes = {};
17704
- if (this._semconvStability & SemconvStability.OLD) {
17705
- name = method.toUpperCase();
17706
- attributes[ATTR_HTTP_METHOD] = method;
17707
- attributes[ATTR_HTTP_URL$1] = parsedUrl.toString();
17708
- }
17709
- if (this._semconvStability & SemconvStability.STABLE) {
17710
- const origMethod = method;
17711
- const normMethod = normalizeHttpRequestMethod(method);
17712
- if (!name) {
17713
- // The "old" span name wins if emitting both old and stable semconv
17714
- // ('http/dup').
17715
- name = normMethod;
17716
- }
17717
- attributes[ATTR_HTTP_REQUEST_METHOD] = normMethod;
17718
- if (normMethod !== origMethod) {
17719
- attributes[ATTR_HTTP_REQUEST_METHOD_ORIGINAL] = origMethod;
17720
- }
17721
- attributes[ATTR_URL_FULL] = parsedUrl.toString();
17722
- attributes[ATTR_SERVER_ADDRESS] = parsedUrl.hostname;
17723
- const serverPort = serverPortFromUrl(parsedUrl);
17724
- if (serverPort) {
17725
- attributes[ATTR_SERVER_PORT] = serverPort;
17726
- }
17727
- }
17728
- const currentSpan = this.tracer.startSpan(name, {
17729
- kind: SpanKind.CLIENT,
17730
- attributes,
17731
- });
17732
- currentSpan.addEvent(EventNames$1.METHOD_OPEN);
17733
- this._cleanPreviousSpanInformation(xhr);
17734
- this._xhrMem.set(xhr, {
17735
- span: currentSpan,
17736
- spanUrl: url,
17737
- });
17738
- return currentSpan;
17739
- }
17740
- /**
17741
- * Marks certain [resource]{@link PerformanceResourceTiming} when information
17742
- * from this is used to add events to span.
17743
- * This is done to avoid reusing the same resource again for next span
17744
- * @param resource
17745
- * @private
17746
- */
17747
- _markResourceAsUsed(resource) {
17748
- this._usedResources.add(resource);
17749
- }
17750
- /**
17751
- * Patches the method open
17752
- * @private
17753
- */
17754
- _patchOpen() {
17755
- return (original) => {
17756
- const plugin = this;
17757
- return function patchOpen(...args) {
17758
- const method = args[0];
17759
- const url = args[1];
17760
- plugin._createSpan(this, url, method);
17761
- return original.apply(this, args);
17762
- };
17763
- };
17764
- }
17765
- /**
17766
- * Patches the method send
17767
- * @private
16135
+ * Patches zone cancel task - this is done to be able to correctly
16136
+ * decrement the number of remaining tasks
17768
16137
  */
17769
- _patchSend() {
16138
+ _patchZoneCancelTask() {
17770
16139
  const plugin = this;
17771
- function endSpanTimeout(eventName, xhrMem, performanceEndTime, endTime) {
17772
- const callbackToRemoveEvents = xhrMem.callbackToRemoveEvents;
17773
- if (typeof callbackToRemoveEvents === 'function') {
17774
- callbackToRemoveEvents();
17775
- }
17776
- const { span, spanUrl, sendStartTime } = xhrMem;
17777
- if (span) {
17778
- plugin._findResourceAndAddNetworkEvents(xhrMem, span, spanUrl, sendStartTime, performanceEndTime);
17779
- span.addEvent(eventName, endTime);
17780
- plugin._addFinalSpanAttributes(span, xhrMem, spanUrl);
17781
- span.end(endTime);
17782
- plugin._tasksCount--;
17783
- }
17784
- plugin._clearResources();
17785
- }
17786
- function endSpan(eventName, xhr, isError, errorType) {
17787
- const xhrMem = plugin._xhrMem.get(xhr);
17788
- if (!xhrMem) {
17789
- return;
17790
- }
17791
- xhrMem.status = xhr.status;
17792
- xhrMem.statusText = xhr.statusText;
17793
- plugin._xhrMem.delete(xhr);
17794
- if (xhrMem.span) {
17795
- const span = xhrMem.span;
17796
- plugin._applyAttributesAfterXHR(span, xhr);
17797
- if (plugin._semconvStability & SemconvStability.STABLE) {
17798
- if (isError) {
17799
- if (errorType) {
17800
- span.setStatus({
17801
- code: SpanStatusCode.ERROR,
17802
- message: errorType,
17803
- });
17804
- span.setAttribute(ATTR_ERROR_TYPE, errorType);
17805
- }
17806
- }
17807
- else if (xhrMem.status && xhrMem.status >= 400) {
17808
- span.setStatus({ code: SpanStatusCode.ERROR });
17809
- span.setAttribute(ATTR_ERROR_TYPE, String(xhrMem.status));
17810
- }
17811
- }
17812
- }
17813
- const performanceEndTime = hrTime();
17814
- const endTime = Date.now();
17815
- // the timeout is needed as observer doesn't have yet information
17816
- // when event "load" is called. Also the time may differ depends on
17817
- // browser and speed of computer
17818
- setTimeout(() => {
17819
- endSpanTimeout(eventName, xhrMem, performanceEndTime, endTime);
17820
- }, OBSERVER_WAIT_TIME_MS);
17821
- }
17822
- function onError() {
17823
- endSpan(EventNames$1.EVENT_ERROR, this, true, 'error');
17824
- }
17825
- function onAbort() {
17826
- endSpan(EventNames$1.EVENT_ABORT, this, false);
17827
- }
17828
- function onTimeout() {
17829
- endSpan(EventNames$1.EVENT_TIMEOUT, this, true, 'timeout');
17830
- }
17831
- function onLoad() {
17832
- if (this.status < 299) {
17833
- endSpan(EventNames$1.EVENT_LOAD, this, false);
17834
- }
17835
- else {
17836
- endSpan(EventNames$1.EVENT_ERROR, this, false);
17837
- }
17838
- }
17839
- function unregister(xhr) {
17840
- xhr.removeEventListener('abort', onAbort);
17841
- xhr.removeEventListener('error', onError);
17842
- xhr.removeEventListener('load', onLoad);
17843
- xhr.removeEventListener('timeout', onTimeout);
17844
- const xhrMem = plugin._xhrMem.get(xhr);
17845
- if (xhrMem) {
17846
- xhrMem.callbackToRemoveEvents = undefined;
17847
- }
17848
- }
17849
16140
  return (original) => {
17850
- return function patchSend(...args) {
17851
- const xhrMem = plugin._xhrMem.get(this);
17852
- if (!xhrMem) {
17853
- return original.apply(this, args);
17854
- }
17855
- const currentSpan = xhrMem.span;
17856
- const spanUrl = xhrMem.spanUrl;
17857
- if (currentSpan && spanUrl) {
17858
- if (plugin.getConfig().measureRequestSize && args?.[0]) {
17859
- const body = args[0];
17860
- const bodyLength = getXHRBodyLength(body);
17861
- if (bodyLength !== undefined) {
17862
- if (plugin._semconvStability & SemconvStability.OLD) {
17863
- currentSpan.setAttribute(ATTR_HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED, bodyLength);
17864
- }
17865
- if (plugin._semconvStability & SemconvStability.STABLE) {
17866
- currentSpan.setAttribute(ATTR_HTTP_REQUEST_BODY_SIZE, bodyLength);
17867
- }
17868
- }
17869
- }
17870
- context.with(trace.setSpan(context.active(), currentSpan), () => {
17871
- plugin._tasksCount++;
17872
- xhrMem.sendStartTime = hrTime();
17873
- currentSpan.addEvent(EventNames$1.METHOD_SEND);
17874
- this.addEventListener('abort', onAbort);
17875
- this.addEventListener('error', onError);
17876
- this.addEventListener('load', onLoad);
17877
- this.addEventListener('timeout', onTimeout);
17878
- xhrMem.callbackToRemoveEvents = () => {
17879
- unregister(this);
17880
- if (xhrMem.createdResources) {
17881
- xhrMem.createdResources.observer.disconnect();
17882
- }
17883
- };
17884
- plugin._addHeaders(this, spanUrl);
17885
- plugin._addResourceObserver(this, spanUrl);
17886
- });
17887
- }
17888
- return original.apply(this, args);
17889
- };
17890
- };
17891
- }
17892
- /**
17893
- * implements enable function
17894
- */
17895
- enable() {
17896
- this._diag.debug('applying patch to', this.moduleName, this.version);
17897
- if (isWrapped(XMLHttpRequest.prototype.open)) {
17898
- this._unwrap(XMLHttpRequest.prototype, 'open');
17899
- this._diag.debug('removing previous patch from method open');
17900
- }
17901
- if (isWrapped(XMLHttpRequest.prototype.send)) {
17902
- this._unwrap(XMLHttpRequest.prototype, 'send');
17903
- this._diag.debug('removing previous patch from method send');
17904
- }
17905
- this._wrap(XMLHttpRequest.prototype, 'open', this._patchOpen());
17906
- this._wrap(XMLHttpRequest.prototype, 'send', this._patchSend());
17907
- }
17908
- /**
17909
- * implements disable function
17910
- */
17911
- disable() {
17912
- this._diag.debug('removing patch from', this.moduleName, this.version);
17913
- this._unwrap(XMLHttpRequest.prototype, 'open');
17914
- this._unwrap(XMLHttpRequest.prototype, 'send');
17915
- this._tasksCount = 0;
17916
- this._xhrMem = new WeakMap();
17917
- this._usedResources = new WeakSet();
17918
- }
17919
- }
17920
-
17921
- /*
17922
- * Copyright The OpenTelemetry Authors
17923
- *
17924
- * Licensed under the Apache License, Version 2.0 (the "License");
17925
- * you may not use this file except in compliance with the License.
17926
- * You may obtain a copy of the License at
17927
- *
17928
- * https://www.apache.org/licenses/LICENSE-2.0
17929
- *
17930
- * Unless required by applicable law or agreed to in writing, software
17931
- * distributed under the License is distributed on an "AS IS" BASIS,
17932
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17933
- * See the License for the specific language governing permissions and
17934
- * limitations under the License.
17935
- */
17936
- var AttributeNames$1;
17937
- (function (AttributeNames) {
17938
- AttributeNames["EVENT_TYPE"] = "event_type";
17939
- AttributeNames["TARGET_ELEMENT"] = "target_element";
17940
- AttributeNames["TARGET_XPATH"] = "target_xpath";
17941
- AttributeNames["HTTP_URL"] = "http.url";
17942
- })(AttributeNames$1 || (AttributeNames$1 = {}));
17943
-
17944
- /*
17945
- * Copyright The OpenTelemetry Authors
17946
- *
17947
- * Licensed under the Apache License, Version 2.0 (the "License");
17948
- * you may not use this file except in compliance with the License.
17949
- * You may obtain a copy of the License at
17950
- *
17951
- * https://www.apache.org/licenses/LICENSE-2.0
17952
- *
17953
- * Unless required by applicable law or agreed to in writing, software
17954
- * distributed under the License is distributed on an "AS IS" BASIS,
17955
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17956
- * See the License for the specific language governing permissions and
17957
- * limitations under the License.
17958
- */
17959
- // this is autogenerated file, see scripts/version-update.js
17960
- const PACKAGE_VERSION$1 = '0.53.0';
17961
- const PACKAGE_NAME$1 = '@opentelemetry/instrumentation-user-interaction';
17962
-
17963
- /*
17964
- * Copyright The OpenTelemetry Authors
17965
- *
17966
- * Licensed under the Apache License, Version 2.0 (the "License");
17967
- * you may not use this file except in compliance with the License.
17968
- * You may obtain a copy of the License at
17969
- *
17970
- * https://www.apache.org/licenses/LICENSE-2.0
17971
- *
17972
- * Unless required by applicable law or agreed to in writing, software
17973
- * distributed under the License is distributed on an "AS IS" BASIS,
17974
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17975
- * See the License for the specific language governing permissions and
17976
- * limitations under the License.
17977
- */
17978
- /// <reference types="zone.js" />
17979
- const ZONE_CONTEXT_KEY = 'OT_ZONE_CONTEXT';
17980
- const EVENT_NAVIGATION_NAME = 'Navigation:';
17981
- const DEFAULT_EVENT_NAMES = ['click'];
17982
- function defaultShouldPreventSpanCreation() {
17983
- return false;
17984
- }
17985
- /**
17986
- * This class represents a UserInteraction plugin for auto instrumentation.
17987
- * If zone.js is available then it patches the zone otherwise it patches
17988
- * addEventListener of HTMLElement
17989
- */
17990
- class UserInteractionInstrumentation extends InstrumentationBase {
17991
- version = PACKAGE_VERSION$1;
17992
- moduleName = 'user-interaction';
17993
- _spansData = new WeakMap();
17994
- // for addEventListener/removeEventListener state
17995
- _wrappedListeners = new WeakMap();
17996
- // for event bubbling
17997
- _eventsSpanMap = new WeakMap();
17998
- _eventNames;
17999
- _shouldPreventSpanCreation;
18000
- constructor(config = {}) {
18001
- super(PACKAGE_NAME$1, PACKAGE_VERSION$1, config);
18002
- this._eventNames = new Set(config?.eventNames ?? DEFAULT_EVENT_NAMES);
18003
- this._shouldPreventSpanCreation =
18004
- typeof config?.shouldPreventSpanCreation === 'function'
18005
- ? config.shouldPreventSpanCreation
18006
- : defaultShouldPreventSpanCreation;
18007
- }
18008
- init() { }
18009
- /**
18010
- * This will check if last task was timeout and will save the time to
18011
- * fix the user interaction when nothing happens
18012
- * This timeout comes from xhr plugin which is needed to collect information
18013
- * about last xhr main request from observer
18014
- * @param task
18015
- * @param span
18016
- */
18017
- _checkForTimeout(task, span) {
18018
- const spanData = this._spansData.get(span);
18019
- if (spanData) {
18020
- if (task.source === 'setTimeout') {
18021
- spanData.hrTimeLastTimeout = hrTime();
18022
- }
18023
- else if (task.source !== 'Promise.then' &&
18024
- task.source !== 'setTimeout') {
18025
- spanData.hrTimeLastTimeout = undefined;
18026
- }
18027
- }
18028
- }
18029
- /**
18030
- * Controls whether or not to create a span, based on the event type.
18031
- */
18032
- _allowEventName(eventName) {
18033
- return this._eventNames.has(eventName);
18034
- }
18035
- /**
18036
- * Creates a new span
18037
- * @param element
18038
- * @param eventName
18039
- * @param parentSpan
18040
- */
18041
- _createSpan(element, eventName, parentSpan) {
18042
- if (!(element instanceof HTMLElement)) {
18043
- return undefined;
18044
- }
18045
- if (!element.getAttribute) {
18046
- return undefined;
18047
- }
18048
- if (element.hasAttribute('disabled')) {
18049
- return undefined;
18050
- }
18051
- if (!this._allowEventName(eventName)) {
18052
- return undefined;
18053
- }
18054
- const xpath = getElementXPath(element, true);
18055
- try {
18056
- const span = this.tracer.startSpan(eventName, {
18057
- attributes: {
18058
- [AttributeNames$1.EVENT_TYPE]: eventName,
18059
- [AttributeNames$1.TARGET_ELEMENT]: element.tagName,
18060
- [AttributeNames$1.TARGET_XPATH]: xpath,
18061
- [AttributeNames$1.HTTP_URL]: window.location.href,
18062
- },
18063
- }, parentSpan
18064
- ? trace.setSpan(context.active(), parentSpan)
18065
- : undefined);
18066
- if (this._shouldPreventSpanCreation(eventName, element, span) === true) {
18067
- return undefined;
18068
- }
18069
- this._spansData.set(span, {
18070
- taskCount: 0,
18071
- });
18072
- return span;
18073
- }
18074
- catch (e) {
18075
- this._diag.error('failed to start create new user interaction span', e);
18076
- }
18077
- return undefined;
18078
- }
18079
- /**
18080
- * Decrement number of tasks that left in zone,
18081
- * This is needed to be able to end span when no more tasks left
18082
- * @param span
18083
- */
18084
- _decrementTask(span) {
18085
- const spanData = this._spansData.get(span);
18086
- if (spanData) {
18087
- spanData.taskCount--;
18088
- if (spanData.taskCount === 0) {
18089
- this._tryToEndSpan(span, spanData.hrTimeLastTimeout);
18090
- }
18091
- }
18092
- }
18093
- /**
18094
- * Return the current span
18095
- * @param zone
18096
- * @private
18097
- */
18098
- _getCurrentSpan(zone) {
18099
- const context = zone.get(ZONE_CONTEXT_KEY);
18100
- if (context) {
18101
- return trace.getSpan(context);
18102
- }
18103
- return context;
18104
- }
18105
- /**
18106
- * Increment number of tasks that are run within the same zone.
18107
- * This is needed to be able to end span when no more tasks left
18108
- * @param span
18109
- */
18110
- _incrementTask(span) {
18111
- const spanData = this._spansData.get(span);
18112
- if (spanData) {
18113
- spanData.taskCount++;
18114
- }
18115
- }
18116
- /**
18117
- * Returns true iff we should use the patched callback; false if it's already been patched
18118
- */
18119
- addPatchedListener(on, type, listener, wrappedListener) {
18120
- let listener2Type = this._wrappedListeners.get(listener);
18121
- if (!listener2Type) {
18122
- listener2Type = new Map();
18123
- this._wrappedListeners.set(listener, listener2Type);
18124
- }
18125
- let element2patched = listener2Type.get(type);
18126
- if (!element2patched) {
18127
- element2patched = new Map();
18128
- listener2Type.set(type, element2patched);
18129
- }
18130
- if (element2patched.has(on)) {
18131
- return false;
18132
- }
18133
- element2patched.set(on, wrappedListener);
18134
- return true;
18135
- }
18136
- /**
18137
- * Returns the patched version of the callback (or undefined)
18138
- */
18139
- removePatchedListener(on, type, listener) {
18140
- const listener2Type = this._wrappedListeners.get(listener);
18141
- if (!listener2Type) {
18142
- return undefined;
18143
- }
18144
- const element2patched = listener2Type.get(type);
18145
- if (!element2patched) {
18146
- return undefined;
18147
- }
18148
- const patched = element2patched.get(on);
18149
- if (patched) {
18150
- element2patched.delete(on);
18151
- if (element2patched.size === 0) {
18152
- listener2Type.delete(type);
18153
- if (listener2Type.size === 0) {
18154
- this._wrappedListeners.delete(listener);
18155
- }
18156
- }
18157
- }
18158
- return patched;
18159
- }
18160
- // utility method to deal with the Function|EventListener nature of addEventListener
18161
- _invokeListener(listener, target, args) {
18162
- if (typeof listener === 'function') {
18163
- return listener.apply(target, args);
18164
- }
18165
- else {
18166
- return listener.handleEvent(args[0]);
18167
- }
18168
- }
18169
- /**
18170
- * This patches the addEventListener of HTMLElement to be able to
18171
- * auto instrument the click events
18172
- * This is done when zone is not available
18173
- */
18174
- _patchAddEventListener() {
18175
- const plugin = this;
18176
- return (original) => {
18177
- return function addEventListenerPatched(type, listener, useCapture) {
18178
- // Forward calls with listener = null
18179
- if (!listener) {
18180
- return original.call(this, type, listener, useCapture);
18181
- }
18182
- // filter out null (typeof null === 'object')
18183
- const once = useCapture && typeof useCapture === 'object' && useCapture.once;
18184
- const patchedListener = function (...args) {
18185
- let parentSpan;
18186
- const event = args[0];
18187
- const target = event?.target;
18188
- if (event) {
18189
- parentSpan = plugin._eventsSpanMap.get(event);
18190
- }
18191
- if (once) {
18192
- plugin.removePatchedListener(this, type, listener);
18193
- }
18194
- const span = plugin._createSpan(target, type, parentSpan);
18195
- if (span) {
18196
- if (event) {
18197
- plugin._eventsSpanMap.set(event, span);
18198
- }
18199
- return context.with(trace.setSpan(context.active(), span), () => {
18200
- const result = plugin._invokeListener(listener, this, args);
18201
- // no zone so end span immediately
18202
- span.end();
18203
- return result;
18204
- });
18205
- }
18206
- else {
18207
- return plugin._invokeListener(listener, this, args);
18208
- }
18209
- };
18210
- if (plugin.addPatchedListener(this, type, listener, patchedListener)) {
18211
- return original.call(this, type, patchedListener, useCapture);
18212
- }
18213
- };
18214
- };
18215
- }
18216
- /**
18217
- * This patches the removeEventListener of HTMLElement to handle the fact that
18218
- * we patched the original callbacks
18219
- * This is done when zone is not available
18220
- */
18221
- _patchRemoveEventListener() {
18222
- const plugin = this;
18223
- return (original) => {
18224
- return function removeEventListenerPatched(type, listener, useCapture) {
18225
- const wrappedListener = plugin.removePatchedListener(this, type, listener);
18226
- if (wrappedListener) {
18227
- return original.call(this, type, wrappedListener, useCapture);
18228
- }
18229
- else {
18230
- return original.call(this, type, listener, useCapture);
18231
- }
18232
- };
18233
- };
18234
- }
18235
- /**
18236
- * Most browser provide event listener api via EventTarget in prototype chain.
18237
- * Exception to this is IE 11 which has it on the prototypes closest to EventTarget:
18238
- *
18239
- * * - has addEventListener in IE
18240
- * ** - has addEventListener in all other browsers
18241
- * ! - missing in IE
18242
- *
18243
- * HTMLElement -> Element -> Node * -> EventTarget **! -> Object
18244
- * Document -> Node * -> EventTarget **! -> Object
18245
- * Window * -> WindowProperties ! -> EventTarget **! -> Object
18246
- */
18247
- _getPatchableEventTargets() {
18248
- return window.EventTarget
18249
- ? [EventTarget.prototype]
18250
- : [Node.prototype, Window.prototype];
18251
- }
18252
- /**
18253
- * Patches the history api
18254
- */
18255
- _patchHistoryApi() {
18256
- this._unpatchHistoryApi();
18257
- this._wrap(history, 'replaceState', this._patchHistoryMethod());
18258
- this._wrap(history, 'pushState', this._patchHistoryMethod());
18259
- this._wrap(history, 'back', this._patchHistoryMethod());
18260
- this._wrap(history, 'forward', this._patchHistoryMethod());
18261
- this._wrap(history, 'go', this._patchHistoryMethod());
18262
- }
18263
- /**
18264
- * Patches the certain history api method
18265
- */
18266
- _patchHistoryMethod() {
18267
- const plugin = this;
18268
- return (original) => {
18269
- return function patchHistoryMethod(...args) {
18270
- const url = `${location.pathname}${location.hash}${location.search}`;
18271
- const result = original.apply(this, args);
18272
- const urlAfter = `${location.pathname}${location.hash}${location.search}`;
18273
- if (url !== urlAfter) {
18274
- plugin._updateInteractionName(urlAfter);
18275
- }
18276
- return result;
18277
- };
18278
- };
18279
- }
18280
- /**
18281
- * unpatch the history api methods
18282
- */
18283
- _unpatchHistoryApi() {
18284
- if (isWrapped(history.replaceState))
18285
- this._unwrap(history, 'replaceState');
18286
- if (isWrapped(history.pushState))
18287
- this._unwrap(history, 'pushState');
18288
- if (isWrapped(history.back))
18289
- this._unwrap(history, 'back');
18290
- if (isWrapped(history.forward))
18291
- this._unwrap(history, 'forward');
18292
- if (isWrapped(history.go))
18293
- this._unwrap(history, 'go');
18294
- }
18295
- /**
18296
- * Updates interaction span name
18297
- * @param url
18298
- */
18299
- _updateInteractionName(url) {
18300
- const span = trace.getSpan(context.active());
18301
- if (span && typeof span.updateName === 'function') {
18302
- span.updateName(`${EVENT_NAVIGATION_NAME} ${url}`);
18303
- }
18304
- }
18305
- /**
18306
- * Patches zone cancel task - this is done to be able to correctly
18307
- * decrement the number of remaining tasks
18308
- */
18309
- _patchZoneCancelTask() {
18310
- const plugin = this;
18311
- return (original) => {
18312
- return function patchCancelTask(task) {
18313
- const currentZone = Zone.current;
18314
- const currentSpan = plugin._getCurrentSpan(currentZone);
18315
- if (currentSpan && plugin._shouldCountTask(task, currentZone)) {
18316
- plugin._decrementTask(currentSpan);
18317
- }
18318
- return original.call(this, task);
18319
- };
18320
- };
18321
- }
18322
- /**
18323
- * Patches zone schedule task - this is done to be able to correctly
18324
- * increment the number of tasks running within current zone but also to
18325
- * save time in case of timeout running from xhr plugin when waiting for
18326
- * main request from PerformanceResourceTiming
18327
- */
18328
- _patchZoneScheduleTask() {
18329
- const plugin = this;
18330
- return (original) => {
18331
- return function patchScheduleTask(task) {
18332
- const currentZone = Zone.current;
18333
- const currentSpan = plugin._getCurrentSpan(currentZone);
18334
- if (currentSpan && plugin._shouldCountTask(task, currentZone)) {
18335
- plugin._incrementTask(currentSpan);
18336
- plugin._checkForTimeout(task, currentSpan);
18337
- }
18338
- return original.call(this, task);
18339
- };
18340
- };
18341
- }
18342
- /**
18343
- * Patches zone run task - this is done to be able to create a span when
18344
- * user interaction starts
18345
- * @private
18346
- */
18347
- _patchZoneRunTask() {
18348
- const plugin = this;
18349
- return (original) => {
18350
- return function patchRunTask(task, applyThis, applyArgs) {
18351
- const event = Array.isArray(applyArgs) && applyArgs[0] instanceof Event
18352
- ? applyArgs[0]
18353
- : undefined;
18354
- const target = event?.target;
18355
- let span;
18356
- const activeZone = this;
18357
- if (target) {
18358
- span = plugin._createSpan(target, task.eventName);
18359
- if (span) {
18360
- plugin._incrementTask(span);
18361
- return activeZone.run(() => {
18362
- try {
18363
- return context.with(trace.setSpan(context.active(), span), () => {
18364
- const currentZone = Zone.current;
18365
- task._zone = currentZone;
18366
- return original.call(currentZone, task, applyThis, applyArgs);
18367
- });
18368
- }
18369
- finally {
18370
- plugin._decrementTask(span);
18371
- }
18372
- });
18373
- }
18374
- }
18375
- else {
18376
- span = plugin._getCurrentSpan(activeZone);
18377
- }
18378
- try {
18379
- return original.call(activeZone, task, applyThis, applyArgs);
18380
- }
18381
- finally {
18382
- if (span && plugin._shouldCountTask(task, activeZone)) {
18383
- plugin._decrementTask(span);
18384
- }
18385
- }
18386
- };
18387
- };
18388
- }
18389
- /**
18390
- * Decides if task should be counted.
18391
- * @param task
18392
- * @param currentZone
18393
- * @private
18394
- */
18395
- _shouldCountTask(task, currentZone) {
18396
- if (task._zone) {
18397
- currentZone = task._zone;
18398
- }
18399
- if (!currentZone || !task.data || task.data.isPeriodic) {
18400
- return false;
18401
- }
18402
- const currentSpan = this._getCurrentSpan(currentZone);
18403
- if (!currentSpan) {
18404
- return false;
18405
- }
18406
- if (!this._spansData.get(currentSpan)) {
18407
- return false;
18408
- }
18409
- return task.type === 'macroTask' || task.type === 'microTask';
18410
- }
18411
- /**
18412
- * Will try to end span when such span still exists.
18413
- * @param span
18414
- * @param endTime
18415
- * @private
18416
- */
18417
- _tryToEndSpan(span, endTime) {
18418
- if (span) {
18419
- const spanData = this._spansData.get(span);
18420
- if (spanData) {
18421
- span.end(endTime);
18422
- this._spansData.delete(span);
18423
- }
18424
- }
18425
- }
18426
- /**
18427
- * implements enable function
18428
- */
18429
- enable() {
18430
- const ZoneWithPrototype = this._getZoneWithPrototype();
18431
- this._diag.debug('applying patch to', this.moduleName, this.version, 'zone:', !!ZoneWithPrototype);
18432
- if (ZoneWithPrototype) {
18433
- if (isWrapped(ZoneWithPrototype.prototype.runTask)) {
18434
- this._unwrap(ZoneWithPrototype.prototype, 'runTask');
18435
- this._diag.debug('removing previous patch from method runTask');
18436
- }
18437
- if (isWrapped(ZoneWithPrototype.prototype.scheduleTask)) {
18438
- this._unwrap(ZoneWithPrototype.prototype, 'scheduleTask');
18439
- this._diag.debug('removing previous patch from method scheduleTask');
18440
- }
18441
- if (isWrapped(ZoneWithPrototype.prototype.cancelTask)) {
18442
- this._unwrap(ZoneWithPrototype.prototype, 'cancelTask');
18443
- this._diag.debug('removing previous patch from method cancelTask');
18444
- }
18445
- this._zonePatched = true;
18446
- this._wrap(ZoneWithPrototype.prototype, 'runTask', this._patchZoneRunTask());
18447
- this._wrap(ZoneWithPrototype.prototype, 'scheduleTask', this._patchZoneScheduleTask());
18448
- this._wrap(ZoneWithPrototype.prototype, 'cancelTask', this._patchZoneCancelTask());
18449
- }
18450
- else {
18451
- this._zonePatched = false;
18452
- const targets = this._getPatchableEventTargets();
18453
- targets.forEach(target => {
18454
- if (isWrapped(target.addEventListener)) {
18455
- this._unwrap(target, 'addEventListener');
18456
- this._diag.debug('removing previous patch from method addEventListener');
18457
- }
18458
- if (isWrapped(target.removeEventListener)) {
18459
- this._unwrap(target, 'removeEventListener');
18460
- this._diag.debug('removing previous patch from method removeEventListener');
18461
- }
18462
- this._wrap(target, 'addEventListener', this._patchAddEventListener());
18463
- this._wrap(target, 'removeEventListener', this._patchRemoveEventListener());
18464
- });
18465
- }
18466
- this._patchHistoryApi();
18467
- }
18468
- /**
18469
- * implements unpatch function
18470
- */
18471
- disable() {
18472
- const ZoneWithPrototype = this._getZoneWithPrototype();
18473
- this._diag.debug('removing patch from', this.moduleName, this.version, 'zone:', !!ZoneWithPrototype);
18474
- if (ZoneWithPrototype && this._zonePatched) {
18475
- if (isWrapped(ZoneWithPrototype.prototype.runTask)) {
18476
- this._unwrap(ZoneWithPrototype.prototype, 'runTask');
18477
- }
18478
- if (isWrapped(ZoneWithPrototype.prototype.scheduleTask)) {
18479
- this._unwrap(ZoneWithPrototype.prototype, 'scheduleTask');
18480
- }
18481
- if (isWrapped(ZoneWithPrototype.prototype.cancelTask)) {
18482
- this._unwrap(ZoneWithPrototype.prototype, 'cancelTask');
18483
- }
18484
- }
18485
- else {
18486
- const targets = this._getPatchableEventTargets();
18487
- targets.forEach(target => {
18488
- if (isWrapped(target.addEventListener)) {
18489
- this._unwrap(target, 'addEventListener');
18490
- }
18491
- if (isWrapped(target.removeEventListener)) {
18492
- this._unwrap(target, 'removeEventListener');
18493
- }
18494
- });
18495
- }
18496
- this._unpatchHistoryApi();
18497
- }
18498
- /**
18499
- * returns Zone
18500
- */
18501
- _getZoneWithPrototype() {
18502
- const _window = window;
18503
- return _window.Zone;
18504
- }
18505
- }
18506
-
18507
- /*
18508
- * Copyright The OpenTelemetry Authors
18509
- *
18510
- * Licensed under the Apache License, Version 2.0 (the "License");
18511
- * you may not use this file except in compliance with the License.
18512
- * You may obtain a copy of the License at
18513
- *
18514
- * https://www.apache.org/licenses/LICENSE-2.0
18515
- *
18516
- * Unless required by applicable law or agreed to in writing, software
18517
- * distributed under the License is distributed on an "AS IS" BASIS,
18518
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18519
- * See the License for the specific language governing permissions and
18520
- * limitations under the License.
18521
- */
18522
- var AttributeNames;
18523
- (function (AttributeNames) {
18524
- AttributeNames["DOCUMENT_LOAD"] = "documentLoad";
18525
- AttributeNames["DOCUMENT_FETCH"] = "documentFetch";
18526
- AttributeNames["RESOURCE_FETCH"] = "resourceFetch";
18527
- })(AttributeNames || (AttributeNames = {}));
18528
-
18529
- /*
18530
- * Copyright The OpenTelemetry Authors
18531
- *
18532
- * Licensed under the Apache License, Version 2.0 (the "License");
18533
- * you may not use this file except in compliance with the License.
18534
- * You may obtain a copy of the License at
18535
- *
18536
- * https://www.apache.org/licenses/LICENSE-2.0
18537
- *
18538
- * Unless required by applicable law or agreed to in writing, software
18539
- * distributed under the License is distributed on an "AS IS" BASIS,
18540
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18541
- * See the License for the specific language governing permissions and
18542
- * limitations under the License.
18543
- */
18544
- // this is autogenerated file, see scripts/version-update.js
18545
- const PACKAGE_VERSION = '0.54.0';
18546
- const PACKAGE_NAME = '@opentelemetry/instrumentation-document-load';
18547
-
18548
- /*
18549
- * Copyright The OpenTelemetry Authors
18550
- *
18551
- * Licensed under the Apache License, Version 2.0 (the "License");
18552
- * you may not use this file except in compliance with the License.
18553
- * You may obtain a copy of the License at
18554
- *
18555
- * https://www.apache.org/licenses/LICENSE-2.0
18556
- *
18557
- * Unless required by applicable law or agreed to in writing, software
18558
- * distributed under the License is distributed on an "AS IS" BASIS,
18559
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18560
- * See the License for the specific language governing permissions and
18561
- * limitations under the License.
18562
- */
18563
- /*
18564
- * This file contains a copy of unstable semantic convention definitions
18565
- * used by this package.
18566
- * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv
18567
- */
18568
- /**
18569
- * Deprecated, use `http.response.header.content-length` instead.
18570
- *
18571
- * @example 3495
18572
- *
18573
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
18574
- *
18575
- * @deprecated Replaced by `http.response.header.content-length`.
18576
- */
18577
- /**
18578
- * Deprecated, use `url.full` instead.
18579
- *
18580
- * @example https://www.foo.bar/search?q=OpenTelemetry#SemConv
18581
- *
18582
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
18583
- *
18584
- * @deprecated Replaced by `url.full`.
18585
- */
18586
- const ATTR_HTTP_URL = 'http.url';
18587
- /**
18588
- * Deprecated, use `user_agent.original` instead.
18589
- *
18590
- * @example CERN-LineMode/2.15 libwww/2.17b3
18591
- * @example Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1
18592
- *
18593
- * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
18594
- *
18595
- * @deprecated Replaced by `user_agent.original`.
18596
- */
18597
- const ATTR_HTTP_USER_AGENT = 'http.user_agent';
18598
-
18599
- /*
18600
- * Copyright The OpenTelemetry Authors
18601
- *
18602
- * Licensed under the Apache License, Version 2.0 (the "License");
18603
- * you may not use this file except in compliance with the License.
18604
- * You may obtain a copy of the License at
18605
- *
18606
- * https://www.apache.org/licenses/LICENSE-2.0
18607
- *
18608
- * Unless required by applicable law or agreed to in writing, software
18609
- * distributed under the License is distributed on an "AS IS" BASIS,
18610
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18611
- * See the License for the specific language governing permissions and
18612
- * limitations under the License.
18613
- */
18614
- var EventNames;
18615
- (function (EventNames) {
18616
- EventNames["FIRST_PAINT"] = "firstPaint";
18617
- EventNames["FIRST_CONTENTFUL_PAINT"] = "firstContentfulPaint";
18618
- })(EventNames || (EventNames = {}));
18619
-
18620
- /*
18621
- * Copyright The OpenTelemetry Authors
18622
- *
18623
- * Licensed under the Apache License, Version 2.0 (the "License");
18624
- * you may not use this file except in compliance with the License.
18625
- * You may obtain a copy of the License at
18626
- *
18627
- * https://www.apache.org/licenses/LICENSE-2.0
18628
- *
18629
- * Unless required by applicable law or agreed to in writing, software
18630
- * distributed under the License is distributed on an "AS IS" BASIS,
18631
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18632
- * See the License for the specific language governing permissions and
18633
- * limitations under the License.
18634
- */
18635
- const getPerformanceNavigationEntries = () => {
18636
- const entries = {};
18637
- const performanceNavigationTiming = otperformance.getEntriesByType?.('navigation')[0];
18638
- if (performanceNavigationTiming) {
18639
- const keys = Object.values(PerformanceTimingNames);
18640
- keys.forEach((key) => {
18641
- if (hasKey(performanceNavigationTiming, key)) {
18642
- const value = performanceNavigationTiming[key];
18643
- if (typeof value === 'number') {
18644
- entries[key] = value;
18645
- }
18646
- }
18647
- });
18648
- }
18649
- else {
18650
- // // fallback to previous version
18651
- const perf = otperformance;
18652
- const performanceTiming = perf.timing;
18653
- if (performanceTiming) {
18654
- const keys = Object.values(PerformanceTimingNames);
18655
- keys.forEach((key) => {
18656
- if (hasKey(performanceTiming, key)) {
18657
- const value = performanceTiming[key];
18658
- if (typeof value === 'number') {
18659
- entries[key] = value;
18660
- }
18661
- }
18662
- });
18663
- }
18664
- }
18665
- return entries;
18666
- };
18667
- const performancePaintNames = {
18668
- 'first-paint': EventNames.FIRST_PAINT,
18669
- 'first-contentful-paint': EventNames.FIRST_CONTENTFUL_PAINT,
18670
- };
18671
- const addSpanPerformancePaintEvents = (span) => {
18672
- const performancePaintTiming = otperformance.getEntriesByType?.('paint');
18673
- if (performancePaintTiming) {
18674
- performancePaintTiming.forEach(({ name, startTime }) => {
18675
- if (hasKey(performancePaintNames, name)) {
18676
- span.addEvent(performancePaintNames[name], startTime);
18677
- }
18678
- });
18679
- }
18680
- };
18681
-
18682
- /*
18683
- * Copyright The OpenTelemetry Authors
18684
- *
18685
- * Licensed under the Apache License, Version 2.0 (the "License");
18686
- * you may not use this file except in compliance with the License.
18687
- * You may obtain a copy of the License at
18688
- *
18689
- * https://www.apache.org/licenses/LICENSE-2.0
18690
- *
18691
- * Unless required by applicable law or agreed to in writing, software
18692
- * distributed under the License is distributed on an "AS IS" BASIS,
18693
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18694
- * See the License for the specific language governing permissions and
18695
- * limitations under the License.
18696
- */
18697
- /**
18698
- * This class represents a document load plugin
18699
- */
18700
- class DocumentLoadInstrumentation extends InstrumentationBase {
18701
- component = 'document-load';
18702
- version = '1';
18703
- moduleName = this.component;
18704
- _semconvStability;
18705
- constructor(config = {}) {
18706
- super(PACKAGE_NAME, PACKAGE_VERSION, config);
18707
- this._semconvStability = semconvStabilityFromStr('http', config?.semconvStabilityOptIn);
18708
- }
18709
- init() { }
18710
- /**
18711
- * callback to be executed when page is loaded
18712
- */
18713
- _onDocumentLoaded() {
18714
- // Timeout is needed as load event doesn't have yet the performance metrics for loadEnd.
18715
- // Support for event "loadend" is very limited and cannot be used
18716
- window.setTimeout(() => {
18717
- this._collectPerformance();
18718
- });
16141
+ return function patchCancelTask(task) {
16142
+ const currentZone = Zone.current;
16143
+ const currentSpan = plugin._getCurrentSpan(currentZone);
16144
+ if (currentSpan && plugin._shouldCountTask(task, currentZone)) {
16145
+ plugin._decrementTask(currentSpan);
16146
+ }
16147
+ return original.call(this, task);
16148
+ };
16149
+ };
18719
16150
  }
18720
16151
  /**
18721
- * Adds spans for all resources
18722
- * @param rootSpan
16152
+ * Patches zone schedule task - this is done to be able to correctly
16153
+ * increment the number of tasks running within current zone but also to
16154
+ * save time in case of timeout running from xhr plugin when waiting for
16155
+ * main request from PerformanceResourceTiming
18723
16156
  */
18724
- _addResourcesSpans(rootSpan) {
18725
- const resources = otperformance.getEntriesByType?.('resource');
18726
- if (resources) {
18727
- resources.forEach(resource => {
18728
- this._initResourceSpan(resource, rootSpan);
18729
- });
18730
- }
16157
+ _patchZoneScheduleTask() {
16158
+ const plugin = this;
16159
+ return (original) => {
16160
+ return function patchScheduleTask(task) {
16161
+ const currentZone = Zone.current;
16162
+ const currentSpan = plugin._getCurrentSpan(currentZone);
16163
+ if (currentSpan && plugin._shouldCountTask(task, currentZone)) {
16164
+ plugin._incrementTask(currentSpan);
16165
+ plugin._checkForTimeout(task, currentSpan);
16166
+ }
16167
+ return original.call(this, task);
16168
+ };
16169
+ };
18731
16170
  }
18732
16171
  /**
18733
- * Collects information about performance and creates appropriate spans
16172
+ * Patches zone run task - this is done to be able to create a span when
16173
+ * user interaction starts
16174
+ * @private
18734
16175
  */
18735
- _collectPerformance() {
18736
- const metaElement = Array.from(document.getElementsByTagName('meta')).find(e => e.getAttribute('name') === TRACE_PARENT_HEADER);
18737
- const entries = getPerformanceNavigationEntries();
18738
- const traceparent = (metaElement && metaElement.content) || '';
18739
- context.with(propagation.extract(ROOT_CONTEXT, { traceparent }), () => {
18740
- const rootSpan = this._startSpan(AttributeNames.DOCUMENT_LOAD, PerformanceTimingNames.FETCH_START, entries);
18741
- if (!rootSpan) {
18742
- return;
18743
- }
18744
- context.with(trace.setSpan(context.active(), rootSpan), () => {
18745
- const fetchSpan = this._startSpan(AttributeNames.DOCUMENT_FETCH, PerformanceTimingNames.FETCH_START, entries);
18746
- if (fetchSpan) {
18747
- if (this._semconvStability & SemconvStability.OLD) {
18748
- fetchSpan.setAttribute(ATTR_HTTP_URL, location.href);
16176
+ _patchZoneRunTask() {
16177
+ const plugin = this;
16178
+ return (original) => {
16179
+ return function patchRunTask(task, applyThis, applyArgs) {
16180
+ const event = Array.isArray(applyArgs) && applyArgs[0] instanceof Event
16181
+ ? applyArgs[0]
16182
+ : undefined;
16183
+ const target = event?.target;
16184
+ let span;
16185
+ const activeZone = this;
16186
+ if (target) {
16187
+ span = plugin._createSpan(target, task.eventName);
16188
+ if (span) {
16189
+ plugin._incrementTask(span);
16190
+ return activeZone.run(() => {
16191
+ try {
16192
+ return context.with(trace.setSpan(context.active(), span), () => {
16193
+ const currentZone = Zone.current;
16194
+ task._zone = currentZone;
16195
+ return original.call(currentZone, task, applyThis, applyArgs);
16196
+ });
16197
+ }
16198
+ finally {
16199
+ plugin._decrementTask(span);
16200
+ }
16201
+ });
18749
16202
  }
18750
- if (this._semconvStability & SemconvStability.STABLE) {
18751
- fetchSpan.setAttribute(ATTR_URL_FULL, location.href);
16203
+ }
16204
+ else {
16205
+ span = plugin._getCurrentSpan(activeZone);
16206
+ }
16207
+ try {
16208
+ return original.call(activeZone, task, applyThis, applyArgs);
16209
+ }
16210
+ finally {
16211
+ if (span && plugin._shouldCountTask(task, activeZone)) {
16212
+ plugin._decrementTask(span);
18752
16213
  }
18753
- context.with(trace.setSpan(context.active(), fetchSpan), () => {
18754
- const skipOldSemconvContentLengthAttrs = !(this._semconvStability & SemconvStability.OLD);
18755
- addSpanNetworkEvents(fetchSpan, entries, this.getConfig().ignoreNetworkEvents, undefined, skipOldSemconvContentLengthAttrs);
18756
- this._addCustomAttributesOnSpan(fetchSpan, this.getConfig().applyCustomAttributesOnSpan?.documentFetch);
18757
- this._endSpan(fetchSpan, PerformanceTimingNames.RESPONSE_END, entries);
18758
- });
18759
16214
  }
18760
- });
18761
- if (this._semconvStability & SemconvStability.OLD) {
18762
- rootSpan.setAttribute(ATTR_HTTP_URL, location.href);
18763
- rootSpan.setAttribute(ATTR_HTTP_USER_AGENT, navigator.userAgent);
18764
- }
18765
- if (this._semconvStability & SemconvStability.STABLE) {
18766
- rootSpan.setAttribute(ATTR_URL_FULL, location.href);
18767
- rootSpan.setAttribute(ATTR_USER_AGENT_ORIGINAL, navigator.userAgent);
18768
- }
18769
- this._addResourcesSpans(rootSpan);
18770
- if (!this.getConfig().ignoreNetworkEvents) {
18771
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.FETCH_START, entries);
18772
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.UNLOAD_EVENT_START, entries);
18773
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.UNLOAD_EVENT_END, entries);
18774
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.DOM_INTERACTIVE, entries);
18775
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.DOM_CONTENT_LOADED_EVENT_START, entries);
18776
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.DOM_CONTENT_LOADED_EVENT_END, entries);
18777
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.DOM_COMPLETE, entries);
18778
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.LOAD_EVENT_START, entries);
18779
- addSpanNetworkEvent(rootSpan, PerformanceTimingNames.LOAD_EVENT_END, entries);
18780
- }
18781
- if (!this.getConfig().ignorePerformancePaintEvents) {
18782
- addSpanPerformancePaintEvents(rootSpan);
18783
- }
18784
- this._addCustomAttributesOnSpan(rootSpan, this.getConfig().applyCustomAttributesOnSpan?.documentLoad);
18785
- this._endSpan(rootSpan, PerformanceTimingNames.LOAD_EVENT_END, entries);
18786
- });
16215
+ };
16216
+ };
18787
16217
  }
18788
16218
  /**
18789
- * Helper function for ending span
18790
- * @param span
18791
- * @param performanceName name of performance entry for time end
18792
- * @param entries
16219
+ * Decides if task should be counted.
16220
+ * @param task
16221
+ * @param currentZone
16222
+ * @private
18793
16223
  */
18794
- _endSpan(span, performanceName, entries) {
18795
- // span can be undefined when entries are missing the certain performance - the span will not be created
18796
- if (span) {
18797
- if (hasKey(entries, performanceName)) {
18798
- span.end(entries[performanceName]);
18799
- }
18800
- else {
18801
- // just end span
18802
- span.end();
18803
- }
16224
+ _shouldCountTask(task, currentZone) {
16225
+ if (task._zone) {
16226
+ currentZone = task._zone;
16227
+ }
16228
+ if (!currentZone || !task.data || task.data.isPeriodic) {
16229
+ return false;
16230
+ }
16231
+ const currentSpan = this._getCurrentSpan(currentZone);
16232
+ if (!currentSpan) {
16233
+ return false;
16234
+ }
16235
+ if (!this._spansData.get(currentSpan)) {
16236
+ return false;
18804
16237
  }
16238
+ return task.type === 'macroTask' || task.type === 'microTask';
18805
16239
  }
18806
16240
  /**
18807
- * Creates and ends a span with network information about resource added as timed events
18808
- * @param resource
18809
- * @param parentSpan
16241
+ * Will try to end span when such span still exists.
16242
+ * @param span
16243
+ * @param endTime
16244
+ * @private
18810
16245
  */
18811
- _initResourceSpan(resource, parentSpan) {
18812
- const span = this._startSpan(AttributeNames.RESOURCE_FETCH, PerformanceTimingNames.FETCH_START, resource, parentSpan);
16246
+ _tryToEndSpan(span, endTime) {
18813
16247
  if (span) {
18814
- if (this._semconvStability & SemconvStability.OLD) {
18815
- span.setAttribute(ATTR_HTTP_URL, resource.name);
18816
- }
18817
- if (this._semconvStability & SemconvStability.STABLE) {
18818
- span.setAttribute(ATTR_URL_FULL, resource.name);
16248
+ const spanData = this._spansData.get(span);
16249
+ if (spanData) {
16250
+ span.end(endTime);
16251
+ this._spansData.delete(span);
18819
16252
  }
18820
- const skipOldSemconvContentLengthAttrs = !(this._semconvStability & SemconvStability.OLD);
18821
- addSpanNetworkEvents(span, resource, this.getConfig().ignoreNetworkEvents, undefined, skipOldSemconvContentLengthAttrs);
18822
- this._addCustomAttributesOnResourceSpan(span, resource, this.getConfig().applyCustomAttributesOnSpan?.resourceFetch);
18823
- this._endSpan(span, PerformanceTimingNames.RESPONSE_END, resource);
18824
- }
18825
- }
18826
- /**
18827
- * Helper function for starting a span
18828
- * @param spanName name of span
18829
- * @param performanceName name of performance entry for time start
18830
- * @param entries
18831
- * @param parentSpan
18832
- */
18833
- _startSpan(spanName, performanceName, entries, parentSpan) {
18834
- if (hasKey(entries, performanceName) &&
18835
- typeof entries[performanceName] === 'number') {
18836
- const span = this.tracer.startSpan(spanName, {
18837
- startTime: entries[performanceName],
18838
- }, parentSpan ? trace.setSpan(context.active(), parentSpan) : undefined);
18839
- return span;
18840
16253
  }
18841
- return undefined;
18842
16254
  }
18843
16255
  /**
18844
- * executes callback {_onDocumentLoaded} when the page is loaded
16256
+ * implements enable function
18845
16257
  */
18846
- _waitForPageLoad() {
18847
- if (window.document.readyState === 'complete') {
18848
- this._onDocumentLoaded();
16258
+ enable() {
16259
+ const ZoneWithPrototype = this._getZoneWithPrototype();
16260
+ this._diag.debug('applying patch to', this.moduleName, this.version, 'zone:', !!ZoneWithPrototype);
16261
+ if (ZoneWithPrototype) {
16262
+ if (isWrapped(ZoneWithPrototype.prototype.runTask)) {
16263
+ this._unwrap(ZoneWithPrototype.prototype, 'runTask');
16264
+ this._diag.debug('removing previous patch from method runTask');
16265
+ }
16266
+ if (isWrapped(ZoneWithPrototype.prototype.scheduleTask)) {
16267
+ this._unwrap(ZoneWithPrototype.prototype, 'scheduleTask');
16268
+ this._diag.debug('removing previous patch from method scheduleTask');
16269
+ }
16270
+ if (isWrapped(ZoneWithPrototype.prototype.cancelTask)) {
16271
+ this._unwrap(ZoneWithPrototype.prototype, 'cancelTask');
16272
+ this._diag.debug('removing previous patch from method cancelTask');
16273
+ }
16274
+ this._zonePatched = true;
16275
+ this._wrap(ZoneWithPrototype.prototype, 'runTask', this._patchZoneRunTask());
16276
+ this._wrap(ZoneWithPrototype.prototype, 'scheduleTask', this._patchZoneScheduleTask());
16277
+ this._wrap(ZoneWithPrototype.prototype, 'cancelTask', this._patchZoneCancelTask());
18849
16278
  }
18850
16279
  else {
18851
- this._onDocumentLoaded = this._onDocumentLoaded.bind(this);
18852
- window.addEventListener('load', this._onDocumentLoaded);
18853
- }
18854
- }
18855
- /**
18856
- * adds custom attributes to root span if configured
18857
- */
18858
- _addCustomAttributesOnSpan(span, applyCustomAttributesOnSpan) {
18859
- if (applyCustomAttributesOnSpan) {
18860
- safeExecuteInTheMiddle(() => applyCustomAttributesOnSpan(span), error => {
18861
- if (!error) {
18862
- return;
16280
+ this._zonePatched = false;
16281
+ const targets = this._getPatchableEventTargets();
16282
+ targets.forEach(target => {
16283
+ if (isWrapped(target.addEventListener)) {
16284
+ this._unwrap(target, 'addEventListener');
16285
+ this._diag.debug('removing previous patch from method addEventListener');
16286
+ }
16287
+ if (isWrapped(target.removeEventListener)) {
16288
+ this._unwrap(target, 'removeEventListener');
16289
+ this._diag.debug('removing previous patch from method removeEventListener');
18863
16290
  }
18864
- this._diag.error('addCustomAttributesOnSpan', error);
16291
+ this._wrap(target, 'addEventListener', this._patchAddEventListener());
16292
+ this._wrap(target, 'removeEventListener', this._patchRemoveEventListener());
18865
16293
  });
18866
16294
  }
16295
+ this._patchHistoryApi();
18867
16296
  }
18868
16297
  /**
18869
- * adds custom attributes to span if configured
16298
+ * implements unpatch function
18870
16299
  */
18871
- _addCustomAttributesOnResourceSpan(span, resource, applyCustomAttributesOnSpan) {
18872
- if (applyCustomAttributesOnSpan) {
18873
- safeExecuteInTheMiddle(() => applyCustomAttributesOnSpan(span, resource), error => {
18874
- if (!error) {
18875
- return;
16300
+ disable() {
16301
+ const ZoneWithPrototype = this._getZoneWithPrototype();
16302
+ this._diag.debug('removing patch from', this.moduleName, this.version, 'zone:', !!ZoneWithPrototype);
16303
+ if (ZoneWithPrototype && this._zonePatched) {
16304
+ if (isWrapped(ZoneWithPrototype.prototype.runTask)) {
16305
+ this._unwrap(ZoneWithPrototype.prototype, 'runTask');
16306
+ }
16307
+ if (isWrapped(ZoneWithPrototype.prototype.scheduleTask)) {
16308
+ this._unwrap(ZoneWithPrototype.prototype, 'scheduleTask');
16309
+ }
16310
+ if (isWrapped(ZoneWithPrototype.prototype.cancelTask)) {
16311
+ this._unwrap(ZoneWithPrototype.prototype, 'cancelTask');
16312
+ }
16313
+ }
16314
+ else {
16315
+ const targets = this._getPatchableEventTargets();
16316
+ targets.forEach(target => {
16317
+ if (isWrapped(target.addEventListener)) {
16318
+ this._unwrap(target, 'addEventListener');
16319
+ }
16320
+ if (isWrapped(target.removeEventListener)) {
16321
+ this._unwrap(target, 'removeEventListener');
18876
16322
  }
18877
- this._diag.error('addCustomAttributesOnResourceSpan', error);
18878
16323
  });
18879
16324
  }
16325
+ this._unpatchHistoryApi();
18880
16326
  }
18881
16327
  /**
18882
- * implements enable function
18883
- */
18884
- enable() {
18885
- // remove previously attached load to avoid adding the same event twice
18886
- // in case of multiple enable calling.
18887
- window.removeEventListener('load', this._onDocumentLoaded);
18888
- this._waitForPageLoad();
18889
- }
18890
- /**
18891
- * implements disable function
16328
+ * returns Zone
18892
16329
  */
18893
- disable() {
18894
- window.removeEventListener('load', this._onDocumentLoaded);
16330
+ _getZoneWithPrototype() {
16331
+ const _window = window;
16332
+ return _window.Zone;
18895
16333
  }
18896
16334
  }
18897
16335
 
@@ -19951,6 +17389,65 @@ var UAParser = /*@__PURE__*/getDefaultExportFromCjs(uaParserExports);
19951
17389
  // Semantic convention attribute names
19952
17390
  const ATTR_SERVICE_NAME = 'service.name';
19953
17391
  const ATTR_SERVICE_VERSION = 'service.version';
17392
+ // Token de autenticación para OpenTelemetry Collector
17393
+ const AUTH_TOKEN = 'eAzROSTiqNd3i+M9Jw6q5Tld0jarZc617sJB//pvb5c=';
17394
+ // Instalar interceptores globalmente UNA SOLA VEZ antes de cualquier inicialización
17395
+ let interceptorsInstalled = false;
17396
+ function installAuthInterceptors() {
17397
+ if (interceptorsInstalled) {
17398
+ return;
17399
+ }
17400
+ interceptorsInstalled = true;
17401
+ // Guardar referencia al XHR original ANTES de que OpenTelemetry lo toque
17402
+ const RealXHR = window.XMLHttpRequest;
17403
+ if (!RealXHR) {
17404
+ console.error('[TracingService] XMLHttpRequest not available');
17405
+ return;
17406
+ }
17407
+ // Crear wrapper que agrega el header
17408
+ window.XMLHttpRequest = function () {
17409
+ const xhr = new RealXHR();
17410
+ const originalOpen = xhr.open;
17411
+ const originalSend = xhr.send;
17412
+ let isCollectorRequest = false;
17413
+ xhr.open = function (method, url, ...args) {
17414
+ const urlString = typeof url === 'string' ? url : url.toString();
17415
+ isCollectorRequest = urlString.includes('collector.jaak.ai');
17416
+ return originalOpen.apply(this, [method, url, ...args]);
17417
+ };
17418
+ xhr.send = function (...args) {
17419
+ if (isCollectorRequest) {
17420
+ this.setRequestHeader('Authorization', `Bearer ${AUTH_TOKEN}`);
17421
+ }
17422
+ return originalSend.apply(this, args);
17423
+ };
17424
+ return xhr;
17425
+ };
17426
+ // Copiar propiedades del constructor original
17427
+ for (const prop in RealXHR) {
17428
+ if (RealXHR.hasOwnProperty(prop)) {
17429
+ window.XMLHttpRequest[prop] = RealXHR[prop];
17430
+ }
17431
+ }
17432
+ // También interceptar fetch por si el SDK lo usa en lugar de XHR
17433
+ const originalFetch = window.fetch;
17434
+ window.fetch = function (input, init) {
17435
+ const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
17436
+ if (url.includes('collector.jaak.ai')) {
17437
+ const headers = new Headers(init?.headers || {});
17438
+ headers.set('Authorization', `Bearer ${AUTH_TOKEN}`);
17439
+ init = {
17440
+ ...init,
17441
+ headers: headers,
17442
+ };
17443
+ }
17444
+ return originalFetch.call(this, input, init);
17445
+ };
17446
+ // Deshabilitar sendBeacon globalmente porque no soporta headers personalizados
17447
+ navigator.sendBeacon = function () {
17448
+ return false; // Retornar false fuerza al SDK a usar XHR/Fetch como fallback
17449
+ };
17450
+ }
19954
17451
  class TracingService {
19955
17452
  provider = null;
19956
17453
  tracer = null;
@@ -19962,7 +17459,6 @@ class TracingService {
19962
17459
  customerId;
19963
17460
  tenantId;
19964
17461
  environment;
19965
- propagateTraceHeaderCorsUrls;
19966
17462
  enableAutoInstrumentation;
19967
17463
  spanProcessor = null;
19968
17464
  parser;
@@ -19977,19 +17473,43 @@ class TracingService {
19977
17473
  this.customerId = config.customerId;
19978
17474
  this.tenantId = config.tenantId;
19979
17475
  this.environment = config.environment || 'production';
19980
- this.propagateTraceHeaderCorsUrls = config.propagateTraceHeaderCorsUrls || [];
19981
17476
  this.enableAutoInstrumentation = config.enableAutoInstrumentation ?? false; // Default to false
19982
17477
  this.parser = new UAParser();
19983
17478
  }
19984
17479
  initialize() {
19985
17480
  try {
17481
+ // Instalar interceptores de autenticación ANTES de crear el exporter
17482
+ installAuthInterceptors();
19986
17483
  // Create OTLP exporter
19987
- const exporter = new OTLPTraceExporter({
17484
+ const baseExporter = new OTLPTraceExporter({
19988
17485
  url: this.collectorUrl,
19989
17486
  headers: {
19990
17487
  'Content-Type': 'application/json',
17488
+ 'Authorization': `Bearer ${AUTH_TOKEN}`,
19991
17489
  },
17490
+ // @ts-ignore - useSendBeacon no está en los tipos pero es soportada
17491
+ useSendBeacon: false,
19992
17492
  });
17493
+ // Wrap exporter to log export attempts
17494
+ const exporter = {
17495
+ export: (spans, resultCallback) => {
17496
+ if (this.debug) {
17497
+ console.log('[TracingService] 📤 Exporting', spans.length, 'spans to collector');
17498
+ }
17499
+ baseExporter.export(spans, (result) => {
17500
+ if (result.code !== 0) {
17501
+ console.error('[TracingService] ❌ Export failed:', result);
17502
+ }
17503
+ resultCallback(result);
17504
+ });
17505
+ },
17506
+ shutdown: async () => {
17507
+ return baseExporter.shutdown();
17508
+ },
17509
+ forceFlush: async () => {
17510
+ return baseExporter.forceFlush();
17511
+ },
17512
+ };
19993
17513
  // Create batch span processor for each exporter
19994
17514
  this.spanProcessor = new BatchSpanProcessor(exporter, {
19995
17515
  maxQueueSize: 100,
@@ -19997,24 +17517,10 @@ class TracingService {
19997
17517
  scheduledDelayMillis: 5000,
19998
17518
  exportTimeoutMillis: 30000,
19999
17519
  });
20000
- // Create resource attributes
20001
- const resourceAttributes = {
20002
- [ATTR_SERVICE_NAME]: this.serviceName,
20003
- [ATTR_SERVICE_VERSION]: this.serviceVersion,
20004
- 'deployment.environment': this.environment,
20005
- };
20006
- if (this.customerId) {
20007
- resourceAttributes['customer.id'] = this.customerId;
20008
- }
20009
- if (this.tenantId) {
20010
- resourceAttributes['tenant.id'] = this.tenantId;
20011
- }
20012
- // Create tracer provider with resource
17520
+ // Create tracer provider with span processor in constructor
20013
17521
  this.provider = new WebTracerProvider({
20014
- // Resource will be added via span attributes since Resource class is not available
17522
+ spanProcessors: [this.spanProcessor],
20015
17523
  });
20016
- // Add span processor
20017
- this.provider.addSpanProcessor?.(this.spanProcessor);
20018
17524
  // Configure context manager (Zone.js for async context propagation)
20019
17525
  const contextManager = new ZoneContextManager();
20020
17526
  // Configure propagators (W3C Trace Context + B3 for compatibility)
@@ -20028,19 +17534,7 @@ class TracingService {
20028
17534
  this.tracer = trace.getTracer(this.serviceName, this.serviceVersion);
20029
17535
  // Initialize auto-instrumentation if enabled
20030
17536
  if (this.enableAutoInstrumentation) {
20031
- this.initializeAutoInstrumentation(resourceAttributes);
20032
- }
20033
- if (this.debug) {
20034
- console.log('[TracingService] Initialized successfully', {
20035
- collectorUrl: this.collectorUrl,
20036
- serviceName: this.serviceName,
20037
- serviceVersion: this.serviceVersion,
20038
- environment: this.environment,
20039
- customerId: this.customerId,
20040
- tenantId: this.tenantId,
20041
- autoInstrumentation: this.enableAutoInstrumentation,
20042
- propagateUrls: this.propagateTraceHeaderCorsUrls,
20043
- });
17537
+ this.initializeAutoInstrumentation();
20044
17538
  }
20045
17539
  }
20046
17540
  catch (error) {
@@ -20048,37 +17542,15 @@ class TracingService {
20048
17542
  // Don't throw - telemetry should fail silently in production
20049
17543
  }
20050
17544
  }
20051
- initializeAutoInstrumentation(resourceAttributes) {
17545
+ initializeAutoInstrumentation() {
20052
17546
  try {
20053
- // Auto-instrumentation is disabled by default to reduce noise
20054
- // Enable via config.enableAutoInstrumentation = true if needed
17547
+ // NOTE: XHR and Fetch instrumentation are disabled because we manually intercept
17548
+ // them to add authentication headers. Enabling them causes conflicts.
17549
+ // NOTE: DocumentLoadInstrumentation is disabled because it captures events that
17550
+ // occurred before the component initialized, and cannot use custom trace IDs.
17551
+ // Only enable user interaction instrumentation
20055
17552
  registerInstrumentations({
20056
17553
  instrumentations: [
20057
- // Fetch API instrumentation
20058
- new FetchInstrumentation({
20059
- propagateTraceHeaderCorsUrls: this.propagateTraceHeaderCorsUrls,
20060
- clearTimingResources: true,
20061
- applyCustomAttributesOnSpan: (span, _request, response) => {
20062
- // Add resource attributes to each span
20063
- Object.entries(resourceAttributes).forEach(([key, value]) => {
20064
- span.setAttribute(key, value);
20065
- });
20066
- // Add custom attributes
20067
- if (response && 'status' in response) {
20068
- span.setAttribute('http.response.status_code', response.status);
20069
- }
20070
- },
20071
- }),
20072
- // XMLHttpRequest instrumentation
20073
- new XMLHttpRequestInstrumentation({
20074
- propagateTraceHeaderCorsUrls: this.propagateTraceHeaderCorsUrls,
20075
- applyCustomAttributesOnSpan: (span) => {
20076
- // Add resource attributes to each span
20077
- Object.entries(resourceAttributes).forEach(([key, value]) => {
20078
- span.setAttribute(key, value);
20079
- });
20080
- },
20081
- }),
20082
17554
  // User interaction instrumentation (clicks, etc.)
20083
17555
  new UserInteractionInstrumentation({
20084
17556
  eventNames: ['click', 'submit'],
@@ -20087,13 +17559,8 @@ class TracingService {
20087
17559
  return element.tagName === 'BUTTON' || element.tagName === 'A' || element.tagName === 'FORM';
20088
17560
  },
20089
17561
  }),
20090
- // Document load instrumentation
20091
- new DocumentLoadInstrumentation(),
20092
17562
  ],
20093
17563
  });
20094
- if (this.debug) {
20095
- console.log('[TracingService] Auto-instrumentation enabled');
20096
- }
20097
17564
  }
20098
17565
  catch (error) {
20099
17566
  console.error('[TracingService] Failed to initialize auto-instrumentation:', error);
@@ -20184,19 +17651,24 @@ class TracingService {
20184
17651
  }
20185
17652
  startSpan(name, attributes) {
20186
17653
  if (!this.tracer) {
20187
- // Return a no-op span if tracer is not initialized
17654
+ console.warn('[TracingService] Tracer not initialized, returning no-op span');
20188
17655
  return trace.getTracer('noop').startSpan('noop');
20189
17656
  }
20190
17657
  try {
20191
17658
  let currentContext = context.active();
20192
- // If we have a session trace ID, create a span context with it
20193
- if (this.sessionTraceId) {
20194
- const spanContext = {
17659
+ // If we have a session trace ID and there's no active span, create a root span context
17660
+ if (this.sessionTraceId && !trace.getSpan(currentContext)) {
17661
+ // Create a valid span context for the custom trace ID
17662
+ const remoteSpanContext = {
20195
17663
  traceId: this.sessionTraceId,
20196
17664
  spanId: this.generateSpanId(),
20197
- traceFlags: 0x01, // Sampled
17665
+ traceFlags: TraceFlags.SAMPLED,
17666
+ isRemote: true,
20198
17667
  };
20199
- currentContext = trace.setSpanContext(currentContext, spanContext);
17668
+ // Create a non-recording span with the custom trace context
17669
+ const remoteSpan = trace.wrapSpanContext(remoteSpanContext);
17670
+ // Set this span in the context so child spans inherit the trace ID
17671
+ currentContext = trace.setSpan(currentContext, remoteSpan);
20200
17672
  }
20201
17673
  // Get device info
20202
17674
  const deviceInfo = this.getDeviceInfo();
@@ -20253,20 +17725,15 @@ class TracingService {
20253
17725
  }
20254
17726
  }
20255
17727
  endSpan(span) {
20256
- if (!span)
17728
+ if (!span) {
17729
+ console.warn('[TracingService] endSpan called with null/undefined span');
20257
17730
  return;
17731
+ }
20258
17732
  try {
20259
17733
  span.end();
20260
- if (this.debug) {
20261
- const spanContext = span.spanContext();
20262
- console.log('[TracingService] Ended span', {
20263
- traceId: spanContext.traceId,
20264
- spanId: spanContext.spanId,
20265
- });
20266
- }
20267
17734
  }
20268
17735
  catch (error) {
20269
- console.error('[TracingService] Failed to end span:', error);
17736
+ console.error('[TracingService] Failed to end span:', error);
20270
17737
  }
20271
17738
  }
20272
17739
  addSpanEvent(span, name, attributes) {
@@ -20291,9 +17758,6 @@ class TracingService {
20291
17758
  code: SpanStatusCode.ERROR,
20292
17759
  message: error.message,
20293
17760
  });
20294
- if (this.debug) {
20295
- console.log('[TracingService] Recorded exception:', error);
20296
- }
20297
17761
  }
20298
17762
  catch (err) {
20299
17763
  console.error('[TracingService] Failed to record exception:', err);
@@ -20330,6 +17794,26 @@ class TracingService {
20330
17794
  this.endSpan(span);
20331
17795
  }
20332
17796
  }
17797
+ async traceAsync(name, fn, attributes) {
17798
+ return this.trace(name, fn, attributes);
17799
+ }
17800
+ /**
17801
+ * Flush all pending spans to the collector
17802
+ * Call this when capture/process is complete to send all traces
17803
+ */
17804
+ async flush() {
17805
+ try {
17806
+ if (!this.spanProcessor) {
17807
+ console.warn('[TracingService] No span processor available to flush');
17808
+ return;
17809
+ }
17810
+ await this.spanProcessor.forceFlush();
17811
+ }
17812
+ catch (error) {
17813
+ console.error('[TracingService] ❌ Failed to flush spans:', error);
17814
+ throw error;
17815
+ }
17816
+ }
20333
17817
  async cleanup() {
20334
17818
  try {
20335
17819
  if (this.spanProcessor) {
@@ -20339,9 +17823,6 @@ class TracingService {
20339
17823
  if (this.provider) {
20340
17824
  await this.provider.shutdown();
20341
17825
  }
20342
- if (this.debug) {
20343
- console.log('[TracingService] Cleaned up successfully');
20344
- }
20345
17826
  }
20346
17827
  catch (error) {
20347
17828
  console.error('[TracingService] Failed to cleanup:', error);
@@ -20978,8 +18459,8 @@ class LicenseValidationService {
20978
18459
  static ENVIRONMENT_URLS = {
20979
18460
  dev: 'https://api.dev.jaak.ai',
20980
18461
  qa: 'https://api.qa.jaak.ai',
20981
- staging: 'https://api-staging.jaak.ai',
20982
- prod: 'https://api.jaak.ai',
18462
+ sandbox: 'https://api.sandbox.jaak.ai',
18463
+ prod: 'https://services.api.jaak.ai',
20983
18464
  };
20984
18465
  constructor(environment = 'prod') {
20985
18466
  this.baseUrl = LicenseValidationService.ENVIRONMENT_URLS[environment];
@@ -21271,6 +18752,10 @@ const JaakStamps = class {
21271
18752
  this.detectionService = this.serviceContainer.getDetectionService();
21272
18753
  this.tracingService = this.serviceContainer.getTracingService();
21273
18754
  this.metricsService = this.serviceContainer.getMetricsService();
18755
+ // Set the custom trace ID if provided via prop
18756
+ if (this.tracingService && this.traceId) {
18757
+ this.tracingService.setSessionTraceId(this.traceId);
18758
+ }
21274
18759
  // Record component initialization
21275
18760
  if (this.tracingService) {
21276
18761
  const span = this.tracingService.startSpan('component.initialize', {
@@ -22213,7 +19698,7 @@ const JaakStamps = class {
22213
19698
  isCapturing: false
22214
19699
  };
22215
19700
  const cameraInfo = this.cameraInfoWithAutofocus;
22216
- return (index.h("div", { key: '69b36b10f1a790caa352acd5e149fe012ddebd3d', class: "detector-container" }, !this.licenseValid && this.licenseError && (index.h("div", { key: 'b96d8b52f6bb366b1d6239922a95b100befa5735', class: "license-error-container" }, index.h("div", { key: '58fb20b1acae97631c35730ed395acf9fa583df2', class: "license-error-card" }, index.h("svg", { key: 'f2726621e000bad3c62b1106778bb50e32ece973', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, index.h("path", { key: '18a51f219cdc93f717867f61502c55b35d250532', d: "M12 22C12 22 20 18 20 12V5L12 2L4 5V12C4 18 12 22 12 22Z", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), index.h("path", { key: '0f157178a69c10590dd55f55c2223fdef31c2569', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), index.h("circle", { key: '0352746bef8e2e5a6be0c3868406005aae574a71', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), index.h("h2", { key: 'c63de740aa94503f1cf5e1cd1b366b11bc3253b3', class: "license-error-title" }, "Licencia Requerida"), index.h("p", { key: 'e36cefd08b510fc38f326de557ffc16425a0b324', class: "license-error-message" }, this.licenseError), index.h("p", { key: 'c77c6545b5186f7fb77a414120d3f6f5ba4a45f0', class: "license-error-help" }, "Contacte a soporte: ", index.h("a", { key: 'bef70b41a7ec454bed38c4162ce3cafc02c81071', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), index.h("div", { key: '7fd679252453474021494c8dac3ec44da60b40eb', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (index.h("div", { key: '369edcb3d7fcaa18059ae89f340f5e65bd0f0785', class: "video-container" }, index.h("video", { key: '88a67cf2451ebd53cb4fa709d34d11c7fa98cfc9', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), index.h("div", { key: 'd309664c7a9e64f33dd45e0925f27768483b6795', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index$1) => (index.h("div", { key: index$1, class: "detection-box", style: {
19701
+ return (index.h("div", { key: 'a52b452a7aef6574a5e4b74a88c7bd3f9d45fd15', class: "detector-container" }, !this.licenseValid && this.licenseError && (index.h("div", { key: '18a99579e0b74ceb2cf1c4c3e21a864d2ec7d944', class: "license-error-container" }, index.h("div", { key: '3431722f4f47824c172a5b6f3a2ad9bd3bf377f2', class: "license-error-card" }, index.h("svg", { key: 'bf3854de3ba865a58c5c91cfd7a85d3d725be0df', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, index.h("path", { key: '209e3a2a22333ec90e102a7156eb644b529f47c7', d: "M12 22C12 22 20 18 20 12V5L12 2L4 5V12C4 18 12 22 12 22Z", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), index.h("path", { key: '7b0dc1cd29a9055e552885b23f4537c19932556d', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), index.h("circle", { key: '8ea686ebfb31a5744303f313fd104c03c02a5472', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), index.h("h2", { key: '7e0ec3ec23b80176cbec9c706999746d62486f3c', class: "license-error-title" }, "Licencia Requerida"), index.h("p", { key: '261a91e2c20feb09319dc4f319fb79611cc36a46', class: "license-error-message" }, this.licenseError), index.h("p", { key: '2e3cc8da0f4a8ebfd52db469b0f0900514d1d7f8', class: "license-error-help" }, "Contacte a soporte: ", index.h("a", { key: '283eea87e2f69dce1ea7376e3a63fed780633499', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), index.h("div", { key: 'b4227ed25a4fb4d953c753671d27ac8c931a435f', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (index.h("div", { key: 'cb33431cf6992f6e7466273406f729c42c1cbcdb', class: "video-container" }, index.h("video", { key: 'b44befd61ad616fd36fe1e98fd089a2443bc65b6', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), index.h("div", { key: '8cee95ddab5f771a87d43fa434a3ba0c241d2f3e', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index$1) => (index.h("div", { key: index$1, class: "detection-box", style: {
22217
19702
  position: 'absolute',
22218
19703
  left: `${box.x}px`,
22219
19704
  top: `${box.y}px`,
@@ -22222,9 +19707,9 @@ const JaakStamps = class {
22222
19707
  border: '2px solid #32406C',
22223
19708
  pointerEvents: 'none',
22224
19709
  boxSizing: 'border-box'
22225
- } })))), this.isMaskReady && (index.h("div", { key: 'fbfc808e22ec640ddd9e34d52fab476d7a9becc1', class: "overlay-mask" }, index.h("div", { key: '40846a04d852bbcc2ac6c4a0ca356adae1c67765', class: "card-outline" }, index.h("div", { key: '452fe1786b67d0f9194e5d03ad2aaee08868a5fd', class: "side side-top" }), index.h("div", { key: 'a462c388ea55cd022b9616571f0012bd5eb380d4', class: "side side-right" }), index.h("div", { key: 'bfa2232443e23f2e72f009c62f7a866b9ff1b084', class: "side side-bottom" }), index.h("div", { key: '581746eca6fde6340d78e8ab48d6e21d17e7dfd3', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '8e57ac550ea3718322ba954682f93239acbabc78', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '81cfab68789796d901afadc895d28f398e8c15cf', class: "back-capture-section" }, index.h("div", { key: 'd80455bd916c2d7ac47eb0ce3c62b0e5efbe4dff', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (index.h("button", { key: 'c6d427cb32ecfb1ff40150d39f1d8ad7565f7156', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (index.h("span", { key: 'cb57aec75ff91f2887fa258bd79b8efb98614d13', class: "button-spinner" })), "Capturar Reverso")), index.h("button", { key: 'c76f356a34fcbc790ebe2d900ed61cc4a6a02e28', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (index.h("span", { key: 'd8fe69623902a5f41587f630552ef28a352733c6', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
19710
+ } })))), this.isMaskReady && (index.h("div", { key: '00a749ad234294695d9a292911b41fdacafd219a', class: "overlay-mask" }, index.h("div", { key: 'e344df8a709fca5225985ccc9f8def75ddbd393c', class: "card-outline" }, index.h("div", { key: '2dcae9e414f2b7131397d49a3d5ecabfc7cd5eb8', class: "side side-top" }), index.h("div", { key: '48ac3f06fa4a2c83741df378719911f682811caa', class: "side side-right" }), index.h("div", { key: '238a3269b2a12d528e8a1889d3109ee319c7fd88', class: "side side-bottom" }), index.h("div", { key: 'b02eec6c102d7e9fb03ef24dfce7c75e081ff1c4', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '15588129ca8027a6ec1c81d70001142986966826', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: 'f15fd9bddc20c54afcca7be79c3cf2f9ee2b74f7', class: "back-capture-section" }, index.h("div", { key: 'e3284e1301840a9555857fa879de9f4ca91dc21b', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (index.h("button", { key: '8508d13e117deb3b223308497b1db976643b86f2', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (index.h("span", { key: '99bd464541d9ee8589bc11e937c5ad6bca9d95c8', class: "button-spinner" })), "Capturar Reverso")), index.h("button", { key: '3de5f0a142f9dfdfe4578c0fcbe004bb5fe94c56', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (index.h("span", { key: '268ce949bf5155b3729298f23eea0d7ec15b3590', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
22226
19711
  ? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
22227
- : 'Saltar reverso')))), captureState.isVideoActive && (index.h("div", { key: '08f4037c20b4dfed59553a7f29474940f5f3eb49', class: "camera-controls" }, index.h("button", { key: 'e873835d5d6587b19eb5e61e0073e4992fe115b6', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (index.h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (index.h("div", { key: '8fca7e29f868570bb99dd2d09ca7da807656dad0', class: "camera-selector-dropdown" }, index.h("div", { key: 'abfac31042d3b362c094a297429e0272dabb2511', class: "camera-selector-header" }, index.h("span", { key: 'ffcd0e3c262aa86c431617568c1070548d88f38a' }, "Seleccionar C\u00E1mara"), index.h("button", { key: '8351be02ccbfa818cab352a37a29d2cd5bfd53ef', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), index.h("div", { key: 'b42d7a5855ec2f76bc105f7b03369b3d4c950762', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (index.h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (index.h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: 'cf3ca9fe1d626320ad2653a3db44cd86e998bcdf', class: "device-info" }, index.h("small", { key: '9b908dc6e759f1a5311b068dba10428ebd22cdc3' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '9aa48412eaac0b2adf19f1defb3bc835ab031d9f', class: "manual-capture-section" }, index.h("button", { key: '1828e293ae4e544b00d0dd17a86401ff0436de37', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (index.h("span", { key: 'bbea1d654f80e537ff6616920fb6a2cb410e55f0', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (index.h("div", { key: '532f72395868ecf58bef350aed4da4e4fc0fa13c', class: "capture-animation" })), captureState.showFlipAnimation && (index.h("div", { key: '555cbc7504660b722f23389899956cf979a27e6c', class: "flip-animation" }, index.h("div", { key: 'e5de939b02cfb65697c70f265492f1f30f75c771', class: "id-card-icon" }), index.h("div", { key: '35867c2fbdf463d5b28f0bd3a58313d0d6f15e7b', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (index.h("div", { key: '4a96d077e993012ed333384219ba27d5a68787ea', class: "success-animation" }, index.h("div", { key: '836809412d0674a0061aadaaa7c712a22f8770da', class: "check-icon" }), index.h("div", { key: 'd541dbdfa548760b196dd09dc44c3d1a6af8093c', class: "success-text" }, "\u00A1Proceso completado!"))), index.h("div", { key: '89a9d99fbeedff1bbcf723ba13d551c3290150fe', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (index.h("div", { key: 'f100984baef7602ea40cea9bb74b4c84fd1f6ed9', class: "status-spinner" })), index.h("div", { key: 'ad4161c71f438174117e306e5084bfdff3d18dce', class: "status-content" }, index.h("div", { key: '26310245b58f331075dd344a6497e90631d5d78c', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (index.h("div", { key: 'f739148b45f7d43a3015cca3de8efc8b71d3d5e4', class: "status-description" }, this.currentStatus.description)))), this.debug && (index.h("div", { key: '0397b96391dff4f0662c913068a62c714df168bf', class: "performance-monitor" }, index.h("div", { key: 'da3c3638b3c048a425bf691b29755762ad40aa5c', class: "performance-expanded" }, index.h("div", { key: '467f5e2dc207cfd9fd31cef24d434452b3247c5f', class: "metrics-row" }, index.h("div", { key: 'e620d9017402317e09ec554bf933a4f5a5d0b0de', class: "metric-compact" }, index.h("span", { key: '8d21fa081bbf3ec7ad54f553b60b0a64ae41fb01', class: "metric-label" }, "FPS"), index.h("span", { key: '8e99113c7b93c128d7e390900a63f16c5b9483c0', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), index.h("div", { key: '67927ff90810b0c4d6717d520ad50142d5d6c0dd', class: "metric-compact" }, index.h("span", { key: '4810964d65c18248f01aff90dca36d732b80a05c', class: "metric-label" }, "MEM"), index.h("span", { key: 'e82ff493a2bc1d3baf60c1f638154e9208d0991f', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), index.h("div", { key: '6ef07b3f3dc4c3d991f4bbae34e902a9efc1a359', class: "metrics-row" }, index.h("div", { key: 'b5eed3b30cb99d4d088a05494cda2eff0ba393cc', class: "metric-compact" }, index.h("span", { key: '52749839a61316b90f424b0920f4c82c6683dd29', class: "metric-label" }, "INF"), index.h("span", { key: '8509cf19af19b6ac2efc7ab68ac46d9d053c5464', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), index.h("div", { key: '34a8540d0840056a525a7afc35ca956943b527af', class: "metric-compact" }, index.h("span", { key: 'bdc2d8cd180b92ee7b84c8372aba5c2f33289669', class: "metric-label" }, "FRAME"), index.h("span", { key: '481a0735a5b7258fecdc1bab65a4d4018cc0e7b9', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), index.h("div", { key: '7b5aa0a6fe97970f09db23103f7f0301fd98c4f8', class: "metrics-row" }, index.h("div", { key: '1c691159409e021176557904a1ceec05abc329e1', class: "metric-compact" }, index.h("span", { key: '5ab6c25d80548aa4e63c79ecf88d2386393ae707', class: "metric-label" }, "DET"), index.h("span", { key: '7641532633bc764d4dc209ba7e1827a2f3f59338', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), index.h("div", { key: 'feee52f464eeb965eeadfd944a65e94600591ed5', class: "metric-compact" }, index.h("span", { key: 'c7962650a7bf1bc86f8c733eb01d5eeb9e08d37e', class: "metric-label" }, "RATE"), index.h("span", { key: '337529444c8e7bacb47d686d0be33721a066eebe', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), index.h("div", { key: '49717c49e5316bfe10690733c5bf07eb0475a3e2', class: "watermark" }, index.h("img", { key: 'f86ff4364196627bb3f169e5ee1c14696126cd68', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" }))))));
19712
+ : 'Saltar reverso')))), captureState.isVideoActive && (index.h("div", { key: 'bb5c00ad882c303d8a2b6ddc79c9d5b27ff9824e', class: "camera-controls" }, index.h("button", { key: '7d231b550b58a8336f125a1a7fe7235c8bb3d7dd', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (index.h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (index.h("div", { key: '95d1e0d0937f7ef821ff3ad167cd42e25fd1c87f', class: "camera-selector-dropdown" }, index.h("div", { key: 'e42219e5895c82f40c559c27c4f80f3145fc0a0e', class: "camera-selector-header" }, index.h("span", { key: '544a6fb2e08211ab6c44b0bfb281124bee318fae' }, "Seleccionar C\u00E1mara"), index.h("button", { key: '7c4a71243278491ee7dbcc7ab2564bc7e92f5da3', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), index.h("div", { key: 'c9d24e0bd906d20370214fdfd24ae91abfda98e1', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (index.h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (index.h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: '8c2e1d2ed02bc55c84f3f726e5be577686d0f32d', class: "device-info" }, index.h("small", { key: '142410a86e4f819b96ffc9573816994351588a3e' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '48c33b2d6c8c80d18fba6e5f454faaa24c28fbd9', class: "manual-capture-section" }, index.h("button", { key: 'e3d5bfe9ef8b8f16bf669b66bce4e7a500113798', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (index.h("span", { key: 'f50640fe4308c765011e6ed175528920228df5e7', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (index.h("div", { key: '080ab315293fa1fe5b1d97aa2511a2ffe2b013f4', class: "capture-animation" })), captureState.showFlipAnimation && (index.h("div", { key: 'b062c546af50b799bb1fb7dda07b3ffa601c4bac', class: "flip-animation" }, index.h("div", { key: 'f7162dc31673c7db1d8e03a658a722a3d323b28e', class: "id-card-icon" }), index.h("div", { key: 'd950952b480342d80d37df5c48031d72be4ac01a', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (index.h("div", { key: 'bd576fd28065aa712e42636c5fd0e3566d26cc25', class: "success-animation" }, index.h("div", { key: '6ca5c24510df790bd1c955c5e2936909c4767560', class: "check-icon" }), index.h("div", { key: '3420164eacddbe1a9aa0a181528ba0be7683af56', class: "success-text" }, "\u00A1Proceso completado!"))), index.h("div", { key: '8ec2b295b233e7bb8ab0cc1c183adedd4e3c7e04', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (index.h("div", { key: '97c8e7e6219984673ebc631da111c17bf72a83cb', class: "status-spinner" })), index.h("div", { key: '7ca06c48f295892ff77eceff6245891ef7d9dd5e', class: "status-content" }, index.h("div", { key: '08056c7ec8fd66d23e0b6714c08aeccc092cf46a', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (index.h("div", { key: '1e32ca14de53cc2f105822ed5a58e691918b307b', class: "status-description" }, this.currentStatus.description)))), this.debug && (index.h("div", { key: 'c25022d9aadd37ead9ae7d1cf7c7d916cdeb9cc1', class: "performance-monitor" }, index.h("div", { key: 'f0f99c7e820532432ba64726ef0c2aeabeb3309f', class: "performance-expanded" }, index.h("div", { key: 'e839e90c9cb0f33068ac3311e41914aa52610149', class: "metrics-row" }, index.h("div", { key: '9f74f4877a048e63f542f2df54f569f79d6f8bd0', class: "metric-compact" }, index.h("span", { key: '21ec7255706d6fb2cfec035c4be92295ee0216b6', class: "metric-label" }, "FPS"), index.h("span", { key: 'c8be17f3dc752304bf6b7fd9746f11783f7ff6ca', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), index.h("div", { key: '79187257ea30ead7fb41534a94272a3a855e050b', class: "metric-compact" }, index.h("span", { key: 'cc53dc282c1fe4234217207c2085fa2be06a5458', class: "metric-label" }, "MEM"), index.h("span", { key: '032002ff63b3a2349b34833668fed8d6337e2063', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), index.h("div", { key: 'e628febd5bbfb9f593e029b10827635ddd0344fb', class: "metrics-row" }, index.h("div", { key: 'b2fe558bab709ff6b6781648b13ebc66238f3298', class: "metric-compact" }, index.h("span", { key: 'd7d816aff11503657781f8ebe9cb5f0f07c7279e', class: "metric-label" }, "INF"), index.h("span", { key: '3d735d092b5b39d0e96f4ac59b3bf2acde739fab', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), index.h("div", { key: '9a83fd4fe43e8a3760aaea1f134c3101b8757681', class: "metric-compact" }, index.h("span", { key: '8136ab82b50230537f19cd58ed2da0956d291287', class: "metric-label" }, "FRAME"), index.h("span", { key: '6221cc10edff8c4b0e4034a3734deb548416a3e6', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), index.h("div", { key: 'a31bad44d5c2c5fd5417ed82589c0f103bba1d32', class: "metrics-row" }, index.h("div", { key: '1441d11e0d83b3b44dfa963e415c3074691eb4f2', class: "metric-compact" }, index.h("span", { key: '9fe5643129aa7a842f75644b6f71b1ff80993f1b', class: "metric-label" }, "DET"), index.h("span", { key: '0604065a3867e71a745bfb4e804c7e96048cb70e', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), index.h("div", { key: 'daff0fede819f2b59a4ddb83560dc53f6151c2c9', class: "metric-compact" }, index.h("span", { key: '75a55c4a4e36b98af3620866ec6f7842b9ef81f7', class: "metric-label" }, "RATE"), index.h("span", { key: '61776c3fd4c3200d5e18cc28d917c538b282625a', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), index.h("div", { key: '4092c684ee3a148ec40e266fd16a718f2c2f2f52', class: "watermark" }, index.h("img", { key: 'd7bae6157d22675f8b71dbf1afdf345374398c82', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" }))))));
22228
19713
  }
22229
19714
  // Utility methods
22230
19715
  updateDetectionBoxes(boxes) {
@@ -22732,7 +20217,7 @@ const JaakStamps = class {
22732
20217
  catch (error) {
22733
20218
  }
22734
20219
  }
22735
- completeProcess(skippedBack = false) {
20220
+ async completeProcess(skippedBack = false) {
22736
20221
  this.stateManager.updateCaptureState({
22737
20222
  step: 'completed',
22738
20223
  showSuccessAnimation: true
@@ -22747,6 +20232,15 @@ const JaakStamps = class {
22747
20232
  ...capturedImages,
22748
20233
  timestamp: new Date().toISOString()
22749
20234
  };
20235
+ // Flush all traces to collector before emitting capture completed
20236
+ if (this.tracingService) {
20237
+ try {
20238
+ await this.tracingService.flush();
20239
+ }
20240
+ catch (error) {
20241
+ console.error('[my-component] Failed to flush traces:', error);
20242
+ }
20243
+ }
22750
20244
  this.captureCompleted.emit(finalImages);
22751
20245
  setTimeout(() => {
22752
20246
  this.stateManager.updateCaptureState({ showSuccessAnimation: false });