Skip to content

Commit f6b5495

Browse files
committed
Release braintree-web 3.132.0 source
1 parent 22a3baa commit f6b5495

File tree

7 files changed

+120
-5
lines changed

7 files changed

+120
-5
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# CHANGELOG
22

3+
## 3.132.0 (2025-10-16)
4+
5+
- API Latency Logging
6+
- Added FPTI logs to track the performance metrics
7+
38
## 3.131.0 (2025-10-15)
49

510
- Instant Verification

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "braintree-web",
3-
"version": "3.131.0",
3+
"version": "3.132.0",
44
"license": "MIT",
55
"main": "src/index.js",
66
"private": true,

src/client/client.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,12 @@ Client.prototype.request = function (options, callback) {
356356
}
357357

358358
requestOptions.url = baseUrl + options.endpoint;
359-
requestOptions.sendAnalyticsEvent = function (kind) {
360-
analytics.sendEvent(self, kind);
359+
requestOptions.sendAnalyticsEvent = function (kind, extraFields) {
360+
if (extraFields) {
361+
analytics.sendEventPlus(self, kind, extraFields);
362+
} else {
363+
analytics.sendEvent(self, kind);
364+
}
361365
};
362366

363367
self._request(requestOptions, function (err, data, status) {

src/client/request/ajax-driver.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,63 @@ var DefaultRequest = require("./default-request");
1111

1212
var MAX_TCP_RETRYCOUNT = 1;
1313
var TCP_PRECONNECT_BUG_STATUS_CODE = 408;
14+
var PAYPAL_HERMES_CREATE_PAYMENT_RESOURCE_PATTERN =
15+
/\/client_api\/v1\/paypal_hermes\/create_payment_resource/;
16+
var MERCHANT_ID_PATTERN = /\/merchants\/[A-Za-z0-9_-]+\/client_api/;
1417

1518
function requestShouldRetry(status) {
1619
return !status || status === TCP_PRECONNECT_BUG_STATUS_CODE;
1720
}
1821

22+
function sendApiLatencyAnalytics(url, analyticsStartTime, options) {
23+
var domain, path, cleanedPath, parsedUrl;
24+
var analyticsConnectionStartTime, analyticsRequestStartTime, analyticsEndTime;
25+
var finalStartTime;
26+
var entries, entry;
27+
28+
try {
29+
parsedUrl = new URL(url);
30+
domain = parsedUrl.hostname;
31+
path = parsedUrl.pathname;
32+
// eslint-disable-next-line no-unused-vars
33+
} catch (e) {
34+
domain = (url.match(/^https?:\/\/([^\/]+)/) || [])[1] || "";
35+
path = (url.match(/^https?:\/\/[^\/]+(\/.*)$/) || [])[1] || url;
36+
}
37+
cleanedPath = path.replace(MERCHANT_ID_PATTERN, "");
38+
39+
finalStartTime = analyticsStartTime;
40+
analyticsEndTime = Date.now();
41+
42+
if (
43+
typeof window !== "undefined" &&
44+
window.performance &&
45+
window.performance.getEntriesByName
46+
) {
47+
entries = window.performance.getEntriesByName(url);
48+
if (entries && entries.length > 0) {
49+
entry = entries[entries.length - 1];
50+
analyticsConnectionStartTime = entry.connectStart
51+
? Math.round(entry.connectStart)
52+
: null;
53+
analyticsRequestStartTime = entry.requestStart
54+
? Math.round(entry.requestStart)
55+
: null;
56+
finalStartTime = Math.round(entry.startTime);
57+
analyticsEndTime = Math.round(entry.responseEnd);
58+
}
59+
}
60+
61+
options.sendAnalyticsEvent("core.api-request-latency", {
62+
connectionStartTime: analyticsConnectionStartTime,
63+
domain: domain,
64+
endpoint: cleanedPath,
65+
endTime: analyticsEndTime,
66+
requestStartTime: analyticsRequestStartTime,
67+
startTime: finalStartTime,
68+
});
69+
}
70+
1971
function graphQLRequestShouldRetryWithClientApi(body) {
2072
var errorClass =
2173
!body.data &&
@@ -29,6 +81,7 @@ function graphQLRequestShouldRetryWithClientApi(body) {
2981

3082
function _requestWithRetry(options, tcpRetryCount, cb) {
3183
var status, resBody, ajaxRequest, body, method, headers, parsedBody;
84+
var analyticsStartTime = Date.now();
3285
var url = options.url;
3386
var graphQL = options.graphQL;
3487
var timeout = options.timeout;
@@ -80,6 +133,13 @@ function _requestWithRetry(options, tcpRetryCount, cb) {
80133
resBody = ajaxRequest.adaptResponseBody(parsedBody);
81134
status = ajaxRequest.determineStatus(req.status, parsedBody);
82135

136+
if (
137+
PAYPAL_HERMES_CREATE_PAYMENT_RESOURCE_PATTERN.test(url) &&
138+
options.sendAnalyticsEvent
139+
) {
140+
sendApiLatencyAnalytics(url, analyticsStartTime, options);
141+
}
142+
83143
if (status >= 400 || status < 200) {
84144
if (
85145
isGraphQLRequest &&

src/lib/constants.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,11 @@ module.exports = {
5656
"payment_ready_page_type",
5757
"payment_ready_session_id",
5858
"button_type",
59+
"connectionStartTime",
60+
"domain",
61+
"endpoint",
62+
"endTime",
63+
"requestStartTime",
64+
"startTime",
5965
],
6066
};

test/client/unit/request/ajax-driver.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,4 +577,44 @@ describe("AJAXDriver", () => {
577577
testContext.fakeXHR.onreadystatechange();
578578
});
579579
});
580+
581+
describe("API latency tracking", () => {
582+
afterEach(() => {
583+
server._routes = {};
584+
});
585+
586+
it("sends analytics event for create_payment_resource endpoint", (done) => {
587+
const sendAnalyticsEventSpy = jest.fn();
588+
589+
server.post(
590+
"/merchants/test/client_api/v1/paypal_hermes/create_payment_resource",
591+
{
592+
status: 200,
593+
body: '{"success":true}',
594+
}
595+
);
596+
597+
AJAXDriver.request(
598+
{
599+
url: "https://api.braintreegateway.com/merchants/test/client_api/v1/paypal_hermes/create_payment_resource",
600+
method: "POST",
601+
data: {},
602+
graphQL: testContext.fakeGraphQL,
603+
sendAnalyticsEvent: sendAnalyticsEventSpy,
604+
},
605+
() => {
606+
expect(sendAnalyticsEventSpy).toHaveBeenCalledWith(
607+
"core.api-request-latency",
608+
expect.objectContaining({
609+
domain: "api.braintreegateway.com",
610+
endpoint: "/v1/paypal_hermes/create_payment_resource",
611+
startTime: expect.any(Number),
612+
endTime: expect.any(Number),
613+
})
614+
);
615+
done();
616+
}
617+
);
618+
});
619+
});
580620
});

0 commit comments

Comments
 (0)