Giter Club home page Giter Club logo

Comments (7)

vsilaev avatar vsilaev commented on May 23, 2024

Hello, buko

Let us elaborate on this issue a bit more.

First, what is your scenario for logging exceptions? What is the logger you are using? And what version of Tascalate Concurrent are you using?

Second, yes, neither cause nor suppressed exceptions are initialized. All in all, what is a cause when there are multiple ones? And using addSuppresed sounds to me as an API abuse. Probably I will add it but only if there are no other mechanism to fix the issue.

Third, I did some coding for dumping error info. To verify the functionality please try running TestMultitargetExceptionTraces (just copy sources -- it depends only on the Tascalate Concurrent lib).

Also, you can replace a line with

e.printStackTrace(); // line 11

with the following:

System.getLogger("any").log(Level.ERROR, "MY ERROR", e);

to verify that dumping errors works.
For me the output is:

net.tascalate.concurrent.MultitargetException
	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:21)
	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err(TestMultitargetExceptionTraces.java:17)
	at net.tascalate.concurrent.TestMultitargetExceptionTraces.main(TestMultitargetExceptionTraces.java:10)
	[2] -> java.lang.NoSuchMethodError: Data not found
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_2(TestMultitargetExceptionTraces.java:47)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_1(TestMultitargetExceptionTraces.java:43)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b(TestMultitargetExceptionTraces.java:39)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:24)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err(TestMultitargetExceptionTraces.java:17)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.main(TestMultitargetExceptionTraces.java:10)
	[4] -> java.lang.IllegalArgumentException: Something wrong
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.a(TestMultitargetExceptionTraces.java:33)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:25)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err(TestMultitargetExceptionTraces.java:17)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.main(TestMultitargetExceptionTraces.java:10)
	    ... Caused by: java.lang.NoSuchMethodError: Data not found
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_2(TestMultitargetExceptionTraces.java:47)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_1(TestMultitargetExceptionTraces.java:43)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b(TestMultitargetExceptionTraces.java:39)
	    ... 	... 4 more
	[6] -> net.tascalate.concurrent.MultitargetException
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:26)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err(TestMultitargetExceptionTraces.java:17)
	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.main(TestMultitargetExceptionTraces.java:10)
	    ... 	[0] -> java.lang.IllegalStateException: State is forbidden
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.c_2(TestMultitargetExceptionTraces.java:61)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.c_1(TestMultitargetExceptionTraces.java:57)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.c(TestMultitargetExceptionTraces.java:53)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:26)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err(TestMultitargetExceptionTraces.java:17)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.main(TestMultitargetExceptionTraces.java:10)
	    ... 	[1] -> java.lang.NoSuchMethodError: Data not found
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_2(TestMultitargetExceptionTraces.java:47)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_1(TestMultitargetExceptionTraces.java:43)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.b(TestMultitargetExceptionTraces.java:39)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:26)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err(TestMultitargetExceptionTraces.java:17)
	    ... 	    ... 	at net.tascalate.concurrent.TestMultitargetExceptionTraces.main(TestMultitargetExceptionTraces.java:10)

If your logging framework doesn't support dumping stack trace, then it's pretty easy to dump MultitargetException to StringWritter:

// e is a MultitargetException here
java.io.StringWriter w = new java.io.StringWriter();
e.printStackTrace(new java.io.PrintWriter(w));
System.out.println(w.toString());

Waiting for your reply.

from tascalate-concurrent.

buko avatar buko commented on May 23, 2024

We're using the latest version from maven.

It really is important to initialize the cause and the suppressed exceptions for MultitargetException. We have automated monitoring systems that are inspecting cause and suppressed exceptions and looking for specific types. It seems very strange that these systems break because MultitargetException, even though it clearly has a cause, doesn't expose that to the world. It seems to me a good idea to always pick the first exception as the cause and add the rest as suppressed.

Overriding printStackTrace() is a good idea but I would be concerned that it's not possible to retrieve the actual underlying Exception objects from MultitargetException without writing special code specifically for MultitargetException. We actually have code that knows how to work with the standard APIs and generate detailed error reports.

Also overriding printStackTrace() does not solve the problem. The MultitargetException itself gets wrapped in another exception. When the logging system eventually calls printStackTrace() on the root exception (which may wrap another exception which may wrap another exception which may eventually wrap MultitargetException) it is the standard prinstStackTrace() code that gets executed, not MultitargetException's printStackTrace(). The standard printStackTrace() knows how to deal with causes and suppressed exception so that can be highlighted but it doesn't know how to deal with MultitargetException. This is what I mean when I said MultitargetException swallows exceptions, it doesn't actually expose their existence through the standard APIs that everything else depends on.

from tascalate-concurrent.

vsilaev avatar vsilaev commented on May 23, 2024

Hello,

Now I see your point. When I dump new IOException("Invalid user input", new MultitargetException(excepionsList)) I see truncated output, while by default Throwable.printStackTrace inspects causes and suppressedExceptions.

I did a rough test and add all exceptions as suppressed, here is an output:

SEVERE: MY ERROR
java.io.IOException: Invalid user input
	at net.tascalate.concurrent.TestMultitargetExceptionTraces.outer(TestMultitargetExceptionTraces.java:18)
	at net.tascalate.concurrent.TestMultitargetExceptionTraces.main(TestMultitargetExceptionTraces.java:11)
Caused by: net.tascalate.concurrent.MultitargetException
	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:26)
	at net.tascalate.concurrent.TestMultitargetExceptionTraces.err(TestMultitargetExceptionTraces.java:22)
	... 1 more
	Suppressed: java.lang.NoSuchMethodError: Data not found
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_2(TestMultitargetExceptionTraces.java:52)
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_1(TestMultitargetExceptionTraces.java:48)
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.b(TestMultitargetExceptionTraces.java:44)
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:29)
		... 2 more
	Suppressed: java.lang.IllegalArgumentException: Something wrong
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.a(TestMultitargetExceptionTraces.java:38)
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:30)
		... 2 more
	Caused by: java.lang.NoSuchMethodError: Data not found
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_2(TestMultitargetExceptionTraces.java:52)
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_1(TestMultitargetExceptionTraces.java:48)
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.b(TestMultitargetExceptionTraces.java:44)
		... 4 more
	Suppressed: net.tascalate.concurrent.MultitargetException
		at net.tascalate.concurrent.TestMultitargetExceptionTraces.err_1(TestMultitargetExceptionTraces.java:31)
		... 2 more
		Suppressed: java.lang.IllegalStateException: State is forbidden
			at net.tascalate.concurrent.TestMultitargetExceptionTraces.c_2(TestMultitargetExceptionTraces.java:66)
			at net.tascalate.concurrent.TestMultitargetExceptionTraces.c_1(TestMultitargetExceptionTraces.java:62)
			at net.tascalate.concurrent.TestMultitargetExceptionTraces.c(TestMultitargetExceptionTraces.java:58)
			... 3 more
		Suppressed: java.lang.NoSuchMethodError: Data not found
			at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_2(TestMultitargetExceptionTraces.java:52)
			at net.tascalate.concurrent.TestMultitargetExceptionTraces.b_1(TestMultitargetExceptionTraces.java:48)
			at net.tascalate.concurrent.TestMultitargetExceptionTraces.b(TestMultitargetExceptionTraces.java:44)
			... 3 more

Is it enough? I see no reason to add arbitrary cause. Or I can: (A) add a cause when there is a single exception and do not add suppressed at all in this case OR (B) add all exceptions as suppressed when there are multiple.

Is it ok for you?

from tascalate-concurrent.

buko avatar buko commented on May 23, 2024

Adding all the exceptions as suppressed works fine. That kind of output is exactly what we're looking for and what we hope to find when we examine the cause/supressed exceptions.

I also think it would be a good idea for MultitargetException to override Throwable.getMessage(). Right now MultitargetException doesn't override this method and provide any summary of what happened. It would be good if MultitargetException could print a message summarizing what happened, even if the exception stack trace wasn't available. This could look like:

 public String getMessage() {
        List<Throwable> listCopy = getErrors();
        StringBuilder sb = new StringBuilder("A MultitargetException has " + listCopy.size() + " exceptions.  They are:\n");
        
        int lcv = 1;
        for (Throwable th : listCopy) {
            sb.append(lcv++ + ". " + th.getClass().getName() + ((th.getMessage() != null) ? ": " + th.getMessage() : "" ) + "\n");
        }
        
        return sb.toString();
    }

from tascalate-concurrent.

vsilaev avatar vsilaev commented on May 23, 2024

I will not overwrite getMessage -- it's used for dumping exceptions in Trowable.printStackTrace hence the output would contain a lot of duplicated (and, therefore, confusing) data. Instead, I'll try to override toString() -- should be enough. All the rest will be available via standard Trowable.printStackTrace functionality that dumps full info of regular cause and suppressed.

from tascalate-concurrent.

vsilaev avatar vsilaev commented on May 23, 2024

8debc4a

Indeed, I have to overwrite getMessage to include brief info about "nested" exceptions and toString to avoid using getMessage (infinite recurion otherwise).

Please get sources and check locally, the next build will be released within 2-5 days.

from tascalate-concurrent.

vsilaev avatar vsilaev commented on May 23, 2024

I take back my words about API abuse with addSuppressed.
java.net.URLClassLoader, method close -- there is some kind of "batch processing", and exceptions are handled exactly this way -- first one is a cause, others are suppressed. So this practice is somewhat normal.

from tascalate-concurrent.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.