Re: [log4perl-devel] logger state is global

2011-01-26 Thread Tom Metro
Mike Schilli wrote:
 Tom Metro wrote:
 It came about because the $logger object doesn't actually convey the
 full state, so when serialized and passed to a remote method, the
 remote logging reverts to default logging settings.
 
 Yeah, the way it's currently implemented, a logger is only meaningful
 within an initialized Log4perl-system, there's some system-global magic
 involved, and you cannot serialize a logger and plant it into
 another Log4perl-enabled system at runtime easily (yet).
 
 Can you explain more about what the use case is for serializing loggers
 and passing them to remote systems?

Sure. This is part of a parallel processing cluster. Class::Remote is
used to execute code on remote nodes of the cluster. I'd like to be able
to have a single configured logger object used for the controlling node
(local) and then be able to serialize it and pass it to a remote node so
it can log with the identical settings.


 What properties of the logger might be of interest to the remote
 system?

The better questions is what logger state information can't practically
be serialized?


 Is the remote system running Log4perl with exactly the same appenders
 or different ones?

In this case I know the answer is exactly the same - everything is
outputting to STDOUT. But generally speaking, I'm not sure I know what
you mean.

Are you asking whether the remote system has the same appender drivers
installed? Or are you asking whether the remote system will be logging
to identical paths?

I don't think as a module implementer you need to be concerned with
that. If the paths are not identical, then having fixup code on the
remote side will be an obvious requirement. And similarly, an
experienced developer will know better than to write to a network
mounted log file from multiple machines simultaneously.


 I assume that this practice of maintaining global state in Log4perl
 came about because it is convenient to be able to call get_logger() as
 a class method, rather than having the application pass an object
 around.  But it seems that it would be way better if Log4perl was
 internally designed to store all state in instance variables, and
 leave it to the application developer to decide whether they want to
 pass around objects, or dedicate a global variable to it.
 
 Agreed.

OK, so what can we do to start refactoring the code to have the more
desired architecture?


 Ultimately I want a method I can call from my libraries where I can
 pass in a $logger parameter. The method then looks to see if $logger
 is set to anything, and if it is, clones it, sets the category, and
 returns the object.
 
 Hmm, that's similar to how the class method is defined. If the logger
 for the category exists, you get a copy, if it isn't, you get a new
 instance. We could implement an object method that does what you've
 suggested, can you post some code to display how your class hierarchy
 looks like and how you call the metods of the derived class from your
 application?

Sure.

By illustration, here's a sticky situation I'm dealing with right now.

In the controller, I have code approximately like:

  my $logger = Publisher::Logger-init;
  ...
  my $parallel_agents = Parallel::Cluster-new({
  agent_lib = 'Some::Agent::Class',
  logger= $logger,
  });
  $parallel_agents-run();

This initializes a logger object, instantiates the parallel processing
system, passing in the logger object, which in turn will get passed to
the constructor of Some::Agent::Class, and kicks off the run.

Parallel::Cluster implements a map-reduce algorithm, where portions
(some instances of Some::Agent::Class) are executed locally on the
controlling node, while other portions (mapping) happen remotely via
Class::Remote.

If the agent code attempts to use $logger locally, it works as expected.
If they use it remotely, nothing gets output.

Looking at a dump of the $logger object shows little difference between
the working local version and the not working remote version:

local
Address: Publisher::Logger=HASH(0x41f9dc0)@15665
$logger = bless( {
   'is_OFF' = sub { DUMMY },
   'is_DEBUG' = sub { DUMMY },
   'ERROR' = sub { DUMMY },
   'is_INFO' = sub { DUMMY },
   'layout' = undef,
   'category' = 'main',
   'is_TRACE' = sub { DUMMY },
   'DEBUG' = $logger-{'ERROR'},
   'is_ALL' = sub { DUMMY },
   'additivity' = 1,
   'TRACE' = sub { DUMMY },
   'ALL' = $logger-{'TRACE'},
   'is_FATAL' = sub { DUMMY },
   'is_WARN' = sub { DUMMY },
   'FATAL' = $logger-{'ERROR'},
   'appender_names' = [
 'app001'
   ],
   'WARN' = $logger-{'ERROR'},
   'INFO' = $logger-{'ERROR'},
   

Re: [log4perl-devel] logger state is global

2010-11-27 Thread Mike Schilli
On Thu, 18 Nov 2010, Tom Metro wrote:

 It came about because the $logger object doesn't actually convey the
 full state, so when serialized and passed to a remote method, the
 remote logging reverts to default logging settings.

Yeah, the way it's currently implemented, a logger is only meaningful
within an initialized Log4perl-system, there's some system-global magic
involved, and you cannot serialize a logger and plant it into
another Log4perl-enabled system at runtime easily (yet).

Can you explain more about what the use case is for serializing loggers
and passing them to remote systems? What properties of the logger might
be of interest to the remote system? Is the remote system running
Log4perl with exactly the same appenders or different ones?

 (On a side note, I had to rewrite easy_init() in order to make it
 subclass friendly. We can discuss that further in a separate thread,
 if interested.)

Sure.

 I assume that this practice of maintaining global state in Log4perl
 came about because it is convenient to be able to call get_logger() as
 a class method, rather than having the application pass an object
 around.  But it seems that it would be way better if Log4perl was
 internally designed to store all state in instance variables, and
 leave it to the application developer to decide whether they want to
 pass around objects, or dedicate a global variable to it.

Agreed.

 When I fixed the library code to use
 Log::Log4perl-get_logger($class), my first attempt was actually to
 pass a logger object to the library, and call
 $logger-get_logger($class), assuming get_logger($class) would clone
 $logger, set the category, and return a new logger. Instead it fails
 in Log::Log4perl-_new() when it tries to bless the already blessed
 object.

Yes, get_logger() is a class method, calling it by an object is not
defined. We should have a better error message, though.

 Ultimately I want a method I can call from my libraries where I can
 pass in a $logger parameter. The method then looks to see if $logger
 is set to anything, and if it is, clones it, sets the category, and
 returns the object.

Hmm, that's similar to how the class method is defined. If the logger
for the category exists, you get a copy, if it isn't, you get a new
instance. We could implement an object method that does what you've
suggested, can you post some code to display how your class hierarchy
looks like and how you call the metods of the derived class from your
application?

-- Mike

Mike Schilli
m...@perlmeister.com

--
Increase Visibility of Your 3D Game App  Earn a Chance To Win $500!
Tap into the largest installed PC base  get more eyes on your game by
optimizing for Intel(R) Graphics Technology. Get started today with the
Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs.
http://p.sf.net/sfu/intelisp-dev2dev
___
log4perl-devel mailing list
log4perl-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/log4perl-devel


[log4perl-devel] logger state is global

2010-11-16 Thread Tom Metro
I like the API Log::Log4perl provides, but using Log::Log4perl v1.28
I've encountered issues with the internal implementation that have been
very time consuming to resolve.

Most relate to the way Log4perl seems to store state in global or class
variables rather than in object or instance variables. This means that
unless you take extra steps to prevent it, library modules that call
upon Log4perl directly will stomp on the logger established by the
calling code.

This state mechanism also is incompatible with Class::Remote (a module
developed at Shopzilla for remote code execution, which apparently
hasn't been released to CPAN), as it attempts to serialize an object's
data and send it to the remote end.

Perhaps all this is a consequence of our use of easy_init(), though if
so, convenience methods shouldn't have the consequence of creating a
fragile system.

The general objectives I'd like to achieve are:

1. Ability to create a library module that can use Log4perl, such that
if the calling code makes no use of Log4perl, it logs independently with
locally specified defaults, but if the caller does use Log4perl, it
picks up the callers settings.

2. Fully serializable state.


Here's an example of an issue I ran into today. I had a block of code
being evaluated that contained an error. The eval() was followed by an
error check, which then called logdie() with $...@. But post-evaluation,
logdie() or any other Log4perl method failed to produce any output,
resulting the program mysteriously exiting with no error.

A trace showed that $self-is_fatal(), as called by
Log::Log4perl::Logger-logdie(), which resolved to:
return sub { $return_token };
which apparently returned false, meaning that FATAL level logging is
disabled, which should never be the case.

The trigger for the problem turned out to be a 'use' call in the eval'ed
code that loaded a library which internally called easy_init() (yet
specifying the INFO logging level).

This seems broken that a library using normal Log4perl methods can trash
the logger in use by the calling code.

Is there a more correct way to be using the API to avoid this, or does
Log4perl need some internal refactoring?

 -Tom

--
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2  L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today
http://p.sf.net/sfu/msIE9-sfdev2dev
___
log4perl-devel mailing list
log4perl-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/log4perl-devel


Re: [log4perl-devel] logger state is global

2010-11-16 Thread Mike Schilli
On Tue, 16 Nov 2010, Tom Metro wrote:

 1. Ability to create a library module that can use Log4perl, such that
 if the calling code makes no use of Log4perl, it logs independently
 with locally specified defaults, but if the caller does use Log4perl,
 it picks up the callers settings.
Hi Tom,

the current Log4perl implementation assumes that the calling script
initializes Log4perl and libraries don't. Libraries make use of
Log4perl by issuing log statements, but they don't try to modify the
inititalization. If Log4perl isn't initialized in the main program, all
is quiet.

 The trigger for the problem turned out to be a 'use' call in the eval'ed
 code that loaded a library which internally called easy_init() (yet
 specifying the INFO logging level).

That's very confusing and should be avoided at all cost.

 This seems broken that a library using normal Log4perl methods can trash
 the logger in use by the calling code.

That library wasn't using 'normal Log4perl methods', but was clobbering
the settings. We discourage people from doing that, although we don't
stop anyone shooting themselves in the foot (or putting up a module on
CPAN that shoots everyone in the foot for that matter).

But you're bringing up an interesting topic: What would be a good
approach to allow a library to meddle with Log4perl's settings, in the
absence or even presence of a previous initialization?

Everything I've seen so far is just plain confusing to the end user. I'm
open to ideas, however.


-- Mike

Mike Schilli
m...@perlmeister.com

--
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2  L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today
http://p.sf.net/sfu/msIE9-sfdev2dev
___
log4perl-devel mailing list
log4perl-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/log4perl-devel