What do the keys in the '_performanceLogger' object of an XMLHttpRequest response mean? - reactjs

I am trying to measure download (and later upload) speed using Axios in React Native. My question's relate to the most appropriate way to do so, and understanding if the _performanceLogger in the response from XMLHttpRequest is accurate for this purpose. There surprisingly doesn't seem to be much out there about _performanceLogger ... Appreciate the help!
A MWE is:
import React from "react";
import axios from 'axios';
// Dummy API endpoint
let requestURL = 'https://jsonplaceholder.typicode.com/users/2'
// Getting timestamp immediately before request is started
var startTimestamp = (new Date()).getTime()
// Make request through Axios
// Make a request for a user with a given ID
axios.get(requestURL)
.then(function (response) {
// Handle success
console.log("And I am burdened with glorious purpose.")
// Getting timestamp immediately after request is completed
let endTimestamp = (new Date()).getTime()
console.log("Request start time stamp: " + startTimestamp)
console.log("Request completed time stamp: " + endTimestamp)
// Logging the whole _performanceLogger object
let responsePerformanceLogger = response.request._performanceLogger
console.log('Perf Logger:')
console.log(responsePerformanceLogger)
// Logging the key/value specific to the actual request within the _performanceLogger object
let requestPerfString = 'network_XMLHttpRequest_' + requestURL
let responseTimespans = responsePerformanceLogger._timespans[requestPerfString]
console.log('Specific Request Timings:')
console.log(responseTimespans)
})
.catch(function (error) {
// Handle error
console.log("This is a mistake! I shouldn't be here!")
console.log(error);
})
.then(function () {
// always executed
console.log('For all time! Always!')
});
I use Expo to run this code on my device, and I get the following output to the console:
And I am burdened with glorious purpose.
Request start time stamp: 1640229022039
Request completed time stamp: 1640229022156
Perf Logger:
PerformanceLogger {
"_closed": false,
"_extras": Object {},
"_pointExtras": Object {},
"_points": Object {
"initializeCore_end": 194691080.25150004,
"initializeCore_start": 194691027.19495836,
},
"_timespans": Object {
"network_XMLHttpRequest_http://192.168.1.40:19000/logs": Object {
"endExtras": undefined,
"endTime": 194692352.89145836,
"startExtras": undefined,
"startTime": 194691383.22187504,
"totalTime": 969.6695833206177,
},
"network_XMLHttpRequest_http://192.168.1.40:19001/symbolicate": Object {
"endExtras": undefined,
"endTime": 194694267.96945837,
"startExtras": undefined,
"startTime": 194694100.6875417,
"totalTime": 167.2819166779518,
},
"network_XMLHttpRequest_https://jsonplaceholder.typicode.com/users/2": Object {
"endExtras": undefined,
"endTime": 194699846.2774167,
"startExtras": undefined,
"startTime": 194699738.0606667,
"totalTime": 108.21674999594688,
},
},
}
Specific Request Timings:
Object {
"endExtras": undefined,
"endTime": 194699846.2774167,
"startExtras": undefined,
"startTime": 194699738.0606667,
"totalTime": 108.21674999594688,
}
For all time! Always!
My specific questions are:
What are the different objects under the _timespans key? There are two (log, symbolicate) to the local IP for Expo ... what's happening here? Presumably these won't there when I deploy outside of Expo.
Is the third, the one that contains the actual URL made in the request, the actual timing of the download? (I've extracted this one as Specific Request Timings.) This is total download time (latency + file download), correct?
Is relying on the XMLHttpRequest timing less/more accurate than just using the simple getTime() timestamps that I have called before the request and after successful completion? I would expect that they should be close, but the getTime()'s require some finite execution time that could be variable by device/load.

Related

Google Assistant Smart Home may return error 500 when doing Request Sync

I am doing Request Sync for my users because I implemented a new device type.
For some users it succeeds, but for some users I got errors with status 500 as a response of Request Sync like below.
{
"error": {
"code": 500,
"message": "Internal error encountered.",
"status": "INTERNAL"
}
}
I noticed the following rule about this error
If the error occurs in the Request Sync for a user, the same result will occur if I try the same thing for the same user immediately afterwards.
However, if I make a request to that user a day later, the request to the user may be successful.
I looked at the following document, but there is no description about the 500 status error.
https://developers.google.com/assistant/smarthome/develop/request-sync
Do you know why this is happening? Also, if you know the solution, please let me know.
Edited on April 22, 2021
The script is the following. It is written in NodeJS.
const smarthome = require('actions-on-google');
const app = smarthome.smarthome({
jwt: require('config.json')
});
const agentUserIds = ["xxxxx", "yyyyy"];
const sleep = msec => new Promise(resolve => setTimeout(resolve, msec));
const requestSync = async () => {
for (userId of agentUserIds) {
await app.requestSync(userId)
.then(() => {
console.log("Request sync success");
})
.catch(err => {
console.log("Request sync error");
console.error(err);
});
await sleep(1000);
}
};
requestSync();
As a result, I got the following output. It succeeds for some specific users and fails for some specific users.
Request sync error
{
"error": {
"code": 500,
"message": "Internal error encountered.",
"status": "INTERNAL"
}
}
Request sync success
Hi Can you check you are sending the correct API-Key in the Header, related to the users / agenuserId for which the Call is getting failed.

Code was fine but not it's throwing error 403 - Failed to load resource: the server responded with a status of 403 (Forbidden) (Axios YouTube API)

I was following tutorial: https://blog.bitsrc.io/make-a-simple-react-app-with-using-youtube-api-68fa016e5a03.
I'm a noob so please, if you can help, pretend my name is Layman
I had actually finished, made it beautiful and was adding some additional things (like dislike buttons that dont do anything but look the part)
But now none of it works. I've even reverted my commits really far back to points where I know for show it works but I'm getting the same error. I can only assume its with youtube's api key but I dont know whats wrong. I noticed the issue when i tried to change the maxResults from 5 to 20. It did like that and it hasnt worked since.
I've made a new key, and used a try catch (i think ive done it right) and it still doesnt work
handle submit in App.jsx
handleSubmit = async (termFromSearchbar) => {
// alert(termFromSearchbar);
try {
const res = await youtube.get("/search", {
params: {
part: "snippet",
maxResults: 5,
key: process.env.REACT_APP_API_KEY,
q: termFromSearchbar,
},
});
this.setState({
videos: res.data.items,
selectedVideo: res.data.items[0],
});
} catch (error) {
console.error(error);
}
};
my .env file
import axios from "axios";
export default axios.create({
baseURL: "https://www.googleapis.com/youtube/v3",
params: {
part: "snippet",
maxResults: 5,
key: `${process.env.REACT_APP_API_KEY}`,
},
});
One possible explanation is that you've exceeded your quota (https://developers.google.com/youtube/v3/docs/errors)
You should verify that first. This document describes how you can do that (https://developers.google.com/youtube/v3/getting-started#quota)

Call Service Only For One Time in React Native

I'm calling a get service in componentWillMount(). Service response me a object in the form of JSON I which mentioned below. But I need the values of service objects into my variables/objects so I made a loop when I'm getting the data from service and it works fine but the issue is that it takes too much time to pass the data into my objects/variables. It take at least 45 to 50 seconds to pass the service data into my objects. If I removed the loop so service respond me perfectly but I need the values of service into my objects. Please provide me the best solution for it. Thanks
Service JSON Response
{
"Capital": 0,
"Code": "BOL",
"Code2": "",
"Continent": "",
"GNP": 0,
"Name": "Bolivia",
}
I need the Code into key variable and Name into label variable
axios.get('http://apiurl.com/api/user/GetCountries')
.then((response) => {
for (var i = 0; i < response.data.length; i++) {
var joined = this.state.countriesModel.concat({ key: response.data[i].Code, label: response.data[i].Name });
this.setState({ countriesModel: joined });
}
this.hideLoader();
}).catch((err) => {
console.log(err)
});
I made array outside state and it works perfectly. setState is taking too much time to set the data.
countiesOptions = [];
componentDidMount(){
var joined = this.countiesOptions.concat({ key: response.data[i].Code, label: response.data[i].Name });
this.countiesOptions = joined;
}

How fix the bounds problem with openrouteservice API

I am trying send a request with openrouteservice, when I sent the coordinates I receive a error response
I am using react with the openrouteservice-js library
getResponse = async () => {
try {
const response = await Directions.calculate({
coordinates: [[9.930808,-84.052448],[9.933302,-84.056493]],
attributes: ['detourfactor'],
profile: 'driving-car',
extra_info: ['waytype', 'steepness'],
avoidables: ['highways', 'tollways', 'ferries', 'fords'],
instructions: true,
instructions_format: 'text',
preference: 'recommended',
units: 'km',
language: 'es',
format: 'json'
});
console.log(response);
this.setState({ response })
} catch (e) {
console.log(e, 'error');
}
}
Example map: https://maps.openrouteservice.org/directions?n1=9.933376&n2=-84.05461&n3=17&a=9.930808,-84.052448,9.933302,-84.056493&b=0&c=0&k1=en-US&k2=km
If I put the same coordinates in the example map the route is work fine, but when I sent the request I get this response error:
{
"error": {
"code": 2010,
"message": "Point 0 is out of bounds: -84.052448,9.930808"
}, "info": {
"engine": {
"version": "5.0.1",
"build_date": "2019-05-24T16:27:11Z",
},
"timestamp": 1558719789443
}
}
Not sure if this is still active, but I'll leave this answer here for others who might have this problem...
Many Geographical APIs accept [latitude, longitude] pairs, but Open Routes Service accepts [longitude, latitude]. If you swap them, the locations will snap to completely different locations, and if they happen to be in the ocean or outside of an inhabited area (mine was in Antarctica), this error message will be returned.
As the comment on the question said, though, it's also possible to get this error message through using the wrong map on your local version of the Open Routes Service.

InvalidSignatureException from POST request

I have a Lambda function that handles reading data from a file(stored inside S3 bucket) as well as inserting data to a Dynamodb table. This Lambda function is exposed as a REST endpoint using API gateway. The function accepts GET request as well as POST request. I'm making GET/POST requests from my REACT project using axios and aws4(for signing) libraries. GET request is to read data from a file stored inside S3 and it works just fine. And POST request is for inserting data into Dynamodb table. However, it doesn't work and AWS returns InvalidSignatureException error as a respond. This is an excerpt of my code :
createAWSSignedRequest(postData) {
let request = {};
if (postData) {
request = {
host: process.env.AWS_HOST,
method: 'POST',
url: process.env.AWS_URL,
path: process.env.AWS_PATH,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
}
} else {
request = {
host: process.env.AWS_HOST,
method: 'GET',
url: process.env.AWS_URL,
path: process.env.AWS_PATH
}
}
let signedRequest = aws4.sign(request, {
secretAccessKey: process.env.AWS_SECRET_KEY,
accessKeyId: process.env.AWS_ACCESS_KEY
});
return signedRequest;
}
This is how GET request is made :
let signedRequest = this.createAWSSignedRequest('GET');
axios(signedRequest)
.then(response => {
})
.catch((error) => {
console.log("error",error);
});
This is how POST request is made :
const data = {
uuid: "916b7d90-0137-11e8-94e6-116965754e23", //just a mock value
date : "22/jan/2018",
user_response: [
{
question:"this is quesiton1",
choice:"user selected A"
},
{
question:"this is quesiton2",
choice: "user selected b"
},
{
question:"this is quesiton3",
choice: "user selected C"
}
]
};
let signedRequest = this.createAWSSignedRequest(data);
axios(signedRequest)
.then(response => {
......
})
.catch((error) => {
console.log("error",error);
});
As you can see, the code for both GET and POST requests are exactly the same (except payload and method type). I'm singing with the same secret access key and access key id for both requests. I'm not sure why one request results in "InvalidSignatureException" when the other doesn't. Can anyone shed a light on this issue for me.
Thanks
After having discussion with AWS4 lib developer, I figured out what I did wrong. AWS4 uses "body" as a payload attribute to compute signature. However, Axios uses "data" attribute as payload. My mistake was only setting either one of them. So when I set just "data" attribute, the payload was present in the request and content-length is computed correctly. However, the signature was incorrect since the payload was not taken into consideration when computing signature. When I set just "body", payload was not present in the request because Axios does not use "body" attribute for payload. The solution is to set both attributes with payload. I hope this helps to anyone who are having the same issue I have.
If you use the AWS Amplify library it has a module called API which should fit your use cases, and it will perform Sigv4 signing for you either with authenticated or unauthenticated roles. The Auth category uses Cognito as the default implementation. For instance:
npm install aws-amplify --save
Then import and configure the lib:
import Amplify, { API } from 'aws-amplify';
Amplify.configure({
Auth: {
identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX-1234-abcd-1234567890ab',
region: 'XX-XXXX-X'
},
API: {
endpoints: [
{
name: "APIName",
endpoint: "https://invokeURI.amazonaws.com"
}
]
}
});
Then for your API Gateway endpoint calling a Lambda:
let apiName = 'MyApiName';
let path = '/path';
let options = {
headers: {...} // OPTIONAL
}
API.get(apiName, path, options).then(response => {
// Add your code here
});
More info here: https://github.com/aws/aws-amplify

Resources