-
Notifications
You must be signed in to change notification settings - Fork 638
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
Distributed error reporting: Capture more information about the error and its environment #12382
base: distributed-error-reporting
Are you sure you want to change the base?
Distributed error reporting: Capture more information about the error and its environment #12382
Conversation
Build Artifacts
|
6459176
to
da7f8f0
Compare
component: this.vm.$options.name || this.vm.$options._componentTag || 'Unknown Component', | ||
browser: this.getBrowserInfo(), | ||
device: this.getDeviceInfo(), | ||
}, |
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.
context
can be movet to ErrorReport too. We can then do something like the below;
getErrorReport() {
const context = this.getContext();
return {
...
context: {
component: this.vm.$options.name || this.vm.$options._componentTag || 'Unknown Component',
...context,
},
};
}
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.
Could even not even need to define getErrorReport
in this class, instead can just define it in the parent class once, and then here we do:
getContext() {
const context = super.getContext();
return {
...context,
component <etc>...
};
}
context: { | ||
browser: this.getBrowserInfo(), | ||
device: this.getDeviceInfo(), | ||
}, |
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.
Same here https://github.com/learningequality/kolibri/pull/12382/files#r1662911798. Though we would just assign the context
context: this.getContext()
context: { | ||
browser: this.getBrowserInfo(), | ||
device: this.getDeviceInfo(), | ||
}, |
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.
kolibri/core/errorreports/schemas.py
Outdated
"device": { | ||
"type": "object", | ||
"properties": { | ||
"type": {"type": "string"}, # "desktop", "tablet", "mobile" |
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.
With json schema we can ensure the device is from a predefined list of device types
"url": {"type": "string", "optional": True}, | ||
"method": {"type": "string", "optional": True}, | ||
"headers": {"type": "object", "optional": True}, | ||
"body": {"type": "string", "optional": True}, |
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 think properties are optional by default so there is not need to explicitly set them as optional. So you might as well do away with the optional flag?
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.
Also, we can use the required property that specifies the required fields instead where necessary
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.
(There are other sections in the schema with the same)
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.
@akolson I too had a doubt about this. But this comment suggested otherwise:
kolibri/kolibri/core/auth/models.py
Line 90 in dc7a843
# '"optional":True' is obsolete but needed while we keep using an |
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.
Since the use of the optional
property is specific to a particular version of jsonschema, we'll carry on with using it, but create a follow up issue to to update all jsonschemas as python 2.7 support has been dropped (the main reason the current version of jsonschema is used)
kolibri/core/errorreports/schemas.py
Outdated
"platform": { | ||
"type": "string", | ||
"optional": True, | ||
}, # "windows", "mac", "linux", "android", "ios" |
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.
With json schema we can ensure the platform is from a predefined list of platforms
@@ -6,13 +6,35 @@ class ErrorReport { | |||
getErrorReport() { | |||
throw new Error('getErrorReport() method must be implemented.'); | |||
} | |||
getDeviceInfo() { | |||
return { | |||
type: /Mobi|Android/i.test(navigator.userAgent) ? 'Mobile' : 'Desktop', |
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 will return the wrong type
if kolibri is used on a tablet for example.
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.
(Just noting that this is quite an unreliable way to check for device type)
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.
Yes, definitely just relying on the values already defined in browserInfo.js seems like the right way forward here, no need to write new code when we already have robust parsing of the userAgent.
getDeviceInfo() { | ||
return { | ||
type: /Mobi|Android/i.test(navigator.userAgent) ? 'Mobile' : 'Desktop', | ||
platform: navigator.platform, |
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.
We can use os
in browserInfo.js
getErrorReport() { | ||
return { | ||
error_message: this.e.message, | ||
traceback: this.e.stack, | ||
context: { | ||
component: this.vm.$options.name || this.vm.$options._componentTag || 'Unknown Component', | ||
browser: this.getBrowserInfo(), |
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.
We can use browser
in browserInfo.js
|
||
|
||
def get_python_version(): | ||
return version.split()[0] |
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 think this would only pick the first version of the tuple. See here
@@ -47,25 +54,55 @@ def allow_migrate(self, db, app_label, model_name=None, **hints): | |||
|
|||
|
|||
class ErrorReports(models.Model): |
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.
Also noting that
kolibri/kolibri/core/device/api.py
Line 201 in 2418619
info["installer"] = installation_type() |
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.
Similarly, we should store is_touch_device
to clearly distinguish between touch and non touch devices
kolibri/core/errorreports/tasks.py
Outdated
errors_json = serialize_error_reports_to_json_response(errors) | ||
|
||
requests.post( | ||
join_url(server, "/api/v1/errors/"), |
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.
Let's change the resource to /api/v1/errors/report/
for clarity.
device.type = device.type || 'unknown'; | ||
device.model = device.model || 'unknown'; | ||
device.vendor = device.vendor || 'unknown'; | ||
export const deviceWithTouch = { |
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 think this would be superfluous!
I think it would be more straight forward to just export device
info only. I dont see the need to bundle it up with the device
info.
I think the below would suffice
export const device = info.device;
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.
Also deviceWithTouch
could be misinterpreted to mean that it represents an object with touch capabilities which is not really the case -- isTouchDevice
is a runtime value.
// this is better than undefined | ||
device.type = device.type || 'unknown'; | ||
device.model = device.model || 'unknown'; | ||
device.vendor = device.vendor || 'unknown'; |
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 am not sure there any value add of doing this!
@@ -1,3 +1,5 @@ | |||
import { browser, os, deviceWithTouch } from './browserInfo'; |
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.
Lets import device
and isTouchDevice
instead of deviceWithTouch
here. See https://github.com/learningequality/kolibri/pull/12382/files#r1675763461
browser: browser, | ||
os: os, | ||
device: { | ||
...deviceWithTouch, |
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.
instead of deviceWithTouch
, we would have
device: {
...device,
isTouchDevice,
screen: {
...
}
}
"name": {"type": "string", "optional": True}, | ||
"major": {"type": "string", "optional": True}, | ||
"minor": {"type": "string", "optional": True}, | ||
"patch": {"type": "string", "optional": True}, |
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.
These can de defined as a property and referenced instead...
kolibri/core/errorreports/schemas.py
Outdated
"name": {"type": "string", "optional": True}, | ||
"major": {"type": "string", "optional": True}, | ||
"minor": {"type": "string", "optional": True}, | ||
"patch": {"type": "string", "optional": True}, |
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.
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.
For ecample it would mean adding definitions
....
"definitions": {
"versionInfo": {
"type": "object",
"properties": {
"name": {"type": "string", "optional": True},
"major": {"type": "string", "optional": True},
"minor": {"type": "string", "optional": True},
"patch": {"type": "string", "optional": True},
}
}
}
and then use it as below;
"os": {
"$ref": "#/definitions/versionInfo",
},
...
"browser": {
"$ref": "#/definitions/versionInfo",
}
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.
Hi @thesujai! Great work on the changes, The pr is now taking shape! I left a few comments that would be good to implement. Thanks
@@ -64,6 +64,13 @@ export const os = { | |||
patch: osVersion[2], | |||
}; | |||
|
|||
// Device info | |||
export const device = { | |||
type: info.device.type || 'desktop', |
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.
Why are we defaulting to 'desktop'?
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.
The ua-parser library gives undefined for desktop. As according to them desktop
is not an device type.
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.
Summary
error_from
tocategory
and more.References
Closes #12376
Reviewer guidance
Cannot find a way yo get the node version in frontend
Testing checklist
PR process
Reviewer checklist
yarn
andpip
)