You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Anton Tagunov <at...@mail.cnt.ru> on 2003/06/13 01:02:25 UTC

[RT] Minimizing stack traces on startup.

Hi, Leif, Berin and all!

Looks like the question of minimizing the stack traces
is still on the table. To me it splits into the following
sub-areas:

1) AbstractContainer throws a CompositeException from
   initialize()

   Good.

   AbstractContainer can be taught not to log
   anything itself. (Or log with level debug).

   Then we would be able to allow the invoker
   to do the logging.

   The invoker may safely omit stack traces
   for certain "safe" exceptions
       ConfigurationException
       ServiceException
       ContextException
   
   and print only the message.

2)
   But for this to be nice, it would be really
   good for every exception in CompositeException
   to carry info on what component caused the
   failure.

   What should this info be? The 'id' should be
   enough. Ok?

   How to pass id along with exception?

3)
   Pack the info into the CompositeException
   it would be very easy to provide a

   public String[] getIds();

   method that would return an array of ids.
   Very easy, but not generic enough IMO.
   
   With lazy initialization for instance
   it will also be nice to pack the id
   of the offending component along with
   the exception but we won't have a CompositeException
   to wrap it into then.

4)
   Pack the id into the Exception itself.
   The cleanest way, isn't it?
   Just what the Exception-s are for.

   <disclaimer>
   Gentlemen, I want to remark in advance
   that I will not feel at all offended if
   I hit a rock and it hurts, if I ask about
   extending some fundamentals of Avalon and
   I meet resistance - so please, no excuses,
   we are mates here -- I just love this word :-)
   so no bad feeling on my side will come - so
   no excuses, please!
   </disclaimer>

   Gentlemen it's beginning to be funny -- but
   again I feel like proposing to extend the Framework! :-)))

   ROTFL :-))

   But I do!

   We need to pack info on the component that caused
   an exception along with the info itself!

   Does it best fit to CascadingException? Or where?

   Okay, it must be too late now for me to decide this,
   but looks like the id should somehow be packed into
   the exception signalling its failure. Perhaps a
   Fortress-private exception

   * ComponentStartupFailed
   * ActivationFailed

   or something like this, it will have the id attached
   and enclose the exception.

5)

   Now the user-developer should be prepared to deal with it.
   Here we continue section 1) of this mail (plz see it again :-)

   I believe the algorithm should be the following:

   StringBuffer sb = new StringBuffer();
   buildMessage( e, sb );

   
   buildMessage( Throwable t, StringBuffer sb )
   {
       if ( e instanceof CompositeException )
       {
           for ( member in e.getExceptions() )
           {
               buildMessage( member, sb )
           }
       }
       else
       {
           eHasId = e carries a component id;
           
           if ( eHasId )
           {
               sb.append( "Activation failed for '" + e.id + "'
                       because of");
           }
           
           if ( eHasId && e is a "safe and envisioned" exception )
           {
               sb.append( getLastPart(e.getClass.getName()) +
                       e.getMessage() );
           }
           else
           {
               /* we did not envision this. give the stack trace
                  and thus force user-user to call the support,
                  something really bad happened */
               sb.append( e.getStackTrace() );
           }
           
           if ( e.getCause() != null )
           {
               sb.append( " caused by\n" );
               buildMessage( e.getCause, sb );
           }
       }
   }
   
Quite a bit of work. And this work is quite standard.
Probably we shouldn't load user with it. But who then?
I guess we should either teach all our loggers to do that
or just to provide an utility method somewhere to do that.
Again: to late an hour for me to make my mind :-)

6)

For this all to work smoothly with in particular
ConfigurationException we should make sure that

a) correct info on what component triggered the exception
   be available (with a stack trace we would deduct
   better or worse from the classname of the component)
   but if we cut the trace we strictly need the id
   
b) the best possible info on the location of the
   offending element inside the configuration file

We have covered a) in section 4.
Lets look closer at b). This info is available
from Configuration.getLocation(). Now we have to hook
it into the ConfigurationException. Currently I just
attach it to the message like
    new ConfigurationException( message + " at " + conf.getLocation())
however we should probably consider extending the
ConfigurationException with the info on location.

(Yes, again, extending the Framework, I must be mad :-)

What experience did you have gentlemen with this info
being kept separate from the message in SAXExcepton?
Good or Bad?

7)

ServiceManager exception. It looks pretty safe
not to print stack if we have the id of the
component that has caused it. We know what
ServiceManager it operates upon.

8)
And, a bit aside from this.
What on earth is a use case for background
activation of components (Fortress)?

Are these these the "active" components.
They do not passive. They do service incoming
servlet requests, they do not serve incoming JMS
messages, nothing.

Instead they are active. They send requests.
They send JMS messages.

Am I right?

If yes, then what should happen to the system
if activation of such component fails.

Nothing? Run okay?

This makes activation=="background"
identical to the notion of "optional" component,
not "optional" that can be configured on not be configured,
but "optional" that may start and may not start.

Was this the intent?

If no, how can we fix this?

If we decide that all the components are required,
then how do we shutdown the system once a "background"
component fails initialization?

And what about lazy initialization?
Do I get correctly that the inability to activate
a lazily-activatable component never will cause the
whole system to shut-down?


Oh, enough for one poor day,
WBR, Anton Tagunov


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Re[3]: [RT] Minimizing stack traces on startup.

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Peter Royal [mailto:proyal@apache.org] 
> > So this is what the user will get in log:
> >
> >     ActivationException: 'cool-component' caused by
> >         ConfigurationException: badly broken config:
> > file:/D:/conf/super.xconf:27
> 
> I like this.
> 
> As for stack trace suppression, I believe that should be done at the 
> logger level, rather than having 'no stack traces' be hardcoded. -pete

Agreed. (Configurable at logger level, not hard coded).

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Re[3]: [RT] Minimizing stack traces on startup.

Posted by Peter Royal <pr...@apache.org>.
On Friday, June 13, 2003, at 07:15  AM, Anton Tagunov wrote:
> we wrap the ConfigurationException (or a ServiceException
> for that case) into something like
>
>     o.a.a.fotress.ActivationException extends CascadingException
>     {
>         ActivationExcption( String id, Throwable t ) { super( id, t ); 
> }
>     }
>
> Goes without saying that for this exception we will produce no
> trace either.
>
> So this is what the user will get in log:
>
>     ActivationException: 'cool-component' caused by
>         ConfigurationException: badly broken config: 
> file:/D:/conf/super.xconf:27

I like this.

As for stack trace suppression, I believe that should be done at the 
logger level, rather than having 'no stack traces' be hardcoded.
-pete


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[3]: [RT] Minimizing stack traces on startup.

Posted by Anton Tagunov <at...@mail.cnt.ru>.
AT> ConfigurationException ... make sure this exception alone
AT> carries enough info to trace the problem, e.g. it has

AT> *   Configuration.getLocation() including full path name and line
AT>     number
AT> *   the id and probably type of the offending component

AT>     (that's what I'm thinking about - probably subclassing
AT>     ConfigurationException and adding the info there, or
AT>     putting it somehow into message, or changing the
AT>     ConfigurationException itself, or changing
AT>     CascadingException - you see I'm not afraid to touch
AT>     the most sacred things :-)

Have forgotten one more option, probably one of the easiest:

we wrap the ConfigurationException (or a ServiceException
for that case) into something like

    o.a.a.fotress.ActivationException extends CascadingException
    {
        ActivationExcption( String id, Throwable t ) { super( id, t ); }
    }

Goes without saying that for this exception we will produce no
trace either.

So this is what the user will get in log:

    ActivationException: 'cool-component' caused by
        ConfigurationException: badly broken config: file:/D:/conf/super.xconf:27

or at our desire we may completely make the logging
of ActivationException transparent:

    Failed to acitiavate component 'cool-component': ConfiguratonException: badly
    broken config: file:/D:/conf/super.xconf:27

(we still have two nested excptions, just the code is clever enough to
merge them into one line)

-Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [RT] Minimizing stack traces on startup.

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Leo!

LS> I'm jumping in on the discussion a bit late, so you may already 
LS> have covered this ground

No you're not! It's who is turning the discussion into this side.
It's me who comes up with the idea of cutting the stack trace
based on the exception type. So all comments welcome! :-)

LS>  - but I must admit to not really
LS> seeing the purpose of minimizing stack traces by not printing
LS> stack traces for certain exceptions.

Well, I think some exceptions are expected.
ConfigurationException is expected when users supply
invalid configuration.

Moreover, if we make sure this exception alone carries enough
info to trace the problem, e.g. it has

*   Configuration.getLocation() including full path name and line
    number
*   the id and probably type of the offending component

    (that's what I'm thinking about - probably subclassing
    ConfigurationException and adding the info there, or
    putting it somehow into message, or changing the
    ConfigurationException itself, or changing
    CascadingException - you see I'm not afraid to touch
    the most sacred things :-)

Anyway, if ConfigurationException has both location and
coponent information then we do not need a stack trace.

(Or need it when the level of logging is debug)

Moreover, a component id is somewhat better then
a stack trace. Stack trace gives only the class the caused
the exception and if we have several components of the same
class but with different ids, the id is better.

So, ConfigurationException is expected (as users mistype
the configuration for instance) and it is nice to print
only component id + location for it.

Now, if one component failed to startup we can either
* stop immediately (it would be okay to me)
* or do what currently fortress/impl/AbstractContainer.initialize()
  does - try to bring up all we can, collect all the exceptions
  and fail after that (I do not mind that also)

Well, I sort of do not want to change much if I can change little.
If AbstractContainer collects exceptions into a CompositeException
I do not mind.

But then I would like to nicely handle these exceptions also.
In fact if component A failed because it could not get component B
we also do not need a stack trace for this (unless we're at
DEBUG log level). So I was trying to break a path for it too.

To me the path looks somewhat like this: such a failure
most likely will be expressed as a ServiceException.

Very good. Now we should make sure that the ServiceException
has info conveyed on the id of the component _on behalf of which
the operation was attempted_ (again like with ConfigurationException
there are a plethora of options where we can put this info) and
we're fine: we do not need a stack trace again.

Same with ContextException, looks like we avoid the stack trace.
(But ContextException probably got into the list by mistake,
the original intention was to catch a ConfigurationException,
handle it nicely w/o a stack trace and handle the subsequent
ServiceExceptions equally nicely. Leif has made a valid point
that users get very frightened by stack traces and call him
for support as soon as they see one and I have found that
I'm doing exactly the same in my user code - I omit stack
traces for Cofiguration exceptions and I am very pleased
with the result so far.

Peter Royal has yet another approach: he has suggested
to have two logs: one user log without exceptions and
one developer's log with exceptions. Very nice indeed.
But I got to like so much to get little quite error
messages w/o stack traces in the developer's log too,
that I found it reasonable to continue discussion on
the topic. This is something I'm doing for myself
anyway. Probably this has value. Discussion will show! :-)
    
LS> The general consensus appears to be that if any component
LS> fails, the whole container & all components in it are essentially
LS> completely broken.
That would be fine by me, but currently Fortress runs differently.
And there some caveats: for instance with lazy or background
initialization how can you shut down the system if a component
initialization fails? So this probably works only with inline
initialization. Activation policy inline has (unintentionally?)
become the 'required component' policy as well.

LS> Thus, these exceptions should happen very rarely.
In fact I only want some certain cases (like broke config)
to be logger w/o stack traces. Of course all the unforseen
circumstances (including these rare catastrophes should be
logger completely, and if we're talking about this, it's
probably okay to make users call support in this case!).

LS> But when they do happen, having a full stack trace is very
LS> helpful. In fact, a constant annoyance for me is that
LS> an exception thrown in a SAX ContentHandler gets wrapped
LS> in a SAXException and appears like one, requiring manual
LS> unwrapping in order to figure out just what really happened!

Errr... terrible...

To me 2 things are BAD about SAX exception:

* the toString() method is just an assassination of a sane
  mind to be invoked - calling toString() of the nested
  exception - it is more then terrible IMO!
  
* a nesting mechanism different from getCause()
  yes, I guess SAXException was invented before JDK 1.4 :-)
  but now its a problem

The solution IMO is

a) never call toString() on SAXException (and hence on
   any exception probably), but to use

   t.getClass().getName() + ": " + t.getMessage()

   (getMessage() does not seem to be broken on SAXException
   if I'm not mistaken)

   if I'm not mistaken our current loggers all behave like this

b) to unwind nested exceptions not only look at getCause()
   but also check to see if we're dealing with a SAXException
   and in the latter case handle getException() identically
   to getCause(). Our logger do not do that ATM, AFAIK.

   Probably will teach them one day to do that.
   Or you will :-)

   I guess we could easily put that into Avalon formatter.

   Probably even in other formatters in log kit?

   Do you know by any chance what does Log4J do about it?
  
And don't get me wrong: when I speak about cutting stack
traces I _by no means do not want to_ cut nested exception
unwinding as well.

To be true I was thinking about adding the following formatter
to LogKit

<formatter>
  <format> ... %{message}.. </format>
  <no-stack>
     ConfigurationException
     ServiceException-
  </no-stack>
</formatter>

you see those minus? ('-')?
I wanted it to denote that the nested exceptions shouldn't
be unwinded for that exactly exception. But I wanted that
to be optional.

Instead I wanted the unwinding to happen, but the stacks
to be cut _at the inner levels too_ by the same rule for
all levels. So we could have

ActivationFailedException: id='k'
  caused by: ConfigurationException: id='k': foo bar:file:/D:/conf/a.xconf:22
    caused by: ... (why not?)
  

LS> So policy should be this:

LS>   1. Always err
?? what is it ?? :-)

LS> on the side of printing when printing
LS>      stack traces.
LS> Print too much rather than too little.
Well my preference would be for this to happen only
when log level is DEBUG.
I keep more to Leif's opinion that it the stack traces should
be cut for ConfigurationException rather then with Peter Royal's
that we should have two logs (may change my mind in the future :-)

LS>   2. It is better to just *stop* the initialization process
LS>      at the first exception.
It would be okay by me, but
a) it is not now that way
b) lazy and background initialization policies spoil this nice
   intention to fail fast, don't they?


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: [RT] Minimizing stack traces on startup.

Posted by Leo Sutic <le...@inspireinfrastructure.com>.
Anton,

I'm jumping in on the discussion a bit late, so you may already 
have covered this ground - but I must admit to not really
seeing the purpose of minimizing stack traces by not printing
stack traces for certain exceptions.

The general consensus appears to be that if any component
fails, the whole container & all components in it are essentially
completely broken.

Thus, these exceptions should happen very rarely.

But when they do happen, having a full stack trace is very
helpful. In fact, a constant annoyance for me is that
an exception thrown in a SAX ContentHandler gets wrapped
in a SAXException and appears like one, requiring manual
unwrapping in order to figure out just what really happened!

So policy should be this:

  1. Always err on the side of printing when printing
     stack traces. Print too much rather than too little.

  2. It is better to just *stop* the initialization process
     at the first exception.

/LS

> -----Original Message-----
> From: Anton Tagunov [mailto:atagunov@mail.cnt.ru] 
> Sent: den 13 juni 2003 01:02
> To: Avalon Developers List
> Subject: [RT] Minimizing stack traces on startup.
> 
> 
> Hi, Leif, Berin and all!
> 
> Looks like the question of minimizing the stack traces
> is still on the table. To me it splits into the following
> sub-areas:
> 
> 1) AbstractContainer throws a CompositeException from
>    initialize()
> 
>    Good.
> 
>    AbstractContainer can be taught not to log
>    anything itself. (Or log with level debug).
> 
>    Then we would be able to allow the invoker
>    to do the logging.
> 
>    The invoker may safely omit stack traces
>    for certain "safe" exceptions
>        ConfigurationException
>        ServiceException
>        ContextException
>    
>    and print only the message.
> 
> 2)
>    But for this to be nice, it would be really
>    good for every exception in CompositeException
>    to carry info on what component caused the
>    failure.
> 
>    What should this info be? The 'id' should be
>    enough. Ok?
> 
>    How to pass id along with exception?
> 
> 3)
>    Pack the info into the CompositeException
>    it would be very easy to provide a
> 
>    public String[] getIds();
> 
>    method that would return an array of ids.
>    Very easy, but not generic enough IMO.
>    
>    With lazy initialization for instance
>    it will also be nice to pack the id
>    of the offending component along with
>    the exception but we won't have a CompositeException
>    to wrap it into then.
> 
> 4)
>    Pack the id into the Exception itself.
>    The cleanest way, isn't it?
>    Just what the Exception-s are for.
> 
>    <disclaimer>
>    Gentlemen, I want to remark in advance
>    that I will not feel at all offended if
>    I hit a rock and it hurts, if I ask about
>    extending some fundamentals of Avalon and
>    I meet resistance - so please, no excuses,
>    we are mates here -- I just love this word :-)
>    so no bad feeling on my side will come - so
>    no excuses, please!
>    </disclaimer>
> 
>    Gentlemen it's beginning to be funny -- but
>    again I feel like proposing to extend the Framework! :-)))
> 
>    ROTFL :-))
> 
>    But I do!
> 
>    We need to pack info on the component that caused
>    an exception along with the info itself!
> 
>    Does it best fit to CascadingException? Or where?
> 
>    Okay, it must be too late now for me to decide this,
>    but looks like the id should somehow be packed into
>    the exception signalling its failure. Perhaps a
>    Fortress-private exception
> 
>    * ComponentStartupFailed
>    * ActivationFailed
> 
>    or something like this, it will have the id attached
>    and enclose the exception.
> 
> 5)
> 
>    Now the user-developer should be prepared to deal with it.
>    Here we continue section 1) of this mail (plz see it again :-)
> 
>    I believe the algorithm should be the following:
> 
>    StringBuffer sb = new StringBuffer();
>    buildMessage( e, sb );
> 
>    
>    buildMessage( Throwable t, StringBuffer sb )
>    {
>        if ( e instanceof CompositeException )
>        {
>            for ( member in e.getExceptions() )
>            {
>                buildMessage( member, sb )
>            }
>        }
>        else
>        {
>            eHasId = e carries a component id;
>            
>            if ( eHasId )
>            {
>                sb.append( "Activation failed for '" + e.id + "'
>                        because of");
>            }
>            
>            if ( eHasId && e is a "safe and envisioned" exception )
>            {
>                sb.append( getLastPart(e.getClass.getName()) +
>                        e.getMessage() );
>            }
>            else
>            {
>                /* we did not envision this. give the stack trace
>                   and thus force user-user to call the support,
>                   something really bad happened */
>                sb.append( e.getStackTrace() );
>            }
>            
>            if ( e.getCause() != null )
>            {
>                sb.append( " caused by\n" );
>                buildMessage( e.getCause, sb );
>            }
>        }
>    }
>    
> Quite a bit of work. And this work is quite standard.
> Probably we shouldn't load user with it. But who then?
> I guess we should either teach all our loggers to do that
> or just to provide an utility method somewhere to do that.
> Again: to late an hour for me to make my mind :-)
> 
> 6)
> 
> For this all to work smoothly with in particular 
> ConfigurationException we should make sure that
> 
> a) correct info on what component triggered the exception
>    be available (with a stack trace we would deduct
>    better or worse from the classname of the component)
>    but if we cut the trace we strictly need the id
>    
> b) the best possible info on the location of the
>    offending element inside the configuration file
> 
> We have covered a) in section 4.
> Lets look closer at b). This info is available
> from Configuration.getLocation(). Now we have to hook
> it into the ConfigurationException. Currently I just
> attach it to the message like
>     new ConfigurationException( message + " at " + 
> conf.getLocation()) however we should probably consider 
> extending the ConfigurationException with the info on location.
> 
> (Yes, again, extending the Framework, I must be mad :-)
> 
> What experience did you have gentlemen with this info
> being kept separate from the message in SAXExcepton?
> Good or Bad?
> 
> 7)
> 
> ServiceManager exception. It looks pretty safe
> not to print stack if we have the id of the
> component that has caused it. We know what
> ServiceManager it operates upon.
> 
> 8)
> And, a bit aside from this.
> What on earth is a use case for background
> activation of components (Fortress)?
> 
> Are these these the "active" components.
> They do not passive. They do service incoming
> servlet requests, they do not serve incoming JMS
> messages, nothing.
> 
> Instead they are active. They send requests.
> They send JMS messages.
> 
> Am I right?
> 
> If yes, then what should happen to the system
> if activation of such component fails.
> 
> Nothing? Run okay?
> 
> This makes activation=="background"
> identical to the notion of "optional" component,
> not "optional" that can be configured on not be configured,
> but "optional" that may start and may not start.
> 
> Was this the intent?
> 
> If no, how can we fix this?
> 
> If we decide that all the components are required,
> then how do we shutdown the system once a "background" 
> component fails initialization?
> 
> And what about lazy initialization?
> Do I get correctly that the inability to activate
> a lazily-activatable component never will cause the
> whole system to shut-down?
> 
> 
> Oh, enough for one poor day,
> WBR, Anton Tagunov
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
> For additional commands, e-mail: dev-help@avalon.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org