@adobe/spacecat-shared-utils 1.22.2 → 1.22.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/tracing-fetch.js +119 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-utils-v1.22.3](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.22.2...@adobe/spacecat-shared-utils-v1.22.3) (2024-11-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* proper http data for x-ray trace ([#427](https://github.com/adobe/spacecat-shared/issues/427)) ([4fa4d2d](https://github.com/adobe/spacecat-shared/commit/4fa4d2d417d51e911957e37df5136453dea521b2))
|
|
7
|
+
|
|
1
8
|
# [@adobe/spacecat-shared-utils-v1.22.2](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.22.1...@adobe/spacecat-shared-utils-v1.22.2) (2024-11-07)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/src/tracing-fetch.js
CHANGED
|
@@ -9,35 +9,140 @@
|
|
|
9
9
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
|
+
import { Request } from '@adobe/fetch';
|
|
12
13
|
import AWSXRay from 'aws-xray-sdk';
|
|
13
14
|
|
|
14
15
|
import { fetch as adobeFetch } from './adobe-fetch.js';
|
|
16
|
+
import { isNumber } from './functions.js';
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Creates a subsegment for a given hostname based on whether the parent segment is traced or not.
|
|
20
|
+
* @param {Object} parentSegment - The parent X-Ray segment.
|
|
21
|
+
* @param {string} hostname - The hostname to associate with the subsegment.
|
|
22
|
+
* @returns {Object} The created subsegment.
|
|
23
|
+
*/
|
|
24
|
+
const createSubsegment = (parentSegment, hostname) => (parentSegment.notTraced
|
|
25
|
+
? parentSegment.addNewSubsegmentWithoutSampling(hostname)
|
|
26
|
+
: parentSegment.addNewSubsegment(hostname));
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Sets the AWS X-Ray trace headers on the request object.
|
|
30
|
+
* @param {Request} request - The request object on which headers are set.
|
|
31
|
+
* @param {Object} parentSegment - The parent X-Ray segment.
|
|
32
|
+
* @param {Object} subSegment - The subsegment to include in the headers.
|
|
33
|
+
*/
|
|
34
|
+
const setTraceHeaders = (request, parentSegment, subSegment) => {
|
|
35
|
+
const effectiveParentSegment = parentSegment.segment || parentSegment;
|
|
36
|
+
request.headers.set(
|
|
37
|
+
'X-Amzn-Trace-Id',
|
|
38
|
+
`Root=${effectiveParentSegment.trace_id};Parent=${subSegment.id};Sampled=0`,
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Adds flags to the given subsegment based on the status code of the response.
|
|
44
|
+
* @param {Object} subSegment - The X-Ray subsegment to which flags are added.
|
|
45
|
+
* @param {number} status - The status code of the response.
|
|
46
|
+
*/
|
|
47
|
+
const setSubSegmentFlagsByStatusCode = (
|
|
48
|
+
subSegment,
|
|
49
|
+
status,
|
|
50
|
+
) => { /* eslint-disable no-param-reassign */
|
|
51
|
+
if (status === 429) {
|
|
52
|
+
subSegment.throttled = true;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (status >= 400 && status < 500) {
|
|
56
|
+
subSegment.error = true;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (status >= 500 && status < 600) {
|
|
60
|
+
subSegment.fault = true;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Adds request and response data to the given segment for AWS X-Ray tracing.
|
|
66
|
+
* @param {Object} segment - The X-Ray segment to which request and response data are added.
|
|
67
|
+
* @param {Request} request - The original request object.
|
|
68
|
+
* @param {Response} [response] - The response object (if available).
|
|
69
|
+
*/
|
|
70
|
+
const addFetchRequestDataToSegment = (
|
|
71
|
+
segment,
|
|
72
|
+
request,
|
|
73
|
+
response,
|
|
74
|
+
) => { /* eslint-disable no-param-reassign */
|
|
75
|
+
const { url, method } = request;
|
|
76
|
+
segment.http = {
|
|
77
|
+
request: { url, method },
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
if (!response) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
segment.http.response = {
|
|
85
|
+
status: response.status,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const contentLength = Number.parseInt(response.headers.get('content-length'), 10);
|
|
89
|
+
if (isNumber(contentLength)) {
|
|
90
|
+
segment.http.response.content_length = contentLength;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Adds error data to the given segment for AWS X-Ray tracing.
|
|
96
|
+
* @param {Object} subSegment - The X-Ray subsegment to which error data is added.
|
|
97
|
+
* @param {Request} request - The original request object.
|
|
98
|
+
* @param {Error} error - The error object.
|
|
99
|
+
*/
|
|
100
|
+
const handleSubSegmentError = (subSegment, request, error) => {
|
|
101
|
+
subSegment.addErrorFlag();
|
|
102
|
+
addFetchRequestDataToSegment(subSegment, request);
|
|
103
|
+
subSegment.addAnnotation('errorMessage', error.message);
|
|
104
|
+
subSegment.addAnnotation('errorStack', error.stack);
|
|
105
|
+
subSegment.close(error);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Performs a fetch request and adds AWS X-Ray tracing, including request/response tracking.
|
|
110
|
+
* @param {string} url - The URL for the request.
|
|
111
|
+
* @param {Object} options - Options to be passed to the fetch call.
|
|
112
|
+
* @returns {Promise<Response>} The response from the fetch request.
|
|
113
|
+
*/
|
|
114
|
+
export async function tracingFetch(url, options) {
|
|
17
115
|
const parentSegment = AWSXRay.getSegment();
|
|
18
116
|
|
|
19
117
|
if (!parentSegment) {
|
|
20
118
|
return adobeFetch(url, options);
|
|
21
119
|
}
|
|
22
120
|
|
|
23
|
-
const
|
|
24
|
-
const
|
|
121
|
+
const request = new Request(url, options);
|
|
122
|
+
const { hostname } = new URL(request.url);
|
|
123
|
+
const subSegment = createSubsegment(parentSegment, hostname);
|
|
25
124
|
|
|
26
|
-
|
|
27
|
-
subsegment.addAnnotation('url', url);
|
|
28
|
-
subsegment.addAnnotation('method', method);
|
|
125
|
+
subSegment.namespace = 'remote';
|
|
29
126
|
|
|
30
|
-
|
|
127
|
+
if (!parentSegment.noOp) {
|
|
128
|
+
setTraceHeaders(request, parentSegment, subSegment);
|
|
129
|
+
}
|
|
31
130
|
|
|
32
|
-
|
|
131
|
+
const capturedAdobeFetch = async () => {
|
|
132
|
+
let response = null;
|
|
133
|
+
try {
|
|
134
|
+
response = await adobeFetch(request);
|
|
135
|
+
} catch (e) {
|
|
136
|
+
handleSubSegmentError(subSegment, request, e);
|
|
137
|
+
throw e;
|
|
138
|
+
}
|
|
33
139
|
|
|
34
|
-
|
|
140
|
+
setSubSegmentFlagsByStatusCode(subSegment, response.status);
|
|
35
141
|
|
|
142
|
+
addFetchRequestDataToSegment(subSegment, request, response);
|
|
143
|
+
subSegment.close();
|
|
36
144
|
return response;
|
|
37
|
-
}
|
|
38
|
-
subsegment.addError(error);
|
|
39
|
-
subsegment.close();
|
|
145
|
+
};
|
|
40
146
|
|
|
41
|
-
|
|
42
|
-
}
|
|
147
|
+
return capturedAdobeFetch();
|
|
43
148
|
}
|