-
-
Notifications
You must be signed in to change notification settings - Fork 23
Feature/deduplication #58
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
Conversation
make sure we have different stacks when the tests call for it make sure we have a stack when needed
JSON.stringify shortcut didn't work, resulting JSON stack was [{}, {}, {}] Fallback to running through inner errors, calculating hashcode per error, XORing them to a final hashcode
When running the node tests, we need NodeErrorParser, not DefaultErrorParser
because the testsuite process contains a lot of modules, we need to allow more time for module collection
private _processedHashcodes; | ||
private _getCurrentTime; | ||
constructor(getCurrentTime?: () => number); | ||
private _interval; | ||
constructor(getCurrentTime?: () => number, interval?: number); |
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.
should interval have a default value (you can do defaults in typescript)?
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 see that it's there, I just wonder if the definition needs to be regenerated.
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.
Not sure if the definition needs to contain the default value?
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'm not sure either.
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 guess that it generates it correctly?
let context: EventPluginContext; | ||
let contextData: ContextData; | ||
({ context, contextData } = createFixture()); | ||
let errorParser = client.config.errorParser; |
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 guess this allows us to run this test also on node, the con is we have to new up a whole new client.
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 also need the other plugins (to do stack parsing etc) Is there a better way to run all the plugins?
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.
Well for simple tests like this, I figured it would be better to just run the plugins that are required so it's faster and you are running only what is needed.
import { IEventPlugin } from '../IEventPlugin'; | ||
import { EventPluginContext } from '../EventPluginContext'; | ||
import { Utils } from '../../Utils'; | ||
|
||
export class DuplicateCheckerPlugin implements IEventPlugin { | ||
public priority: number = 40; | ||
public priority: number = 90; |
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 priority should be really really high, in .net we do 1010 to ensure it runs last.
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.
Done
|
||
constructor(getCurrentTime: () => number = () => Date.now()) { | ||
constructor(getCurrentTime: () => number = () => Date.now(), interval: number = 60000) { |
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 wonder if it should be less than a minute.. Minute in .net is not that long, minute in the browser is a long time.
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.
Suggestions for a better interval? How do we make sure the event gets sent anyway when the user navigates away?
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 might be an event for that? I know there are libs that you can get notifications of when the page goes to sleep or isn't active, maybe we'd turn off queue processing / submit all events when that happens? Idk
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'd go for a 30second interval I think
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.
Done
log.info(`Ignoring duplicate error event hash: ${hashCode}`); | ||
return true; | ||
while (error) { | ||
if (error.stack_trace && error.stack_trace.length) { |
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.
what if there is no stack trace? Should message be taken into account always?
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.
Done
return true; | ||
while (error) { | ||
if (error.stack_trace && error.stack_trace.length) { | ||
hashCode = (hashCode * 397) ^ Utils.getHashCode(JSON.stringify(error.stack_trace)); |
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.
should this be hashCode +=
?
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.
Done
return; | ||
} | ||
|
||
this._processedHashcodes.push({ hash: hashCode, timestamp: now }); |
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.
would be nice if we added some minimal logging to this class. Makes it much easier to debug issues
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.
Done
@@ -28,8 +28,10 @@ export class DuplicateCheckerPlugin implements IEventPlugin { | |||
let hashCode = 0; | |||
|
|||
while (error) { | |||
if (error.stack_trace && error.stack_trace.length) { | |||
hashCode = (hashCode * 397) ^ Utils.getHashCode(JSON.stringify(error.stack_trace)); | |||
hashCode += (hashCode * 397) ^ Utils.getHashCode(error.message); |
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.
Do you think we should be checking the message length as well? Os should getHashCode method check that?
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.
Added it, just in case :)
context.cancelled = true; | ||
return; | ||
} | ||
|
||
if (this._processedHashcodes.some(h => h.hash === hashCode && h.timestamp >= (now - this._interval))) { | ||
context.log.info("Adding event with hash: " + hashCode); |
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 should be a trace level message
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 only have these:
info(message: string): void;
warn(message: string): void;
error(message: string): void;
this._mergedEvents.push(new MergedEvent(hashCode, context, count)); | ||
context.cancelled = true; | ||
return; | ||
} | ||
|
||
context.log.info("Enqueueing event with hash: " + hashCode + "to cache."); |
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 should be a trace level message
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 only have:
info(message: string): void;
warn(message: string): void;
error(message: string): void;
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.
Guess we could add trace (https://github.com/DeveloperToolsWG/console-object/blob/master/api.md#consolelogobject--object-) doesn't look like it's supported everywhere. We'd have to wrap it like we are doing the other ones I guess.
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.
Done
Errors with just a message are also deduplicated now
#44
Similar to the work in the .NET client. This makes sure that: