Giter Site home page Giter Site logo

aws-rum-web's People

Contributors

adebayor123 avatar alolita avatar amazon-auto avatar ckifer avatar codermpl avatar dependabot[bot] avatar direddyz avatar gethinwebster avatar haotiantest avatar hv-rruiz avatar jhackshaw avatar limhjgrace avatar madhuhc avatar maniator avatar omerfarukaslan avatar paulmowat avatar phekmat avatar piwysocki avatar ps863 avatar qhanam avatar qiah avatar shubhsheth avatar vasireddy99 avatar wadim avatar williazz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aws-rum-web's Issues

Console Errors When window.localStorage Unavailable (iFrame)

I'm trying to use RUM in an iFrame which has no access to the window.localStorage value.

Environment:
Angular 10.21 in an iFrame (on the same domain)
RUM 1.2.1

I'm injecting the script into head dynamically with the following code,

loadRum() {
    (window as any).AwsRumClient = {
      q: [],
      n: 'cwr',
      i: environment.rum.cwrId,
      v: '1.0.0',
      r: 'us-west-2',
      c: {
        sessionSampleRate: 1,
        guestRoleArn: environment.rum.guestRoleArn,
        identityPoolId: environment.rum.identityPoolId,
        endpoint: 'https://dataplane.rum.us-west-2.amazonaws.com',
        telemetries: ['performance', 'errors', 'http'],
        allowCookies: true,
        enableXRay: false,
        cookieAttributes: {
          domain: window.location.hostname,
          path: '/',
          sameSite: 'None',
          secure: true,
        },
      },
    };
    const x = (window as any).AwsRumClient;
    (window as any).cwr = (a, p) => {
      x.q.push({ a, p });
    };
    const z = document.createElement('script');
    z.async = true;
    z.src = 'https://client.rum.us-east-1.amazonaws.com/1.2.1/cwr.js';
    document.head.insertBefore(z, document.getElementsByTagName('script')[0]);
  }

Is it possible to add support for storing authentication tokens in cookies when localStorage is not supported (ie in an iFrame)? This doesn't affect usability of RUM, but it does lead to a series of console errors, since the reject in https://github.com/aws-observability/aws-rum-web/blob/main/src/dispatch/Authentication.ts#L71 is not caught.

The affected lines are

polyfills.cf07b70d8bd3c7d2eb81.js:1 Error: Uncaught (in promise): [object Undefined]
    at Z (polyfills.cf07b70d8bd3c7d2eb81.js:1:12260)
    at polyfills.cf07b70d8bd3c7d2eb81.js:1:11343
    at cwr.js:formatted:1941:44
    at new O (polyfills.cf07b70d8bd3c7d2eb81.js:1:14095)
    at e.<anonymous> (cwr.js:formatted:1939:40)
    at cwr.js:formatted:1905:39
    at Object.next (cwr.js:formatted:1918:22)
    at cwr.js:formatted:1823:45
    at new O (polyfills.cf07b70d8bd3c7d2eb81.js:1:14095)
    at _ (cwr.js:formatted:1800:20)
n.onUnhandledError @ polyfills.cf07b70d8bd3c7d2eb81.js:1
polyfills.cf07b70d8bd3c7d2eb81.js:1 Error: Uncaught (in promise): [object Undefined]
    at Z (polyfills.cf07b70d8bd3c7d2eb81.js:1:12260)
    at Z (polyfills.cf07b70d8bd3c7d2eb81.js:1:11791)
    at polyfills.cf07b70d8bd3c7d2eb81.js:1:11343
    at c (cwr.js:formatted:1817:30)
    at cwr.js:formatted:1823:17
    at new O (polyfills.cf07b70d8bd3c7d2eb81.js:1:14095)
    at _ (cwr.js:formatted:1800:20)
    at e.AnonymousCredentialsProvider (cwr.js:formatted:1936:28)
    at e.<anonymous> (cwr.js:formatted:1928:45)
    at cwr.js:formatted:1905:39
n.onUnhandledError @ polyfills.cf07b70d8bd3c7d2eb81.js:1
2polyfills.cf07b70d8bd3c7d2eb81.js:1 Uncaught (in promise) undefined
invoke @ polyfills.cf07b70d8bd3c7d2eb81.js:1
run @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
invokeTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
runTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
m @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Promise.then (async)
k @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Z @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Z @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
c @ cwr.js:formatted:1817
(anonymous) @ cwr.js:formatted:1823
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
_ @ cwr.js:formatted:1800
AnonymousCredentialsProvider @ cwr.js:formatted:1936
(anonymous) @ cwr.js:formatted:1928
(anonymous) @ cwr.js:formatted:1905
(anonymous) @ cwr.js:formatted:1918
(anonymous) @ cwr.js:formatted:1823
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
_ @ cwr.js:formatted:1800
ChainAnonymousCredentialsProvider @ cwr.js:formatted:1926
e.setAwsCredentials @ cwr.js:formatted:4231
e.initDispatch @ cwr.js:formatted:5485
e @ cwr.js:formatted:5432
e.initCwr @ cwr.js:formatted:5927
(anonymous) @ cwr.js:formatted:5900
(anonymous) @ cwr.js:formatted:5838
(anonymous) @ cwr.js:formatted:5851
(anonymous) @ cwr.js:formatted:5756
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Rn @ cwr.js:formatted:5733
e.init @ cwr.js:formatted:5888
(anonymous) @ cwr.js:formatted:5945
(anonymous) @ cwr.js:formatted:5946
(anonymous) @ cwr.js:formatted:5947
2polyfills.cf07b70d8bd3c7d2eb81.js:1 Uncaught (in promise) undefined
invoke @ polyfills.cf07b70d8bd3c7d2eb81.js:1
run @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
invokeTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
runTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
m @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Promise.then (async)
k @ polyfills.cf07b70d8bd3c7d2eb81.js:1
scheduleTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
scheduleTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
scheduleMicroTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
P @ polyfills.cf07b70d8bd3c7d2eb81.js:1
then @ polyfills.cf07b70d8bd3c7d2eb81.js:1
catch @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ cwr.js:formatted:1928
(anonymous) @ cwr.js:formatted:1905
(anonymous) @ cwr.js:formatted:1918
(anonymous) @ cwr.js:formatted:1823
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
_ @ cwr.js:formatted:1800
ChainAnonymousCredentialsProvider @ cwr.js:formatted:1926
e.setAwsCredentials @ cwr.js:formatted:4231
e.initDispatch @ cwr.js:formatted:5485
e @ cwr.js:formatted:5432
e.initCwr @ cwr.js:formatted:5927
(anonymous) @ cwr.js:formatted:5900
(anonymous) @ cwr.js:formatted:5838
(anonymous) @ cwr.js:formatted:5851
(anonymous) @ cwr.js:formatted:5756
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Rn @ cwr.js:formatted:5733
e.init @ cwr.js:formatted:5888
(anonymous) @ cwr.js:formatted:5945
(anonymous) @ cwr.js:formatted:5946
(anonymous) @ cwr.js:formatted:5947
polyfills.cf07b70d8bd3c7d2eb81.js:1 Uncaught (in promise) undefined
invoke @ polyfills.cf07b70d8bd3c7d2eb81.js:1
run @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
invokeTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
runTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
m @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Promise.then (async)
k @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Z @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Z @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
c @ cwr.js:formatted:1817
(anonymous) @ cwr.js:formatted:1823
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
_ @ cwr.js:formatted:1800
AnonymousStorageCredentialsProvider @ cwr.js:formatted:1952
invoke @ polyfills.cf07b70d8bd3c7d2eb81.js:1
run @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
invokeTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
runTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
m @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Promise.then (async)
k @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Z @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ cwr.js:formatted:1941
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ cwr.js:formatted:1939
(anonymous) @ cwr.js:formatted:1905
(anonymous) @ cwr.js:formatted:1918
(anonymous) @ cwr.js:formatted:1823
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
_ @ cwr.js:formatted:1800
AnonymousCredentialsProvider @ cwr.js:formatted:1936
(anonymous) @ cwr.js:formatted:1928
(anonymous) @ cwr.js:formatted:1905
(anonymous) @ cwr.js:formatted:1918
(anonymous) @ cwr.js:formatted:1823
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
_ @ cwr.js:formatted:1800
ChainAnonymousCredentialsProvider @ cwr.js:formatted:1926
e.setAwsCredentials @ cwr.js:formatted:4231
e.initDispatch @ cwr.js:formatted:5485
e @ cwr.js:formatted:5432
e.initCwr @ cwr.js:formatted:5927
(anonymous) @ cwr.js:formatted:5900
(anonymous) @ cwr.js:formatted:5838
(anonymous) @ cwr.js:formatted:5851
(anonymous) @ cwr.js:formatted:5756
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Rn @ cwr.js:formatted:5733
e.init @ cwr.js:formatted:5888
(anonymous) @ cwr.js:formatted:5945
(anonymous) @ cwr.js:formatted:5946
(anonymous) @ cwr.js:formatted:5947
Show 24 more frames
polyfills.cf07b70d8bd3c7d2eb81.js:1 Uncaught (in promise) undefined
invoke @ polyfills.cf07b70d8bd3c7d2eb81.js:1
run @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
invokeTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
runTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
m @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Promise.then (async)
k @ polyfills.cf07b70d8bd3c7d2eb81.js:1
scheduleTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
scheduleTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
scheduleMicroTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
P @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Z @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Z @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
invokeTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
runTask @ polyfills.cf07b70d8bd3c7d2eb81.js:1
m @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Promise.then (async)
k @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Z @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ cwr.js:formatted:1941
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
(anonymous) @ cwr.js:formatted:1939
(anonymous) @ cwr.js:formatted:1905
(anonymous) @ cwr.js:formatted:1918
(anonymous) @ cwr.js:formatted:1823
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
_ @ cwr.js:formatted:1800
AnonymousCredentialsProvider @ cwr.js:formatted:1936
(anonymous) @ cwr.js:formatted:1928
(anonymous) @ cwr.js:formatted:1905
(anonymous) @ cwr.js:formatted:1918
(anonymous) @ cwr.js:formatted:1823
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
_ @ cwr.js:formatted:1800
ChainAnonymousCredentialsProvider @ cwr.js:formatted:1926
e.setAwsCredentials @ cwr.js:formatted:4231
e.initDispatch @ cwr.js:formatted:5485
e @ cwr.js:formatted:5432
e.initCwr @ cwr.js:formatted:5927
(anonymous) @ cwr.js:formatted:5900
(anonymous) @ cwr.js:formatted:5838
(anonymous) @ cwr.js:formatted:5851
(anonymous) @ cwr.js:formatted:5756
O @ polyfills.cf07b70d8bd3c7d2eb81.js:1
Rn @ cwr.js:formatted:5733
e.init @ cwr.js:formatted:5888
(anonymous) @ cwr.js:formatted:5945
(anonymous) @ cwr.js:formatted:5946
(anonymous) @ cwr.js:formatted:5947
Show 20 more frames
4polyfills.cf07b70d8bd3c7d2eb81.js:1 Uncaught (in promise) undefined

Ability to set the awsSigV4 to use API Gateway as the Service Scope

Hi all!

I wanted to ask if it's possible to scope the awsSigV4 object w/in the DataPlaneClient to something other than rum. The service attribute only allows rum.

I've noticed in the documentation it's possible to set an endpoint to an API gateway proxy. However the permissions won't quite work with the client to only give the client the ability to call the API because this signature is scoped to rum.

We wanted to set the guest role arn to have execute-api permissions to our API. Then from there we can forward it along to RUM.

Thank you!

Is there a maximum length for a recorded error message?

When recording an error, is there a maximum length of the message from the Error that can successfully be recorded?

For example:

try {
  throw new Error("A message that might be very long...");
} catch (e)
  awsRum.recordError(e);
}

The reason I'm asking is that I have encountered errors recorded to CloudWatch RUM simply as Empty or no message. One reason could have been that the error message was too long, but I can't find any relevant documentation around this.

bug: Cannot find module 'aws-rum-web' or its corresponding type declarations.

Hi, I'm getting the following error when importing AwsRum and AwsRumConfig on v1.13.2:

Type error: Cannot find module 'aws-rum-web' or its corresponding type declarations.

Workaround has been to downgrade to v1.12.0.
Very weird because I can see them being exported in the index.d.ts in node_modules. :/

Anyone else have this problem?

"CWR: Failed to retrieve credentials from STS" error thrown by aws-rum-web

Hello,

We've noticed an error thrown by aws-rum-web client itself in our AWS RUM monitoring (occurred only once so far):

Screenshot 2022-09-19 at 18 32 44

The error itself is thrown here:

throw new Error('CWR: Failed to retrieve credentials from STS');

Are there any actions we could take in order to avoid this error? Moreover, would it be possible to include the actual exception being thrown along with the Failed to retrieve credentials from STS error message?

X-Ray trace subsegment name can be invalid

The web client HTTP plugins use the hostname of the callee as the subsegment name. For example, the subsegment name of fetch(https://dataplane.rum.us-east-1.amazonaws.com/appmonitors/abc123) would be dataplane.rum.us-east-1.amazonaws.com. When there is no hostname (e.g., if the URL is specified using a relative path like /appmonitors/abc123), or if the hostname cannot be read, then the empty string "" is used.

This is problematic because the empty string is an invalid subsegment name in X-Ray. When the subsegment name is an empty string, X-Ray will not ingest the trace segment.

This task is to ensure the subsegment name is never empty. If the URL is a relative path, then window.location.hostname should be used.

Potential slowdown of site due to listening for global keydown events

In the VirtualPageLoadTimer plugin on line 81 it has a keydown event, which if a user holds down a key it will get hit every ms until they list their finger from the keyboard.

I think there are two options to fix this issue:

  1. debounce the event for keydown
    Down side to this is that we may not get the most accurate information, and the debounce method still gets hit every ms
  2. figure out a better option for detecting a page interaction without hitting the same method n number of times per second

bump aws-sdk dependencies

Used aws-sdk packages are old. Can be updated to latest version

"@aws-sdk/client-rum": "^3.202.0"
"@aws-sdk/fetch-http-handler": "^3.201.0"
"@aws-sdk/protocol-http": "^3.201.0"
"@aws-sdk/signature-v4": "^3.201.0"
"@aws-sdk/util-hex-encoding": "^3.201.0",

Cache cwr.js file from CDN

I'm currently trying out the CloudWatch RUM product. One thing I noticed today is that the https://client.rum.us-east-1.amazonaws.com/1.0.2/cwr.js file is served without any Cache-Control headers:

๎‚ฐ curl -v https://client.rum.us-east-1.amazonaws.com/1.0.2/cwr.js
*   Trying 65.8.233.80:443...
* Connected to client.rum.us-east-1.amazonaws.com (65.8.233.80) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=client.rum.us-east-1.amazonaws.com
*  start date: Nov 12 00:00:00 2021 GMT
*  expire date: Dec 11 23:59:59 2022 GMT
*  subjectAltName: host "client.rum.us-east-1.amazonaws.com" matched cert's "client.rum.us-east-1.amazonaws.com"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f98b6811000)
> GET /1.0.2/cwr.js HTTP/2
> Host: client.rum.us-east-1.amazonaws.com
> user-agent: curl/7.77.0
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< content-type: application/javascript
< content-length: 114311
< last-modified: Tue, 23 Nov 2021 00:51:47 GMT
< x-amz-version-id: mQ3VEzOswAhdeQEPxFrH_CGxedkxk4zn
< accept-ranges: bytes
< server: AmazonS3
< date: Sat, 18 Dec 2021 12:39:43 GMT
< etag: "0dfa77fbb42f338ac9955897e9f55641"
< vary: Accept-Encoding
< x-cache: Hit from cloudfront
< via: 1.1 30ea845097208edbc19305c535a5be99.cloudfront.net (CloudFront)
< x-amz-cf-pop: DEN52-C1
< x-amz-cf-id: Vo5ZG0zegHb7QUxU2Iu4PwiIXRBZv3_ibZd5Ack_ZENrsWNgB2kHJQ==
< age: 38372

This (rightfully) triggers warnings from Lighthouse:

Screen Shot 2021-12-18 at 4 20 24 PM

As you can see from the screenshot, Google Analytics caches for 2 hours but is still flagged. Since the URL for the CloudWatch asset has a version embedded (1.0.2), it seems like this should be safe to cache for at least 24 hours, if not more.

Getting approval requests for deployments

Hello - I seem to still get approval requests for deployments in this repo even though I'm not at AWS anymore. I couldn't find a reference to my user in this repo, so not sure why but would be good if that could be sorted. Thanks.

/cc @Aneurysm9

Incorrect type definition for methods in XhrPlugin

Hi folks,

Thanks for developing aws-rum-web. It is a great library with a promising roadmap.

When I install aws-rum-web via yarn in a Vue application that uses Typescript 4.4 I get the following errors in dev server (yarn run serve which also results in a build failure via yarn run build.

ERROR in /cw_rum/node_modules/aws-rum-web/dist/cjs/plugins/event-plugins/XhrPlugin.d.ts(61,19):
61:19 Property 'patches' in type 'XhrPlugin' is not assignable to the same property in base type 'MonkeyPatched<XMLHttpRequest, "open" | "send">'.
  Type '(MonkeyPatch<XMLHttpRequest, "open"> | { nodule: XMLHttpRequest; name: "send"; wrapper: () => (original: any) => (this: XMLHttpRequest) => void; })[]' is not assignable to type 'MonkeyPatch<XMLHttpRequest, "open" | "send">[]'.
    Type 'MonkeyPatch<XMLHttpRequest, "open"> | { nodule: XMLHttpRequest; name: "send"; wrapper: () => (original: any) => (this: XMLHttpRequest) => void; }' is not assignable to type 'MonkeyPatch<XMLHttpRequest, "open" | "send">'.
      Type 'MonkeyPatch<XMLHttpRequest, "open">' is not assignable to type 'MonkeyPatch<XMLHttpRequest, "open" | "send">'.
        Type '"open" | "send"' is not assignable to type '"open"'.
          Type '"send"' is not assignable to type '"open"'.
    59 |     constructor(config?: PartialHttpPluginConfig);
    60 |     protected onload(): void;
  > 61 |     protected get patches(): (MonkeyPatch<XMLHttpRequest, "open"> | {
       |                   ^
    62 |         nodule: XMLHttpRequest;
    63 |         name: "send";
    64 |         wrapper: () => (original: any) => (this: XMLHttpRequest) => void;
Version: typescript 4.4.4

I believe it is due to an incorrect type being inferred from this line.

I think updating the patches method in XhrPlugin to what's shown below should fix the issue. I was able to fix the issue by directly editing the type definition file to match the type used below.

protected get patches() {
    return [
        {
            nodule: XMLHttpRequest.prototype,
            name: 'send' as const,
            wrapper: this.sendWrapper
        },
        {
            nodule: XMLHttpRequest.prototype,
            name: 'open' as const,
            wrapper: this.openWrapper
        }
    ] as MonkeyPatch<XMLHttpRequest, 'send' | 'open'>[];
}

This issue currently blocks the usage of aws-rum-web in Vue/Typescript applications. Let me know if that isn't the case and if it is due to something in my setup.

Packages of importance in my setup:

  • Vue: 2.6.11
  • Typescript: 4.4.4
  • AWS Rum Web: 1.8.2
  • Node: 12.16.3

Thanks!

feat: consider accepting the navigator.userAgent string in the dataplane API

Hello ๐Ÿ‘‹

I'm implementing RUM monitoring for a library that's deployed on a number of websites. For this use-case, the final bundle size is of critical importance. I noticed that RUM is bundling ua-parser-js (approx 6kb gzipped) to obtain information about the navigator. Unfortunately this adds too much weight for me to include within the performance budget for my library.

Could the RUM dataplane API accept the raw user agent string as a metadata property, instead of parsing this information into separate fields on the client-side?

Internet Explorer support

Hello! I am trying to implement AWS RUM in my react application and it works really fine on Chrome but it does not work properly on Internet Explorer. Comparing to the Chrome I see that the application on IE does not fire any calls to the AWS. My suspicious is that IE does not support fetch which cwr script uses to communicate with AWS I believe. I use React 16.3.1 and IE 21H2. I pasted my snippet into public/index.html. Is there any possibility to use AWS RUM in Internet Explorer? Does AWS RUM support IE at all?

feat: Support setting userId and sessionId manually

I am working on adding CloudWatch RUM to a web app. Our users will authenticate with AWS Identity Center (IDC) which assigns each user a UUID already. I'd like to use that same UUID as the userId RUM instead of letting RUM generate a new UUID for me. Having consistent userIds will make it easier to connect RUM data with our backend events. We could pass in the IDC user ID as event metadata but it makes sifting through data more confusing and error prone.

Passing in user and session IDs could look like:

const config: AwsRumConfig = {
  userId: 'bd33b2a2-4b14-4ea6-aaeb-ee85c2062f5d',
  sessionId: '40af9b9a-6fa2-45f8-a437-67d2566380d9'
};

Enforce strict type checks with TypeScript

Strict type checks in TypeScript gives stronger guarantees about types, but are not currently enforced.

This task is to (1) update tsconfig.json to include "strict": true in compilerOptions and (2) fix any TypeScript compiler errors with the new configuration.

Provide option to disable monkey-patching of global methods and allow flexibility in configuring http clients.

Hey, really appreciate the efforts to simplify the initial setup experience but I'm having a couple of issues with the current implementation.

Specific Issues

In my case I would like to instrument an application with http telemetry enabled but I'm faced with a couple of different challenges.

  1. The remote service will sometimes return non-error response code that contain error objects that should be reported to RUM.
  2. The local client is built to handle certain classes of http errors (notably 403s) with a retry mechanism but there is no clean way to catch these errors and handle them appropriately.
  3. Certain error responses contain information that should be made available as annotations and metadata in X-Ray but the current implementation doesn't provide a way to enrich those fields.

Proposed Features

  1. Allow an option to disable monkey-patching of fetch and instead expose the instrumented client on the AwsRum instance.
  2. Allow a fetch API compatible function to be passed as the default http client in the CWR configuration object. Currently this could technically be achieved by monkey-patching fetch before initializing CWR web client, but that is far from ideal.
  3. Allow instrumentation of a fetch client in the local scope. This should allow application developers to instrument each service for their own requirements.
  4. Provide a mechanism for extending the annotations and metadata in an X-Ray segment.

It's not clear if you are accepting contributions, particularly those extending the public API of the web client. If you are I'd be happy to implement some of these features myself.

Ignore errors with matching pattern configuration please.

Expecting:

{
          sessionSampleRate: 1,
          guestRoleArn:
            'arn:aws:iam::xxxxxxxx',
          identityPoolId: 'us-west-xxxxxxxxx',
          endpoint: 'https://dataplane.rum.us-west-2.amazonaws.com',
          telemetries: ['performance', 'errors', 'http'],
          allowCookies: true,
          enableXRay: true,
          pageIdFormat: 'PATH_AND_HASH',
/////// if the following configuration matches an error then ignore it.
          ignoreErrors: [
              /ResizeObserver loop limit exceeded/g,  // <---------- Focus here please.
              /Script error\./g,  // <---------- Focus here please.
          ]
},

"CWR: Failed to retrieve Cognito identity" error thrown by aws-rum-web

Hello,

First of all - thank you for building CloudWatch RUM, looking forward to seeing how this project will evolve.

We just noticed a following issue in our DataDog (occurred only once so far):
Screenshot 2022-09-14 at 11 59 55

Are there any actions we could take in order to avoid this error? Moreover, would it be possible to include the actual exception being thrown along with the Failed to retrieve Cognito identity error message?

[BUG] Javascript snippet error with <script> tags outside of <head> in Chrome

Certain chrome extensions inject script tags in document outside and above head tags. While this doesn't feel like something RUM should concern itself with it has caused issues sending metrics while using the JS snippet in Chrome.

Extension example: this extension injects a script via document.createElement('script') which inserts outside and above the head tag.

This results in:
image
when attempting to send metrics to RUM.

Running document.getElementsByTagName('script')[0]; during a debug session in the middle of the RUM script results in:
image

The easiest way to get around this happening to other customers (even if other chrome extensions don't behave this way) is to have the rum script injected as the first script in head rather than document. Not sure if this change would have any other implications.

AWS RUM Endpoint

Is it possible to obtain the Endpoint URL programmatically or does it need to be computed?

For example I have Terraform deploying a Cloudwatch RUM and I want to output the data the user needs to configure the Client code with and I can easily obtain the parameters for guestRoleARN and identityPoolID but it appears endpoint needs to be computed. Is this really the case?

Include domain as dimension in HttpStatusCodeCount metric

Could we get the domain, host or hostname added as a dimension to the HttpStatusCodeCount metric. Most pages only make requests to a fixed number of domains, so the cardinality of this dimension should reasonable. This would let us filter the metric based on the domain the request go to.

We could do this with a metricFilter on the logs, but that is a pain. Wanting to see your failures broken down by domain seems like a pretty common use case.

I see status and file.type as dimensions already. Those can conceivably have a cardinality in the hundreds, so the domain should be less than that.

See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-metrics.html

Moving a tab to the background inflates LCP

The LCP measure uses a PerformanceObserver. As PerformanceObservers don't run in the background, if a user visits a page and minimizes / changes browser tab before the LCP is measured then the LCP value will be the time the browser tab is brought back to the foreground

Error filtering doesn't filter errors caused by browser extensions

Error ignore feature doesn't filter out errors caused by browser extensions. such as @moz-extension and chrome-extension.

Using the error handler function like this:

export const rumErrorHandler = (
  errorEvent: ErrorEvent | PromiseRejectionEvent
): boolean => {
  if (!(errorEvent instanceof ErrorEvent)) {
    return false;
  }
  const errorPatterns = [
    /chrome-extension/,
    /moz-extension/,
    /ResizeObserver loop/,
  ];

  return errorPatterns.some(
    (errorPattern) =>
      errorPattern.test(errorEvent.error?.stack) ||
      errorPattern.test(errorEvent.filename) ||
      errorPattern.test(errorEvent.message)
  );
};

In addition to this issue, that would be also great to be able to filter out 4XX errors.

Thank you.

@aws-sdk/querystring-builder is not correctly marked as a dependency.

Which web client version did you detect this bug with?

v1.13.3

What environment (build systems, module system, and framework) did you detect this bug with?

TypeScript v5.0.2, Webpack v4.46.0, ECMAScript modules (ESM) and React v18.2.0

Is your web application a single page application (SPA) or multi page application (MPA)?

None

Please provide your web client configuration

{
allowCookies: true,
endpoint: "https://dataplane.rum.us-west-2.amazonaws.com",
guestRoleArn: "arn:aws:iam::000000000000:role/RUM-Monitor-us-west-2-000000000000-00xx-Unauth",
identityPoolId: "us-west-2:00000000-0000-0000-0000-000000000000",
sessionSampleRate: 1,
telemetries: ['errors', 'performance', 'http']
}

Please describe the bug/issue

Wrt #328, the issue still exist in latest version. kindly release tag a new version so the fix is available.

Resource handler returned message: "null

Raising this issue here because I don't know how else I would reach the RUM team.

When I try to create a RUM monitor via an L1 CDK construct, CloudFormation outputs the following error.

Resource handler returned message: "null (Service: Rum, Status Code: 403, Request ID: 25882675-8906-45e6-8494-2bb0d62bdb28)" (RequestToken: 4aab9635-1c07-613e-52ae-34085dd4f896, HandlerErrorCode: AccessDenied)

I have admin permission when executing cdk deploy.

Is there more info to this than just "null that I can find anywhere? Also checked if there are any CW logs, but without success.

The CloudFormation stack is afterwards in ROLLBACK_COMPLETE, but I can see that the Cogito identity pool and the CW RUM app have been created. I have tried this multiple times, and every time made sure that there is no existing identity pool and no CW RUM app. The same code seems to work in the account of another team, but not in ours. I'm running out of ideas what to try.

Below is the CDK code we use, with [email protected], [email protected], and [email protected]:

import { Stack } from "aws-cdk-lib";
import { CfnIdentityPool, CfnIdentityPoolRoleAttachment } from "aws-cdk-lib/aws-cognito";
import { FederatedPrincipal, PolicyDocument, PolicyStatement, Role } from "aws-cdk-lib/aws-iam";
import { CfnAppMonitor } from "aws-cdk-lib/aws-rum";
import { Construct } from "constructs";

export interface RumProps {
    /**
     * Provide a domain that will be allowed to send telemetry data to the Real
     * User Monitoring agent
     */
    readonly topLevelDomain: string;
    /**
     * The name for the App Monitor that will be created
     *
     * @unique
     */
    readonly appMonitorName: string;
}

/**
 * The RUM custom resource can be used to setup Real User Monitoring using AWS
 *
 * The resource itself creates all the required infrastructure.
 * Adapted from https://blog.simonireilly.com/posts/cloudwatch-rum-end-to-end-monitoring
 *
 * @example
 * const rum = new Rum(this, "SiteRum", {
 *   topLevelDomain: "*.s3-website-eu-west-1.amazonaws.com",
 *   appMonitorName: "canary-stack-rum",
 * });
 *
 */
export class Rum extends Construct {
    protected unauthenticatedRumRole: Role;

    readonly appMonitor: CfnAppMonitor;
    readonly topLevelDomain: string;
    readonly appMonitorName: string;
    readonly identityPool: CfnIdentityPool;

    constructor(scope: Construct, id: string, props: RumProps) {
        super(scope, id);
        this.topLevelDomain = props.topLevelDomain;
        this.appMonitorName = props.appMonitorName;

        this.identityPool = this.createIdentityPool();
        this.unauthenticatedRumRole = this.createRumRole();
        this.appMonitor = this.initializeRum();
    }

    private initializeRum() {
        this.createRoleAttachment();
        return this.createApplicationMonitor();
    }

    private createIdentityPool() {
        return new CfnIdentityPool(this, "RumAppIdentityPool", {
            allowUnauthenticatedIdentities: true,
        });
    }

    private createRumRole() {
        // See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-get-started-authorization.html
        return new Role(this, "UnauthenticatedRumRole", {
            assumedBy: new FederatedPrincipal(
                "cognito-identity.amazonaws.com",
                {
                    StringEquals: {
                        "cognito-identity.amazonaws.com:aud": this.identityPool.ref,
                    },
                    "ForAnyValue:StringLike": {
                        "cognito-identity.amazonaws.com:amr": "unauthenticated",
                    },
                },
                "sts:AssumeRoleWithWebIdentity",
            ),
            inlinePolicies: {
                RUMPutBatchMetrics: new PolicyDocument({
                    statements: [
                        new PolicyStatement({
                            actions: ["rum:PutRumEvents"],
                            resources: [
                                Stack.of(this).formatArn({
                                    service: "rum",
                                    resource: "appmonitor",
                                    resourceName: this.appMonitorName,
                                }),
                            ],
                        }),
                    ],
                }),
            },
        });
    }

    private createRoleAttachment() {
        new CfnIdentityPoolRoleAttachment(this, "RumAppRoleAttachment", {
            identityPoolId: this.identityPool.ref,
            roles: {
                unauthenticated: this.unauthenticatedRumRole.roleArn,
            },
        });
    }

    private createApplicationMonitor() {
        return new CfnAppMonitor(this, "RumAppMonitor", {
            name: this.appMonitorName,
            domain: this.topLevelDomain,
            appMonitorConfiguration: {
                allowCookies: true,
                enableXRay: false,
                sessionSampleRate: 1,
                telemetries: ["errors", "performance", "http"],
                identityPoolId: this.identityPool.ref,
                guestRoleArn: this.unauthenticatedRumRole.roleArn,
            },
        });
    }
}

Custom session attributes do not get sent randomly for some sessions and/or events

Version: 1.12.0.

We use RUM to track # of unique users that visit our website. We add a custom session attribute of a SHA-256 hash of the user alias at run time after their identity has been verified.

We notice that for some users, either

  • Their sessions do not have this attribute at all, or
  • Some events do not have this attribute even though earlier AND later events (based on interaction level) do

This behaviour seems to exist for all browser types, and there doesn't seem to be a specific pattern to when these issues occur.

In our service:

const addUserAliasHash = async (alias: string) => {
  if (cwrClient !== null) {
    const textAsBuffer = new TextEncoder().encode(alias);
    const hashBuffer = await window.crypto.subtle.digest('SHA-256', textAsBuffer);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const userAliasHash = hashArray.map((b) => b.toString(16)
      .padStart(2, '0'))
      .join('');
    cwrClient.addSessionAttributes({ userAliasHash });
  }
};

In our bootstrap:

useEffect(() => {
  const { alias } = getUserIdentityState;
  CloudWatchRumService.addUserAliasHash(alias)
}, [ getUserIdentityState ]);

architecture: don't require authentication to post metrics

When a new user visits my site, CW RUM kicks off a series of steps before sending metrics: the browser obtains an anonymous identity from the Identity Pool, fetches a token for the identity, assumes role via STS, and stashes the credentials in localstorage.

Once an identity is obtained, the client then performs cryptography (sigv4) on every metrics payload before sending it over the wire.

Initially I thought that the credentials obtained from Cognito were used to establish a tracking session, but looking at the code, the generated user ID in the cwr_u cookie, and the session ID in the session cookie are locally generated UUIDs, separate to the Cognito Identity.

Typically RUM solutions are fire-and-forget, not requiring coordination between the collector endpoint and the client. Instead of credentials, the origin URL, device fingerprint (user agent etc) and the monitor ID are sent to the endpoint.

Could you consider an architecture where the collector endpoints are unauthenticated, and take care of any required AWS service authorisation internally?

Client side libraries should aim to do the least amount of work possible, in the fewest bytes.

Unit tests failing with Node.js 16

GitHub is updating Node.js to version 16 in all OS images.

Several unit test suites and unit tests fail when run with Node.js 16:

  • Jest worker encountered 4 child process exceptions, exceeding retry limit
    • CognitoIdentityClient.test.ts
    • BeaconHttpHandler.test.ts
    • StsClient.test.ts
    • Authentication.test.ts
    • CommandQueue.test.ts
  • when a TypeError is thrown then the plugin records the name, message and stack

To reproduce, run npm run test with Node.js 16.

Out of box set-up fails with an uncaught exception when an existing Cognito IDP is used

Hi,

I'm setting up aws-rum-web via npm into a React Typescript project that has an existing Cognito user pool.

Steps so far:

  1. npm i aws-rum-web
  2. In AWS Console, I followed the bouncing ball to configure a RUM application and pointed it to an existing Cognito user pool + identity pool
  3. I added a policy to my "auth" and "unauth" roles in my Cognito IDP with the action rum:PutRumEvents
  4. I copied the generated JS into my app
  5. I've adjusted CSP headers to allow the traffic
  6. I've read the READMEs and TROUBLESHOOTING docs

When I run the app, I get this error:

Uncaught (in promise) Error: CWR: Failed to retrieve credentials from STS: TypeError: Cannot read properties of undefined (reading 'split')
    at StsClient.eval (StsClient.js?0019:98:1)
    at step (StsClient.js?0019:43:1)
    at Object.eval [as next] (StsClient.js?0019:24:46)
    at fulfilled (StsClient.js?0019:15:43)

This is caused by not properly handling an STS error payload, with the root cause to this being at Cognito with something-something basic auth flow. What I see happening is this:

  1. cognito-identity is called and returns an error such as "Basic flow not enabled" (there are two variants, see below)
  2. sts is called next with a payload containing WebIdentityToken: undefined, so it returns "The ID Token provided is not a valid JWT."
  3. The JS in StsClient.eval() doesn't correctly parse this response and generates the above error, and suppresses the actual error

The root error to this is about basic auth flow, which I see is part of Cognito Identity Pools.

  • If I don't enable Basic Auth Flow, I get the error "Basic (classic) flow is not enabled, please use enhanced flow"
  • If I do enable it, I instead get the error "Basic (classic) flow is not supported with RoleMappings, please use enhanced flow"

I've read the troubleshooting guide which talks to this, and I've also read open issue 172 where that user is in a similar position. I've also read of people using proxies, and that'd be great if there's an example I can run with.

However, while open issue 172 is asking you to implement the enhanced flow, all I'm after is for the out-of-box experience to work. I figure it works on your machine, so I'm wondering what I've done wrong, or what I need to do in Cognito in order to get this all working?

Many thanks, Scott

`@aws-sdk/querystring-builder` is not correctly marked as a dependency.

It is used in src/dispatch/BeaconHttpHandler.ts, which causes errors when using Plug-n-Play build tooling:

Module not found: Error: Can't resolve '@aws-sdk/querystring-builder' in '/home/runner/work/.../.../.yarn/cache/aws-rum-web-npm-1.12.0-d1cba678f0-d2387b42c7.zip/node_modules/aws-rum-web/dist/es/dispatch'

I believe this can be solved as simply as adding "@aws-sdk/querystring-builder": "^3.0.0" to package.json's dependencies list.

Add log level support

We've found that recordError is a useful replacement for custom client error logging. However to completely replace what we have now we'd need support for other log levels, e.g. info, warn.

This could be provided by a recordLog or recordEvent command that supports arbitrary logging. Is this something that would be considered in scope for the rum client?

[Bug]: Fetch plugin fetches multiple identities before starting

Which web client version did you detect this bug with?

v1.13.6

What environment (build systems, module system, and framework) did you detect this bug with?

Remix v1.14.3, Typescript v5.0.4, ECMAScript modules (ESM) and React v18.2.0, aws-rum-web installed as JavaScript Module

Is your web application a single page application (SPA) or multi page application (MPA)?

SPA

Please provide your web client configuration

{
  "allowCookies":true,
  "enableXRay":true,
  "endpoint":"https://dataplane.rum.eu-north-1.amazonaws.com",
  "guestRoleArn":"arn:aws:iam::account:role/stage-stack-App-AppMonitorUnauthentic1O1WJSN77WOS0",
  "identityPoolId":"eu-north-1:4447b5b0-ebdd-4a73-ace3-ede974be41c3",
  "sessionSampleRate":1,
  "telemetries":[
    "errors",
    "performance",
    ["http", { "addXRayTraceIdHeader": true }]
  ]
}

Please describe the bug/issue

There seems to be some kind of race condition, if the application is installed as a JS module, whereby multiple identities are loaded when starting up the application. I believe this should happen only once. If the script is injected via the script tag, it works as expected with the same config.

image

image

`PageAttributes` is not exported from root.

recordPageView accepts a PageAttributes parameter, but the PageAttributes type is not exported by aws-rum-web.

In order to either (1) wrap this function or (2) initialize the payload ahead of time, the PageAttributes type needs to be exposed.

Example 1: wrapping the function

function myRecordPageView(payload: PageAttributes | string): void {
  myCustomHandler(payload);
  cwr.recordPageView(payload);
}

Example 2: Initializing the payload ahead of time.

const payload: PageAttributes = {
  pageId: 'test-page-id',
  pageAttributes: {},
};

for (const [key, value] of Object.entries(window.location)) {
  if (typeof value !== 'string') {
    continue;
  }
  payload.pageAttributes[key] = value;
}

cwr.recordPageView(payload);

Both scenarios would be unblocked by allowing:

import type { PageAttributes } from 'aws-rum-web';

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.