getsentry / sentry

Developer-first error tracking and performance monitoring
https://sentry.io
Other
39.09k stars 4.2k forks source link

Path matching in custom grouping rules doesn't work as expected in some cases #20095

Open rchl opened 4 years ago

rchl commented 4 years ago

Important Details

How are you running Sentry?

Saas (sentry.io)

Description

Custom grouping rule path:**app/**/*.* +app, to mark frames as "app", is not applied when expected.

Steps to Reproduce

  1. in Project -> General -> Grouping Settings, set a grouping rule: path:**app/**/*.* +app
  2. Trigger an error that contains path that starts with app/...

An example stacktrace (JS):

TypeError: this.boom is not a function
  at VueComponent.crash(app/pages/index.vue:17:1)
  at click(./app/pages/index.vue?c9f3:1:366)
  at invokeWithErrorHandling(./node_modules/vue/dist/vue.runtime.esm.js:1854:1)
  at HTMLAnchorElement.invoker(./node_modules/vue/dist/vue.runtime.esm.js:2179:1)
  at HTMLAnchorElement.original._wrapper(./node_modules/vue/dist/vue.runtime.esm.js:6917:1)

Note that the first frame from the top is not matched but second (starting with ./) is.

Screenshot 2020-07-30 at 19 23 33

I've also tried globs like:

What you expected to happen

The **app/**/*.* (or app/**/*.*) glob matches the path starting with app/....

Possible Solution

Match using further components of the path which makes the match less reliable.

untitaker commented 4 years ago

Yeah, glob is tricky. I used https://globster.xyz/ and the only thing that actually matched app/... (your first frame) was app/**. Could you try that?

rchl commented 4 years ago

No sorry, this still doesn't work.

But then this page also seems to match for **app/**: Screenshot 2020-07-30 at 20 30 51

untitaker commented 4 years ago

If you go to JSON download of the app, what is the JSON object surrounding that problematic path string? I can try some things locally.

rchl commented 4 years ago

Here is the whole exception object:

Details ```js "exception": { "values": [{ "stacktrace": { "frames": [{ "function": "HTMLAnchorElement.original._wrapper", "abs_path": "webpack:///./node_modules/vue/dist/vue.runtime.esm.js", "pre_context": [ " // #9448 bail if event is fired in another document in a multi-page", " // electron/nw.js app, since event.timeStamp will be using a different", " // starting reference", " e.target.ownerDocument !== document", " ) {" ], "post_context": [ " }", " };", " }", " target$1.addEventListener(", " name," ], "module": "vue/dist/vue.runtime.esm", "filename": "./node_modules/vue/dist/vue.runtime.esm.js", "lineno": 6917, "colno": 1, "in_app": false, "data": { "sourcemap": "http://localhost:9000/_nuxt/commons/app.2cd0a1c.js.map" }, "context_line": " return original.apply(this, arguments)" }, { "function": "HTMLAnchorElement.invoker", "abs_path": "webpack:///./node_modules/vue/dist/vue.runtime.esm.js", "pre_context": [ " for (var i = 0; i < cloned.length; i++) {", " invokeWithErrorHandling(cloned[i], null, arguments$1, vm, \"v-on handler\");", " }", " } else {", " // return handler return value for single handlers" ], "post_context": [ " }", " }", " invoker.fns = fns;", " return invoker", "}" ], "module": "vue/dist/vue.runtime.esm", "filename": "./node_modules/vue/dist/vue.runtime.esm.js", "lineno": 2179, "colno": 1, "in_app": false, "data": { "sourcemap": "http://localhost:9000/_nuxt/commons/app.2cd0a1c.js.map" }, "context_line": " return invokeWithErrorHandling(fns, null, arguments, vm, \"v-on handler\")" }, { "function": "invokeWithErrorHandling", "abs_path": "webpack:///./node_modules/vue/dist/vue.runtime.esm.js", "pre_context": [ " vm,", " info", ") {", " var res;", " try {" ], "post_context": [ " if (res && !res._isVue && isPromise(res) && !res._handled) {", " res.catch(function (e) { return handleError(e, vm, info + \" (Promise/async)\"); });", " // issue #9511", " // avoid catch triggering multiple times when nested calls", " res._handled = true;" ], "module": "vue/dist/vue.runtime.esm", "filename": "./node_modules/vue/dist/vue.runtime.esm.js", "lineno": 1854, "colno": 1, "in_app": false, "data": { "sourcemap": "http://localhost:9000/_nuxt/commons/app.2cd0a1c.js.map" }, "context_line": " res = args ? handler.apply(context, args) : handler.call(context);" }, { "function": "click", "abs_path": "webpack:///./app/pages/index.vue?c9f3", "post_context": [ "var staticRenderFns = []", "", "export { render, staticRenderFns }" ], "module": "app/pages/index", "filename": "./app/pages/index.vue?c9f3", "lineno": 1, "colno": 366, "in_app": true, "data": { "sourcemap": "http://localhost:9000/_nuxt/pages/index.fe09d4a.js.map" }, "context_line": "{snip} n($event){$event.preventDefault();$event.stopPropagation();return _vm.crash()}}},[_vm._v(\"Click to crash\")])]),_vm._v(\" \"),_c('p',[_vm._v(\"G {snip}" }, { "function": "VueComponent.crash", "abs_path": "webpack:///app/pages/index.vue", "pre_context": [ "", "", "" ], "module": "app/pages/index", "filename": "app/pages/index.vue", "lineno": 17, "colno": 1, "in_app": false, "data": { "sourcemap": "http://localhost:9000/_nuxt/pages/index.fe09d4a.js.map" }, "context_line": " this.boom();" } ] }, "type": "TypeError", "raw_stacktrace": { "frames": [{ "function": "HTMLAnchorElement.original._wrapper", "abs_path": "http://localhost:9000/_nuxt/commons/app.2cd0a1c.js", "pre_context": [ " // #9448 bail if event is fired in another document in a multi-page", " // electron/nw.js app, since event.timeStamp will be using a different", " // starting reference", " e.target.ownerDocument !== document", " ) {" ], "post_context": [ " }", " };", " }", " target$1.addEventListener(", " name," ], "filename": "/_nuxt/commons/app.2cd0a1c.js", "lineno": 6350, "colno": 25, "in_app": false, "context_line": " return original.apply(this, arguments)" }, { "function": "HTMLAnchorElement.invoker", "abs_path": "http://localhost:9000/_nuxt/commons/app.2cd0a1c.js", "pre_context": [ " for (var i = 0; i < cloned.length; i++) {", " invokeWithErrorHandling(cloned[i], null, arguments$1, vm, \"v-on handler\");", " }", " } else {", " // return handler return value for single handlers" ], "post_context": [ " }", " }", " invoker.fns = fns;", " return invoker", "}" ], "filename": "/_nuxt/commons/app.2cd0a1c.js", "lineno": 1929, "colno": 14, "in_app": false, "context_line": " return invokeWithErrorHandling(fns, null, arguments, vm, \"v-on handler\")" }, { "function": "invokeWithErrorHandling", "abs_path": "http://localhost:9000/_nuxt/commons/app.2cd0a1c.js", "pre_context": [ " vm,", " info", ") {", " var res;", " try {" ], "post_context": [ " if (res && !res._isVue && isPromise(res) && !res._handled) {", " res.catch(function (e) { return handleError(e, vm, info + \" (Promise/async)\"); });", " // issue #9511", " // avoid catch triggering multiple times when nested calls", " res._handled = true;" ], "filename": "/_nuxt/commons/app.2cd0a1c.js", "lineno": 1706, "colno": 26, "in_app": false, "context_line": " res = args ? handler.apply(context, args) : handler.call(context);" }, { "function": "click", "abs_path": "http://localhost:9000/_nuxt/pages/index.fe09d4a.js", "pre_context": [ "\"use strict\";", "// ESM COMPAT FLAG", "__webpack_require__.r(__webpack_exports__);", "", "// CONCATENATED MODULE: ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loade {snip}" ], "post_context": [ "var staticRenderFns = []", "", "", "// CONCATENATED MODULE: ./app/pages/index.vue?vue&type=template&id=5cb5be7a&", "" ], "filename": "/_nuxt/pages/index.fe09d4a.js", "lineno": 11, "colno": 377, "in_app": true, "context_line": "{snip} event.preventDefault();$event.stopPropagation();return _vm.crash()}}},[_vm._v(\"Click to crash\")])]),_vm._v(\" \"),_c('p',[_vm._v(\"Go to \"),_c( {snip}" }, { "function": "VueComponent.crash", "abs_path": "http://localhost:9000/_nuxt/pages/index.fe09d4a.js", "pre_context": [ "//", "//", "/* harmony default export */ var pagesvue_type_script_lang_js_ = ({", " methods: {", " crash: function crash() {" ], "post_context": [ " }", " }", "});", "// CONCATENATED MODULE: ./app/pages/index.vue?vue&type=script&lang=js&", " /* harmony default export */ var app_pagesvue_type_script_lang_js_ = (pagesvue_type_script_lang_js_); " ], "filename": "/_nuxt/pages/index.fe09d4a.js", "lineno": 33, "colno": 12, "in_app": false, "context_line": " this.boom();" } ] }, "value": "this.boom is not a function", "mechanism": { "type": "generic", "handled": true } }] }, ```
untitaker commented 4 years ago

Okay... we use abs_path for matching. I tried this now in the shell using the Python function that is used on the server:

**/app/**

let me know

rchl commented 4 years ago

That works well indeed. 👍

Screenshot 2020-07-30 at 21 05 29

In that case, I'm not sure there is any action to do here. Maybe adding some clarity to the UI? Either with more complex examples, link to a more detailed explanation or some online playground for testing globs. :)

Talking about this place: Screenshot 2020-07-30 at 21 06 49

untitaker commented 4 years ago

Yeah for sure. I think one pitfall here is also that filename is visible in teh UI and the actual value matched against is abs_path. We can tweak that logic a little, maybe.

rchl commented 4 years ago

Like maybe prepend **/ automatically (behind the scenes even) if that exact string does not start with that pattern. (at least for path matcher)

github-actions[bot] commented 3 years ago

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Accepted, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀