-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Initial implementation of post function for Qt #346
Conversation
Hi @ChinYing-Li ! Thank you for this PR. The uploader is used by the Qt platform object. It should implement the |
I copied the chin-ying@chinying-Leopard-10SFK:~/repo/opensource/js/glean.js/samples/qt-qml-app$ .venv/bin/python3 main.py
qml: Initialized Glean succesfully.
qml: Adding to the `button_clicked` metric.
qml: Adding to the `button_clicked` metric.
qml: Adding to the `button_clicked` metric.
qml: Attempted to delete an entry from an invalid index. Ignoring.
qml: {
"metrics": {
"datetime": {
"sample.app_started": "2021-05-24T06:51:47.559-04:00"
},
"counter": {
"sample.button_clicked": 3
}
},
"ping_info": {
"seq": 0,
"start_time": "2021-05-24T06:51-04:00",
"end_time": "2021-05-24T06:52-04:00"
},
"client_info": {
"telemetry_sdk_build": "0.12.0",
"client_id": "d0c6f2e3-bf7a-4b41-b067-3c6fcb8cc438",
"first_run_date": "2021-05-24-04:00",
"os": "Linux",
"os_version": "Unknown",
"architecture": "Unknown",
"locale": "en-US",
"app_build": "Unknown",
"app_display_version": "Unknown"
}
}
I wonder if I missed some caveats of using the webext implementation in Qt. @Dexterp37 |
We were/are not sure about what subset of APIs are available on QT/QML: sadly not all of them are :-) Looks like we're lucky this time! My main concern was about Would you kindly also update the code in this PR to reflect what you're currently testing? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied the post function of BrowserUploader to qt/uploader.ts to see why people aren't using the webext's implementation for Qt platform, but it seems that the sample Qt app can run without running into any problem.
Interesting. This should not be the case, as far as I remember Qt does not provide the fetch
API. That is a browser only thing.
I see in the code changes that you have included a uploader.js
file, but have not changed the exported uploader over on https://github.com/mozilla/glean.js/blob/main/glean/src/platform/qt/index.ts. That needs to be changed in order for the uploader to be actually picked up. Maybe this is the case why it seemed to work with the web ext uploader.
Thank you for the pointers; it turns out that the chin-ying@chinying-Leopard-10SFK:~/repo/opensource/js/glean.js/glean$ nc -l 8080
POST /submit/qt-qml-app/custom/1/3ee47bdb-9cdb-4d06-96f0-19434386ac76 HTTP/1.1
Host: localhost:8080
X-Client-Type: Glean.js
X-Client-Version: 0.12.0
Content-Type: application/json; charset=UTF-8
Content-Length: 441
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Accept-Language: en-US,*
User-Agent: Mozilla/5.0
{"metrics":{"datetime":{"sample.app_started":"2021-05-26T19:06:55.964-04:00"}},"ping_info":{"seq":0,"start_time":"2021-05-26T19:06-04:00","end_time":"2021-05-26T19:06-04:00"},"client_info":{"telemetry_sdk_build":"0.12.0","client_id":"29aa3260-d94f-4dc0-ae3b-721284c081d3","first_run_date":"2021-05-26-04:00","os":"Linux","os_version":"Unknown","architecture":"Unknown","locale":"en-US","app_build":"Unknown","app_display_version":"Unknown"}} I will further investigate and update when the patch is ready! |
So the problem of "hanging after receiving the first log" seems to be a server side issue instead of a client side issue. import socket
import sys
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8080)) # (host, port) because AF_INET
print("Listening...")
sock.listen(1)
except Exception as e:
print(repr(e))
print('Failed to create socket')
sys.exit()
if __name__ == "__main__":
while True:
conn, addr = sock.accept()
print('Connected by', addr)
print(conn.recv(4096)) # buffer size
conn.close() Every time the Connected by ('127.0.0.1', 52400)
b'POST /submit/qt-qml-app/custom/1/e575aec8-8564-42f5-9580-ce3e8fdb28b8 HTTP/1.1\r\nHost: localhost:8080\r\nX-Client-Type: Glean.js\r\nX-Client-Version: 0.12.0\r\nContent-Type: application/json; charset=UTF-8\r\nContent-Length: 441\r\nConnection: Keep-Alive\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: en-US,*\r\nUser-Agent: Mozilla/5.0\r\n\r\n{"metrics":{"datetime":{"sample.app_started":"2021-05-28T18:43:19.156-04:00"}},"ping_info":{"seq":0,"start_time":"2021-05-28T18:43-04:00","end_time":"2021-05-28T18:43-04:00"},"client_info":{"telemetry_sdk_build":"0.12.0","client_id":"f9a3d823-2e0d-4407-a92e-951606ad2efb","first_run_date":"2021-05-28-04:00","os":"Linux","os_version":"Unknown","architecture":"Unknown","locale":"en-US","app_build":"Unknown","app_display_version":"Unknown"}}' And the client (Qt app in debug mode) logs to terminal: qml: Attempted to delete an entry from an invalid index. Ignoring.
qml: {
"metrics": {
"datetime": {
"sample.app_started": "2021-05-28T18:43:19.156-04:00"
}
},
"ping_info": {
"seq": 0,
"start_time": "2021-05-28T18:43-04:00",
"end_time": "2021-05-28T18:43-04:00"
},
"client_info": {
"telemetry_sdk_build": "0.12.0",
"client_id": "f9a3d823-2e0d-4407-a92e-951606ad2efb",
"first_run_date": "2021-05-28-04:00",
"os": "Linux",
"os_version": "Unknown",
"architecture": "Unknown",
"locale": "en-US",
"app_build": "Unknown",
"app_display_version": "Unknown"
}
}
qml: Some network error occurred. undefined
qml: Recoverable upload failure while attempting to send ping e575aec8-8564-42f5-9580-ce3e8fdb28b8, will retry. Error was no status.
qml: Some network error occurred. undefined
qml: Recoverable upload failure while attempting to send ping e575aec8-8564-42f5-9580-ce3e8fdb28b8, will retry. Error was no status.
qml: Some network error occurred. undefined
qml: Recoverable upload failure while attempting to send ping e575aec8-8564-42f5-9580-ce3e8fdb28b8, will retry. Error was no status.
qml: Reached maximum recoverable failures for the current uploading window. You are done. The |
Hm, could this be happening because there is no response from the server to the client? Note that Glean.js expects some response from the server. The body of the request shouldn't matter, only the status code. Try adding a Wondering if we should provide a test server in our development documentation. WDYT? @ChinYing-Li @Dexterp37 |
We do have a simple test server if we want to make sure the ingestion is not the offending part. |
I tested the code with https://github.com/mozilla/gzipServer, and it does work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work here, @ChinYing-Li ! Let's also add some tests to the new uploader. We need to make sure that
- When the request is completed succesfully, the correct UploadResult is returned;
- When the request is not completed succesfully, the correct UploadResult is returned;
- When the request times out, the correct UploadResult is returned.
Another thing. We need to be extra sure that the promise returned by the Uploader always resolves. I notice the onabort
event is not covered. Although the request unlikely to be aborted, I think it is best to make sure we cover all cases. Another option would be to resort to the onloadend
event which is triggered when the request is completed withor without errors.
Just to update what I've been trying to do: Please let me know if you have any thought on this. |
Hey, our of curiosity, why are you trying to mock the server, @ChinYing-Li ? |
I thought it's better to write unit tests for |
The problem with the test is that it What you can do is something like this: // Make the request, but don't await on it.
const response = QtUploader.post("/hello", "");
// Tell the server to respond to pending requests
server.respond();
// Only then await on the request and assert. Now it is ok to await because we know the server will respond :)
assert.deepStrictEqual(
await response,
{ status: status, result: UploadResultStatus.Success }
); This is untested, so might need some tweaking. It should work though :)
I think it is a fine approach to provide a fake server here. I mocked
If you were to mock the request itself instead of providing a fake server, you would not mock |
Unit tests for QtUploader working. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great, thanks for the hard work here! There are a just a few last nits to address, otherwise, good to go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work here, @ChinYing-Li ! Thanks a lot, this is of great help to the project. We appreciate you taking bugs on Glean.js :)
This PR is a work in progress, and needs some comments before I can move on.
Right now, I implemented a
post
function in Javascript, so that thepost
function could be used in aQML
file.It's not immediately clear to me how this
Uploader
implementation would be exposed to a Qt application.Will the Qt application import the entire Glean.js library? (From https://github.com/mozilla-mobile/mozilla-vpn-client/tree/main/glean, this doesn't seem to be the case.)