Skip to content

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

Merged
merged 28 commits into from
Oct 4, 2016
Merged

Feature/deduplication #58

merged 28 commits into from
Oct 4, 2016

Conversation

srijken
Copy link
Contributor

@srijken srijken commented Sep 27, 2016

#44

Similar to the work in the .NET client. This makes sure that:

  • the occurrence count is set in the deduplicated event, instead of just dropping events.
  • The date is set to the max of the dates of the rolled up events

srijken added 15 commits May 14, 2016 01:57
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);
Copy link
Member

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)?

Copy link
Member

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.

Copy link
Contributor Author

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?

Copy link
Member

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.

Copy link
Contributor Author

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;
Copy link
Member

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.

Copy link
Contributor Author

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?

Copy link
Member

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;
Copy link
Member

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.

Copy link
Contributor Author

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) {
Copy link
Member

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.

Copy link
Contributor Author

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?

Copy link
Member

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

Copy link
Member

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

Copy link
Contributor Author

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) {
Copy link
Member

@niemyjski niemyjski Sep 27, 2016

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?

Copy link
Contributor Author

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));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be hashCode +=?

Copy link
Contributor Author

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 });
Copy link
Member

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

Copy link
Contributor Author

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);
Copy link
Member

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?

Copy link
Contributor Author

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);
Copy link
Member

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

Copy link
Contributor Author

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.");
Copy link
Member

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

Copy link
Contributor Author

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;

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@srijken srijken merged commit c24d435 into master Oct 4, 2016
@srijken srijken deleted the feature/deduplication branch October 4, 2016 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants