http://coldfusion.com logo
#box-products
Title
# box-products
s

sknowlton

05/02/2022, 1:49 PM
We use the Sentry module and love it, but we've recently started using a whole bunch of API endpoints that do a lot of validation of client input where we call
validateOrFail()
on the request scope. We use the REST-HMVC template and so
ValidationException
is caught and dealt with, but it still triggers
onException
which triggers the Sentry Module. Consequently we're getting a Sentry entry for every single client validation failure. Is there a way we can specify the error level somewhere in the request or the exception, and then have Sentry's
onException
look for it and only default to
error
if it isn't there? That seems like the most correct way to reflect what's really going on, which is that some of these exceptions, being caught, shouldn't trigger the thing we have for actual CF errors
w

wil-shiftinsert

05/02/2022, 2:31 PM
I think the sentry module is not that smart, but I think it shouldn’t be too hard to achieve, without messing up the module itself.|
You could extend
YourSentryService
from the sentryService in the sentry module and override the captureException method. Create a default Exception type, check the exception.type against your own ignore list (ValidationException, maybe more…) and return null, or call super.captureException(…) if you don’t want to filter. Next thing to do is override the wirebox mapping for sentryService@sentry and map it to your own version. You can do that in an
afterAspectsLoad
interceptor, which fires when all modules have loaded.
s

sknowlton

05/02/2022, 2:42 PM
I think I just want to make that call to
captureException
in ModuleConfig that gets registered in the onException interceptor check for a value in
exception
that would override "error"
The way it's set up now, every single CF exception is level
ERROR
since the module already supports min & max levels for reporting exceptions, seems like the path of least resistance to just let us catch and modify those levels on a per-exception basis
w

wil-shiftinsert

05/02/2022, 2:45 PM
were are these min and max levels set now?
s

sknowlton

05/02/2022, 2:47 PM
In the module settings
w

wil-shiftinsert

05/02/2022, 2:47 PM
I think there are min and max levels for LOGGING, so if you cal log.error() , it will be sent to sentry but log,debug not
s

sknowlton

05/02/2022, 2:50 PM
hmm, yeah, I guess every exception is an error
maybe an optional property on the exception object
because it's not just 'all exceptions of (type)', it's something I want to be able to toggle in particular catch blocks
w

wil-shiftinsert

05/02/2022, 2:54 PM
Well, you could investigate your exception here and only call captureException if it is not in your exclude list. But that would mean modifying the module.
You can send a different level to captureException, but it it sends all levels it receives to sentry. So your options are: modifying the onException in the moduleconfig which needs a module update. Or my suggestion which creates more or less your own filter on the captureException method by extending it, which doesn’t need a module update. I did a similar trick before on the cbswagger module where I wanted to change behaviour of the routesParser. I didn’t create a pull here because I needed flexibility and I was the only one using a modified version. But to be honest, I think this module could use a PR for an IgnoreExceptionTypes setting, so we could specify which Error types to ignore. Not so hard to create. Reading the setting in the captureException method and ignore where appropriate.
b

bdw429s

05/03/2022, 12:16 AM
@sknowlton Log levels really have nothing to do with this since it's not coming through a Logbox logger. When the
enableExceptionLogging
setting is turned on, the module simply listens to any time the
onException
interception point is announced and then sends it to Sentry https://github.com/coldbox-modules/sentry/blob/development/ModuleConfig.cfc#L108
If you have code like this
Copy code
try {
  model.validate();
} catch( validationException e ) {
  // Deal with vaildation error
}
then the framework will never "see" that exception and neither will Sentry
I don't know exactly where you're throwing the validation exceptions and where you're catching them, but somewhere in there the framework (or a base handler, perhaps) is announcing the
onException
interception point.
s

sknowlton

05/03/2022, 12:23 AM
We'll do something in a new user API handler like this:
var validateResults = validateOrFail( target = event.getCollection(), constraints = constraints );
which then triggers
validateOrFail
in cbvalidation which throws a validationException (on a custom validator, in this case a unique email checker). It's correctly caught by our baseHandler's
validationException
catch because the API repsonse object shows all the proper plumbing with the validation errors. But Sentry is reporting it as well.
b

bdw429s

05/03/2022, 12:24 AM
Right, so if you look in the base handler's catch block, is it announcing
onexception
?
s

sknowlton

05/03/2022, 12:25 AM
None of our code is announcing an onException
b

bdw429s

05/03/2022, 12:25 AM
I didn't imply is was your code 😉
I'm just trying to tack the code path first
s

sknowlton

05/03/2022, 12:25 AM
No, our API BaseHandler is the Coldbox 5 REST-HMVC template that we've modified a bunch but not that part
The stack trace Sentry grabs is interesting in that it's reporting the validationManager itself as the source
we are two minor versions behind in cbvalidation but I don't see anything relevant to this there
b

bdw429s

05/03/2022, 12:32 AM
I can't find your base handler
It doesn't exist in the repo in the location that it shows in the stack trace above
how long ago did you use the rest hmvc app template?
Looks like it was quite a while ago. That file hasn't existed since the Coldbox 5 versions of the template I think https://github.com/coldbox-templates/rest-hmvc/blob/v1.29.0/modules_app/api/handlers/BaseHandler.cfc
s

sknowlton

05/03/2022, 12:35 AM
That's correct. It was the CB5 version
Copy code
function aroundHandler( event, rc, prc, targetAction, eventArguments ) {
	try {
		(basehandler prep plumbing)

			// Execute action
			if ( !prc.response.getError() ) {
				var actionResults = arguments.targetAction( argumentCollection = args );
			}	
		}
catch ( ValidationException e ) {
	(massage response object)
}
If aroundHandler weren't executing, prc.response wouldn't even be getting created, nor would the response object have all the things it's returning to us
b

bdw429s

05/03/2022, 12:43 AM
Hmm, I'm not sure what the code is then
Without being able to trace it
I'd put a check in the actual sentry service for one of the validation messages them dump the call stack and abort
That will at least show you if it's coming through an onException announcement or a logbox error message.
s

sknowlton

05/03/2022, 12:46 AM
It's coming from the validation messages
Copy code
{
Extended Info: {
email: [
{
errorMetadata: {}, 
field: email, 
message: The specified email address is unavailable or already belongs to a user in this league., 
rejectedValue: <mailto:someguy@gmail.com|someguy@gmail.com>, 
validationData: {}, 
validationType: Unique User
}
]
}
}
b

bdw429s

05/03/2022, 12:51 AM
That's... not what I was asking
I'm asking what code path is calling Sentry to log it
w

wil-shiftinsert

05/03/2022, 8:38 AM
I understand what you are saying Brad. If you catch ALL validation exceptions in your base handler it shouldn’t trigger the onException interception. Which means there is only one other path which sends this error to sentry: the sentry logbox appender. So if you change this modulesetting
Copy code
enableLogBoxAppender = false
for testing, the only route left would be the onException interception. Which shouldn’t fire if your aroundhandler has proper code to handle this. I think we used a similar setup and if I remember correctly I had to add error catching for validation exceptions. At least it was not there in older versions of the handler.
s

sknowlton

05/03/2022, 1:00 PM
I have no idea. It doesn't make sense to me that the stack trace doesn't include the aroundHandler in baseHandler, and yet the baseHandler plumbing is all there
Like how is this error being caught and wrapped up nicely in a bow for our API response object, and yet it's also triggering onException
b

bdw429s

05/03/2022, 1:04 PM
Dump/abort the call stack like I suggested (in the sentyservice) and we'll find out 😀
w

wil-shiftinsert

05/03/2022, 1:07 PM
Or disable the appender. If your errors still show up in sentry then your exceptions are not caught by your baseHandler. But I agree with brad the call stack should show all details.
s

sknowlton

05/03/2022, 1:07 PM
will check it out shortly
w

wil-shiftinsert

05/03/2022, 1:11 PM
I assume you have a simular setup like me in the basehandler aroundhandler method, something like
Copy code
// Validation Exceptions
        catch ( "ValidationException" e ) {
            arguments.exception = e;
            this.onValidationException( argumentCollection = arguments );
        }
if you abort with some clear message on the first line of your onValidationException method, you are absolutely sure your exception is caught in the right place.
b

bdw429s

05/03/2022, 1:30 PM
No, not there. I said in the actual sentry service. Then you'll have the full code path that hits sentry.
w

wil-shiftinsert

05/03/2022, 1:37 PM
It was just a different way to find out what’s going wrong here. Just trying to help, not trying to be smarter. I have better things to do today.
s

sknowlton

05/03/2022, 1:38 PM
yeah, it'd tell me if my aroundHandler is in fact running
the stack trace would tell me what else is running instead of it. 🙂
w

wil-shiftinsert

05/03/2022, 1:40 PM
still curious why it doesn’t work. I think my setup here is almost identical
4 Views