SlideShare a Scribd company logo
1 of 205
Easy Logging
with Log::Message::Structured and Message::Passing
Me
Damien 'dams' Krotkine

Paris.pm member

French Perl Monger vice-president

Perl Dancer developer

11 modules on CPAN
    (pretty weak)

Author of Moderne Perl
 (french book, go buy it)
• Let’s say I have a big application
• Let’s say I have a big application
• It processes a lot of data
• Let’s say I have a big application
• It processes a lot of data
• It computes lots of lines
• Let’s say I have a big application
• It processes a lot of data
• It computes lots of lines
• Per user, and per account
account 1
user 1
         lines

user 2

                                  process
user 3


                      account n                 result

                         running on multiple hosts
• It runs fine
• It runs fine
• Well, more or less
• It runs fine
• Well, more or less
• I’d like to know what’s going on with it
When the app crashes
When the app crashes

• Why did it crash ? ( reason, stack trace )
When the app crashes

• Why did it crash ? ( reason, stack trace )
• At crash time
When the app crashes

• Why did it crash ? ( reason, stack trace )
• At crash time
 • What was the situation ?
When the app crashes

• Why did it crash ? ( reason, stack trace )
• At crash time
 • What was the situation ?
 • What was the data it was processing ?
When there are issues
When there are issues

• How bad is this failure ?
When there are issues

• How bad is this failure ?
• Why did it fail to process this line ?
When there are issues

• How bad is this failure ?
• Why did it fail to process this line ?
• Is it only this line ?
When there are issues

• How bad is this failure ?
• Why did it fail to process this line ?
• Is it only this line ?
• Is it reproducible ?
When there are issues

• How bad is this failure ?
• Why did it fail to process this line ?
• Is it only this line ?
• Is it reproducible ?
• Does the rest fail ? (user, account)
When the app runs fine
When the app runs fine

• Information harvesting loop
When the app runs fine

• Information harvesting loop
 • 1: get more info about the process run
When the app runs fine

• Information harvesting loop
 • 1: get more info about the process run
 • 2: go see my boss/colleague/...
When the app runs fine

• Information harvesting loop
 • 1: get more info about the process run
 • 2: go see my boss/colleague/...
 • 3: (s)he asks something I don’t know
When the app runs fine

• Information harvesting loop
 • 1: get more info about the process run
 • 2: go see my boss/colleague/...
 • 3: (s)he asks something I don’t know
 • 4: go back to step 1
So yeah, I need some logs
So yeah, I need some logs


But we knew that, didn’t we ?
Logs
Logs
Logs
Exceptions
Exceptions
Exceptions

• An exception is an issue
Exceptions

• An exception is an issue
• All issues are not fatal (important)
Exceptions

• An exception is an issue
• All issues are not fatal (important)
• So, try / catch !
Exception Module
Exception Module
• Pick your own from CPAN
Exception Module
• Pick your own from CPAN
• I wrote mine anyway :)
Exception Module
• Pick your own from CPAN
• I wrote mine anyway :)
• Dancer::Exception
Exception Module
• Pick your own from CPAN
• I wrote mine anyway :)
• Dancer::Exception
• Extracted it as a standalone module
Exception Module
• Pick your own from CPAN
• I wrote mine anyway :)
• Dancer::Exception
• Extracted it as a standalone module
• Exceptions are objects with message
  pattern, stack trace... raise(), throw(),
  register(), introspection
Exception Module
• Pick your own from CPAN
• I wrote mine anyway :)
• Dancer::Exception
• Extracted it as a standalone module
• Exceptions are objects with message
  pattern, stack trace... raise(), throw(),
  register(), introspection
• Should end up on CPAN one day
foreach account {
    try {
        foreach user {
            try {
                foreach data line {
                    try {
                        process_line()
                    } catch {
                        log warning
                    };
                }
            } catch {
                log important
            };
        }
    } catch {
        log important
    };
}
log fatal
Logs
Logging a line
Logging a line
• say "warning, data is not good"
Logging a line
• say "warning, data is not good"
• say "warning, data '$data' is not good"
Logging a line
• say "warning, data is not good"
• say "warning, data '$data' is not good"
• say "$level, data '$data' is not good"
Logging a line
• say "warning, data is not good"
• say "warning, data '$data' is not good"
• say "$level, data '$data' is not good"
• log( in_file => "$level, '$data' is not good")
Logging a line
• say "warning, data is not good"
• say "warning, data '$data' is not good"
• say "$level, data '$data' is not good"
• log( in_file => "$level, '$data' is not good")
•   my $logger = MyOwnLogger->new(write_in => 'file',
    display_level => 'WARNING');
Logging a line
• say "warning, data is not good"
• say "warning, data '$data' is not good"
• say "$level, data '$data' is not good"
• log( in_file => "$level, '$data' is not good")
•   my $logger = MyOwnLogger->new(write_in => 'file',
    display_level => 'WARNING');

•   $logger->log(warning =>"$Level, '$data' is not good");
Logging a line
• say "warning, data is not good"
• say "warning, data '$data' is not good"
• say "$level, data '$data' is not good"
• log( in_file => "$level, '$data' is not good")
•   my $logger = MyOwnLogger->new(write_in => 'file',
    display_level => 'WARNING');

•   $logger->log(warning =>"$Level, '$data' is not good");

•   Put that in a function, then a module, etc
Logging a line
• say "warning, data is not good"
• say "warning, data '$data' is not good"
• say "$level, data '$data' is not good"
• log( in_file => "$level, '$data' is not good")
•   my $logger = MyOwnLogger->new(write_in => 'file',
    display_level => 'WARNING');

•   $logger->log(warning =>"$Level, '$data' is not good");

•   Put that in a function, then a module, etc
The wheel...
The wheel...
• Home-made logging system : I've seen that
  in every single company I've worked.
The wheel...
• Home-made logging system : I've seen that
  in every single company I've worked.
• Sometimes multiple home-made logging
  system in a single company
The wheel...
• Home-made logging system : I've seen that
  in every single company I've worked.
• Sometimes multiple home-made logging
  system in a single company

• Sometimes multiple home-made logging
  system in a single project
The wheel...
• Home-made logging system : I've seen that
  in every single company I've worked.
• Sometimes multiple home-made logging
  system in a single company

• Sometimes multiple home-made logging
  system in a single project
• It's so easy to start with a print STDERR...
The wheel...
• Home-made logging system : I've seen that
  in every single company I've worked.
• Sometimes multiple home-made logging
  system in a single company

• Sometimes multiple home-made logging
  system in a single project
• It's so easy to start with a print STDERR...
• Stop reinventing the wheel
Pick up a logger
Pick up a logger
• Many Log modules on CPAN
Pick up a logger
• Many Log modules on CPAN
• Pick one you like
Pick up a logger
• Many Log modules on CPAN
• Pick one you like
• I choose Log::Dispatch
Pick up a logger
• Many Log modules on CPAN
• Pick one you like
• I choose Log::Dispatch
•   $log->log(level => 'info', message => 'Blah' );
Pick up a logger
• Many Log modules on CPAN
• Pick one you like
• I choose Log::Dispatch
•   $log->log(level => 'info', message => 'Blah' );


• Good ?
Pick up a logger
• Many Log modules on CPAN
• Pick one you like
• I choose Log::Dispatch
•   $log->log(level => 'info', message => 'Blah' );


• Good ?
• No, we are still nowhere !
Pick up a logger
• Many Log modules on CPAN
• Pick one you like
• I choose Log::Dispatch
•   $log->log(level => 'info', message => 'Blah' );


• Good ?
• No, we are still nowhere !
• We want contextual information
Contextual information
Contextual information
• What do we need to log ?
Contextual information
• What do we need to log ?
• A log message - ok, but
Contextual information
• What do we need to log ?
• A log message - ok, but
• Hardware info (Mem, CPU, disk, host)
Contextual information
• What do we need to log ?
• A log message - ok, but
• Hardware info (Mem, CPU, disk, host)
• Software info (time, user / account id...)
Contextual information
• What do we need to log ?
• A log message - ok, but
• Hardware info (Mem, CPU, disk, host)
• Software info (time, user / account id...)
• Message (filename, line nb, stacktrace...)
Contextual information
• What do we need to log ?
• A log message - ok, but
• Hardware info (Mem, CPU, disk, host)
• Software info (time, user / account id...)
• Message (filename, line nb, stacktrace...)
• Log line = mix contextual and specific info
Contextual information
• What do we need to log ?
• A log message - ok, but
• Hardware info (Mem, CPU, disk, host)
• Software info (time, user / account id...)
• Message (filename, line nb, stacktrace...)
• Log line = mix contextual and specific info
• Even with a great logger, need to build that
Richer logging
Richer logging
• How to pack these information together ?
Richer logging
• How to pack these information together ?
• Use a key-value structure
Richer logging
• How to pack these information together ?
• Use a key-value structure
• Better: a class, fields are attributes
Richer logging
• How to pack these information together ?
• Use a key-value structure
• Better: a class, fields are attributes
• So we can benefit of defaults, lazyness, etc
Richer logging
• How to pack these information together ?
• Use a key-value structure
• Better: a class, fields are attributes
• So we can benefit of defaults, lazyness, etc
• One log line = one class instance
Richer logging
• How to pack these information together ?
• Use a key-value structure
• Better: a class, fields are attributes
• So we can benefit of defaults, lazyness, etc
• One log line = one class instance
• We need it as a string at the end
Richer logging
• How to pack these information together ?
• Use a key-value structure
• Better: a class, fields are attributes
• So we can benefit of defaults, lazyness, etc
• One log line = one class instance
• We need it as a string at the end
• So stringify to JSON,YAML...
Log::Message::Structured
Log::Message::Structured
 • A set of roles, consume in MyEvent class
Log::Message::Structured
 • A set of roles, consume in MyEvent class
 • 4 types of roles :
Log::Message::Structured
 • A set of roles, consume in MyEvent class
 • 4 types of roles :
  • L::M::S : basic setup + "" overloading
Log::Message::Structured
 • A set of roles, consume in MyEvent class
 • 4 types of roles :
  • L::M::S : basic setup + "" overloading
  • L::M::S::Components : provides ready to
     use additional fields
Log::Message::Structured
 • A set of roles, consume in MyEvent class
 • 4 types of roles :
  • L::M::S : basic setup + "" overloading
  • L::M::S::Components : provides ready to
     use additional fields
  • L::M::S::Stringify : provides stringifiers
Log::Message::Structured
 • A set of roles, consume in MyEvent class
 • 4 types of roles :
  • L::M::S : basic setup + "" overloading
  • L::M::S::Components : provides ready to
     use additional fields
   • L::M::S::Stringify : provides stringifiers
 • Your custom fields : additional attributes
package MyLogEvent; use Moose;
with qw/
    Log::Message::Structured
    Log::Message::Structured::Component::Date
    Log::Message::Structured::Component::Hostname
    Log::Message::Structured::Stringify::AsJSON
/;
has message => ( is => 'ro', required => 1);
has account_id => ( is => 'ro', required => 1);
has user_id => ( is => 'ro' );
package MyLogEvent; use Moose;
with qw/
    Log::Message::Structured
    Log::Message::Structured::Component::Date
    Log::Message::Structured::Component::Hostname
    Log::Message::Structured::Stringify::AsJSON
/;
has message => ( is => 'ro', required => 1);
has account_id => ( is => 'ro', required => 1);
has user_id => ( is => 'ro' );

                      ...elsewhere...
package MyLogEvent; use Moose;
with qw/
    Log::Message::Structured
    Log::Message::Structured::Component::Date
    Log::Message::Structured::Component::Hostname
    Log::Message::Structured::Stringify::AsJSON
/;
has message => ( is => 'ro', required => 1);
has account_id => ( is => 'ro', required => 1);
has user_id => ( is => 'ro' );

                      ...elsewhere...
use My::Log::Event;
$logger->log( warning => MyLogEvent->new(
                account_id => 42,
                user_id => 12,
                message => "watch out! behind you!" ));
package MyLogEvent; use Moose;
with qw/
    Log::Message::Structured
    Log::Message::Structured::Component::Date
    Log::Message::Structured::Component::Hostname
    Log::Message::Structured::Stringify::AsJSON
/;
has message => ( is => 'ro', required => 1);
has account_id => ( is => 'ro', required => 1);
has user_id => ( is => 'ro' );

                      ...elsewhere...
use My::Log::Event;
$logger->log( warning => MyLogEvent->new(
                account_id => 42,
                user_id => 12,
                message => "watch out! behind you!" ));


 That's sending the stringified JSON to Log::Dispatch
Outputs as log:

'{"__CLASS__":"MyLogEvent",
"account_id":42,
"user_id":42,
"date":"2010-03-28T23:15:52Z",
"hostname":"mymachine.domain",
message=>"watch out! behind you!"}'
Outputs as log:

'{"__CLASS__":"MyLogEvent",
"account_id":42,
"user_id":42,
"date":"2010-03-28T23:15:52Z",
"hostname":"mymachine.domain",
message=>"watch out! behind you!"}'




      L::M::S also supports options passed on the
      command line
Outputs as log:

'{"__CLASS__":"MyLogEvent",
"account_id":42,
"user_id":42,
"date":"2010-03-28T23:15:52Z",
"hostname":"mymachine.domain",
message=>"watch out! behind you!"}'




      L::M::S also supports options passed on the
      command line
$ my_program.pl --account_id=42
Let's shorten the code
In my application I have:
Let's shorten the code
      In my application I have:
while (my $account_id = AccountIterator->next) {
  while (my $user_id = UserIterator->next) {
    while (my $data_line = DataIterator->next) {
      ... do stuff ...
Let's shorten the code
      In my application I have:
while (my $account_id = AccountIterator->next) {
  while (my $user_id = UserIterator->next) {
    while (my $data_line = DataIterator->next) {
      ... do stuff ...

package MyLogEvent; use Moose;
with qw/Log::Message::Structured .... /;
use AccountIterator; use UserIterator;
has account_id => ( is => 'ro',
             default => sub { AccountIterator->current } );
has user_id => ( is => 'ro',
             default => sub { UserIterator->current } );
Let's shorten the code
Let's shorten the code
Wrap Log::Dispatch call + L::M::S
Let's shorten the code
      Wrap Log::Dispatch call + L::M::S
log_warning( message => "Achtung!");
Let's shorten the code
      Wrap Log::Dispatch call + L::M::S
log_warning( message => "Achtung!");

       actually calls
Let's shorten the code
      Wrap Log::Dispatch call + L::M::S
log_warning( message => "Achtung!");

       actually calls
$logger->log( warning => MyLogEvent->new( @_ );
Let's shorten the code
      Wrap Log::Dispatch call + L::M::S
log_warning( message => "Achtung!");

       actually calls
$logger->log( warning => MyLogEvent->new( @_ );

       outputs
Let's shorten the code
      Wrap Log::Dispatch call + L::M::S
log_warning( message => "Achtung!");

       actually calls
$logger->log( warning => MyLogEvent->new( @_ );

       outputs
'{"__CLASS__":"MyLogEvent",
"account_id":42,
"user_id":42,
"date":"2010-03-28T23:15:52Z",
"hostname":"mymachine.domain",
message=>"Achtung!"}'
Exceptions...
Remember ?
Exceptions...
        Remember ?
try { ... } catch {
    log_warning(exception => $_ )
};
Exceptions...
           Remember ?
   try { ... } catch {
       log_warning(exception => $_ )
   };

• To be able to write that, you need in your
  MyLogEvent class:
Exceptions...
            Remember ?
   try { ... } catch {
       log_warning(exception => $_ )
   };

• To be able to write that, you need in your
  MyLogEvent class:
• these attributes : 'exception', 'stack_trace',
Exceptions...
            Remember ?
   try { ... } catch {
       log_warning(exception => $_ )
   };

• To be able to write that, you need in your
  MyLogEvent class:
• these attributes : 'exception', 'stack_trace',
• with a BUILDARGS
Exceptions...
            Remember ?
   try { ... } catch {
       log_warning(exception => $_ )
   };

• To be able to write that, you need in your
  MyLogEvent class:
• these attributes : 'exception', 'stack_trace',
• with a BUILDARGS
• that looks at the exception, and set the
  'message' and the 'stack_trace' arguments
around BUILDARGS => sub {
    my $orig = shift;
    my $class = shift;

     my $h = $class->$orig(@_);

     my $e = $h->{exception}
       or return $h;

     if ( blessed($e) &&   $e->isa('My::Exception::Base') ) {
         $h->{message} =   $e->message;
         $h->{shortmess}   = $e->{_shortmess};
     } else {
         $h->{message} =   $e
     }
     return $h;
};
around BUILDARGS => sub {
    my $orig = shift;
    my $class = shift;

     my $h = $class->$orig(@_);

     my $e = $h->{exception}
       or return $h;

     if ( blessed($e) &&   $e->isa('My::Exception::Base') ) {
         $h->{message} =   $e->message;
         $h->{shortmess}   = $e->{_shortmess};
     } else {
         $h->{message} =   $e
     }
     return $h;
};

try { ... } catch {
    log_warning(exception => $_ )
                                            That would now
};                                              work !
Log::Message::Structured
Log::Message::Structured
 • Does the job
Log::Message::Structured
 • Does the job
 • Please contribute
Log::Message::Structured
 • Does the job
 • Please contribute
  • we need more components
Log::Message::Structured
 • Does the job
 • Please contribute
  • we need more components
  • we need more stringifiers
Log::Message::Structured
 • Does the job
 • Please contribute
  • we need more components
  • we need more stringifiers
  • compatibility with Moo
Log::Message::Structured
 • Does the job
 • Please contribute
  • we need more components
  • we need more stringifiers
  • compatibility with Moo
 • On CPAN / github
• We have all we need as JSON
• We have all we need as JSON
• But that's not enough :(
• We have all we need as JSON
• But that's not enough :(
• Your boss wants to look at the log
• We have all we need as JSON
• But that's not enough :(
• Your boss wants to look at the log
 • => provide a simple interface
• We have all we need as JSON
• But that's not enough :(
• Your boss wants to look at the log
 • => provide a simple interface
• You need to do complex lookups / research
• We have all we need as JSON
• But that's not enough :(
• Your boss wants to look at the log
 • => provide a simple interface
• You need to do complex lookups / research
 • thousands of files, grep not good enough
• We have all we need as JSON
• But that's not enough :(
• Your boss wants to look at the log
 • => provide a simple interface
• You need to do complex lookups / research
 • thousands of files, grep not good enough
 • => need a powerful search engine
• We have all we need as JSON
• But that's not enough :(
• Your boss wants to look at the log
 • => provide a simple interface
• You need to do complex lookups / research
 • thousands of files, grep not good enough
 • => need a powerful search engine
• Also, what if you have different log sources
• We have all we need as JSON
• But that's not enough :(
• Your boss wants to look at the log
 • => provide a simple interface
• You need to do complex lookups / research
 • thousands of files, grep not good enough
 • => need a powerful search engine
• Also, what if you have different log sources
 • From DB events, Redis MQ, system logs ?
Web interfaces
Web interfaces
• Two interfaces
Web interfaces
• Two interfaces
• First one is easy to use
Web interfaces
• Two interfaces
• First one is easy to use
  • Based on Dancer + MongoDB
Web interfaces
• Two interfaces
• First one is easy to use
  • Based on Dancer + MongoDB
  • Shows logs in natural manner, grouped by
    job, hostname, and presented by time
Web interfaces
• Two interfaces
• First one is easy to use
  • Based on Dancer + MongoDB
  • Shows logs in natural manner, grouped by
    job, hostname, and presented by time

• Second one is more for data mining
Web interfaces
• Two interfaces
• First one is easy to use
  • Based on Dancer + MongoDB
  • Shows logs in natural manner, grouped by
    job, hostname, and presented by time

• Second one is more for data mining
  • Elasticsearch: deep searching, filtering, etc
We need some kind of big stuff

   syslog
                                      Standard log files

Redis MQ logs          $stuff          Web interface

 Other logs                           Search Engine
We need some kind of big stuff

   syslog
                                      Standard log files

Redis MQ logs          $stuff          Web interface

 Other logs                           Search Engine



      $stuff = Message::Passing
Message::Passing
Message::Passing
• Written by Tomas Doran
Message::Passing
• Written by Tomas Doran
• Logstash-like but in Perl and with style
Message::Passing
• Written by Tomas Doran
• Logstash-like but in Perl and with style
• It's a daemon (AnyEvent based)
Message::Passing
• Written by Tomas Doran
• Logstash-like but in Perl and with style
• It's a daemon (AnyEvent based)
• basic concepts: inputs, filters, outputs
Message::Passing
• Written by Tomas Doran
• Logstash-like but in Perl and with style
• It's a daemon (AnyEvent based)
• basic concepts: inputs, filters, outputs
• run it as : command line, using the DSL,
  using classes directly.
Real Life
Real Life
• My software runs on many machines
Real Life
• My software runs on many machines
• Connected to one syslog-ng server
Real Life
• My software runs on many machines
• Connected to one syslog-ng server
• Writing to log files
Real Life
• My software runs on many machines
• Connected to one syslog-ng server
• Writing to log files
• Configure syslog-ng to output to a pipe
Real Life
• My software runs on many machines
• Connected to one syslog-ng server
• Writing to log files
• Configure syslog-ng to output to a pipe
• Branch M::P on this named pipe
Real Life
• My software runs on many machines
• Connected to one syslog-ng server
• Writing to log files
• Configure syslog-ng to output to a pipe
• Branch M::P on this named pipe
• Web interface: Dancer + MongoDB
Real Life
• My software runs on many machines
• Connected to one syslog-ng server
• Writing to log files
• Configure syslog-ng to output to a pipe
• Branch M::P on this named pipe
• Web interface: Dancer + MongoDB
• Search interface : Elasticsearch + plugin
syslog-ng
 many      logs
machines
                  standard
                   log files
syslog-ng    duplicated
                                        flow
 many           logs
machines
                         standard
                          log files   Message::Passing



ElasticSearch      MongoDB

  Web GUI              Web GUI
logs MQ
                                    Message::Passing
 many
machines
                In a better world




ElasticSearch       MongoDB

  Web GUI           Web GUI
Let's use Message::Passing
Let's use Message::Passing
 • step 1 : configure & run M::P daemon
Let's use Message::Passing
 • step 1 : configure & run M::P daemon
 • step 2 : ...
Let's use Message::Passing
 • step 1 : configure & run M::P daemon
 • step 2 : ...
 • step 3 : PROFIT
Let's use Message::Passing
 • step 1 : configure & run M::P daemon
 • step 2 : ...
 • step 3 : PROFIT
 Remember the basic concepts?
 inputs, filters, outputs
use Message::Passing::DSL; use Moose;
with 'Message::Passing::Role::Script';
sub build_chain { message_chain {
  input filetail => (
      class     => 'FileTail',
      filename => ‘/path/to/logs’,
      output_to => 'cleanup_logs' );
  filter cleanup_logs => (
      class => '+My::Filter::DeJSON',
      output_to => [ 'elasticsearch', 'mongodb' ] );
  output elasticsearch_servers => (
      class => 'ElasticSearch',
      elasticsearch_servers => 'localhost:9200' );
  output mongodb => (
      class      => 'MongoDB',
      hostname   => 'localhost',
      database   => 'reporting',
      collection => 'logs',
      indexes => [ # specify fields to index ] );}
}
__PACKAGE__->start;
My::Filter::DeJSON


package My::Filter::DeJSON;

use Moose;

sub consume {
    my ( $self, $message ) = @_;
    $message =~ m/(w+):JSON:(.*)/ or return;
    my $structure_log = from_json($2);
    $structure_log->{log_level} = $1;
    foreach my $output_to ( @{ $self->output_to } ) {
        $output_to->consume($structure_log);
    }
}
Message::Passing::Output::MongoDB
use Moose; use MongoDB; use AnyEvent;
with qw/
    Message::Passing::Role::Output
    Message::Passing::Role::HasUsernameAndPassword
    Message::Passing::Role::HasHostnameAndPort
/;
# ... hostname, port, user/pass attributes ...
has _db => (
    is => 'ro', isa => 'MongoDB::Database', lazy => 1,
    default => sub {
        my $self = shift;
        my $connection = MongoDB::Connection->new(
            host => $self->hostname,
            port => $self->port,
        );
        return $connection->get_database($self->database);
    },
);
Message::Passing::Output::MongoDB


# ... _collection attribute
sub _build_logs_collection {
    my ($self) = @_;
    my $collection_name = $self->collection;
    my $collection = $self->_db->$collection_name;
 
    if ($self->_has_indexes) {
        foreach my $index (@{$self->indexes}){
            $collection->ensure_index(@$index);
        }
    }
    return $collection;
}
Message::Passing::Output::MongoDB

sub consume {
    my ($self, $data) = @_;
    return unless $data;
    my $date;
    my $collection = $self->_collection;
    $collection->insert($data)
      or warn "Insertion failure: " . Dumper($data) . "n";
    if ($self->verbose) {
        $self->_inc_log_counter;
        warn("Total " . $self->_log_counter
            . " records inserted in MongoDBn");
    }
}



                  On CPAN, by Bin Shu
Dancer web GUI
Dancer web GUI
•   Very simple Dancer application
Dancer web GUI
•   Very simple Dancer application

•   Could have used Dancer::Plugin::Mongo
Dancer web GUI
•   Very simple Dancer application

•   Could have used Dancer::Plugin::Mongo

•   A screen to display log
Dancer web GUI
•   Very simple Dancer application

•   Could have used Dancer::Plugin::Mongo

•   A screen to display log

•   A screen to search (filter) logs
Dancer web GUI
•   Very simple Dancer application

•   Could have used Dancer::Plugin::Mongo

•   A screen to display log

•   A screen to search (filter) logs

•   Result page always show logs ordered by time
Dancer GUI
Dancer GUI
Dancer GUI routes
Dancer GUI routes

•   get /   :
Dancer GUI routes

•   get /   :

    • a mongoDB group request per host, command, => /result
Dancer GUI routes

•   get /   :

    • a mongoDB group request per host, command, => /result

•   get /search   :
Dancer GUI routes

•   get /   :

    • a mongoDB group request per host, command, => /result

•   get /search   :

    • a mapreduce to display asearch form, => /result
Dancer GUI routes

•   get /   :

    • a mongoDB group request per host, command, => /result

•   get /search   :

    • a mapreduce to display asearch form, => /result

•   get /result   :
Dancer GUI routes

•   get /   :

    • a mongoDB group request per host, command, => /result

•   get /search   :

    • a mapreduce to display asearch form, => /result

•   get /result   :

    • get search params from url, issue a find request
Dancer GUI routes

•   get /   :

    • a mongoDB group request per host, command, => /result

•   get /search   :

    • a mapreduce to display asearch form, => /result

•   get /result   :

    • get search params from url, issue a find request

    • display in a table
Dancer GUI routes

•   get /   :

    • a mongoDB group request per host, command, => /result

•   get /search   :

    • a mapreduce to display asearch form, => /result

•   get /result   :

    • get search params from url, issue a find request

    • display in a table

• clicking on a result brings up a JS detailed result popup
Show me the video
Elasticsearch
Elasticsearch
•   Installation : trivial
Elasticsearch
•   Installation : trivial

•   Configuration : none
Elasticsearch
•   Installation : trivial

•   Configuration : none

•   Web GUI : elasticsearch-head
Elasticsearch
•   Installation : trivial

•   Configuration : none

•   Web GUI : elasticsearch-head

•   Code ? there is no code to show :)
Elasticsearch
•   Installation : trivial

•   Configuration : none

•   Web GUI : elasticsearch-head

•   Code ? there is no code to show :)

•   Usage : perform advanced search on massive backlog
Show me the video
Additional stuff

• If there is an error in Message::Passing
 • You should use the error channel
 • To avoid loop of death
Conclusion

• That's all there is about it, really
• Message::Passing is easy and work great
• Log::Message::Structured : an awesome idea
Questions ?


      Thanks !




Damien 'dams' Krotkine

More Related Content

What's hot

Mito, a successor of Integral
Mito, a successor of IntegralMito, a successor of Integral
Mito, a successor of Integralfukamachi
 
Spl to the Rescue - Zendcon 09
Spl to the Rescue - Zendcon 09Spl to the Rescue - Zendcon 09
Spl to the Rescue - Zendcon 09Elizabeth Smith
 
Blazing Data With Redis (and LEGOS!)
Blazing Data With Redis (and LEGOS!)Blazing Data With Redis (and LEGOS!)
Blazing Data With Redis (and LEGOS!)Justin Carmony
 
CPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its toolsCPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its toolscharsbar
 
Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'Gary Larizza
 
Puppet Camp Portland 2015: Introduction to Hiera (Beginner)
Puppet Camp Portland 2015: Introduction to Hiera (Beginner)Puppet Camp Portland 2015: Introduction to Hiera (Beginner)
Puppet Camp Portland 2015: Introduction to Hiera (Beginner)Puppet
 
Socket applications
Socket applicationsSocket applications
Socket applicationsJoão Moura
 
SPL to the Rescue - Tek 09
SPL to the Rescue - Tek 09SPL to the Rescue - Tek 09
SPL to the Rescue - Tek 09Elizabeth Smith
 
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...Puppet
 
Getting Hiera and Hiera
Getting Hiera and HieraGetting Hiera and Hiera
Getting Hiera and HieraPuppet
 
Writing and using php streams and sockets tek11
Writing and using php streams and sockets   tek11Writing and using php streams and sockets   tek11
Writing and using php streams and sockets tek11Elizabeth Smith
 
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)joegilbert
 
Day 7 - Make it Fast
Day 7 - Make it FastDay 7 - Make it Fast
Day 7 - Make it FastBarry Jones
 
Lessons learned while building Omroep.nl
Lessons learned while building Omroep.nlLessons learned while building Omroep.nl
Lessons learned while building Omroep.nlbartzon
 
Using hiera with puppet
Using hiera with puppetUsing hiera with puppet
Using hiera with puppetScott Lackey
 
Puppet101
Puppet101Puppet101
Puppet101Puppet
 
Tuning Your Engine
Tuning Your EngineTuning Your Engine
Tuning Your Enginejoelbradbury
 

What's hot (19)

Mito, a successor of Integral
Mito, a successor of IntegralMito, a successor of Integral
Mito, a successor of Integral
 
Spl to the Rescue - Zendcon 09
Spl to the Rescue - Zendcon 09Spl to the Rescue - Zendcon 09
Spl to the Rescue - Zendcon 09
 
Blazing Data With Redis (and LEGOS!)
Blazing Data With Redis (and LEGOS!)Blazing Data With Redis (and LEGOS!)
Blazing Data With Redis (and LEGOS!)
 
rtwerewr
rtwerewrrtwerewr
rtwerewr
 
CPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its toolsCPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its tools
 
Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'
 
Puppet Camp Portland 2015: Introduction to Hiera (Beginner)
Puppet Camp Portland 2015: Introduction to Hiera (Beginner)Puppet Camp Portland 2015: Introduction to Hiera (Beginner)
Puppet Camp Portland 2015: Introduction to Hiera (Beginner)
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
SPL to the Rescue - Tek 09
SPL to the Rescue - Tek 09SPL to the Rescue - Tek 09
SPL to the Rescue - Tek 09
 
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
 
Getting Hiera and Hiera
Getting Hiera and HieraGetting Hiera and Hiera
Getting Hiera and Hiera
 
Writing and using php streams and sockets tek11
Writing and using php streams and sockets   tek11Writing and using php streams and sockets   tek11
Writing and using php streams and sockets tek11
 
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby)
 
Day 7 - Make it Fast
Day 7 - Make it FastDay 7 - Make it Fast
Day 7 - Make it Fast
 
Lessons learned while building Omroep.nl
Lessons learned while building Omroep.nlLessons learned while building Omroep.nl
Lessons learned while building Omroep.nl
 
Using hiera with puppet
Using hiera with puppetUsing hiera with puppet
Using hiera with puppet
 
Web::Scraper
Web::ScraperWeb::Scraper
Web::Scraper
 
Puppet101
Puppet101Puppet101
Puppet101
 
Tuning Your Engine
Tuning Your EngineTuning Your Engine
Tuning Your Engine
 

Viewers also liked

Your first website in under a minute with Dancer
Your first website in under a minute with DancerYour first website in under a minute with Dancer
Your first website in under a minute with DancerxSawyer
 
Perl <b>5 Tutorial</b>, First Edition
Perl <b>5 Tutorial</b>, First EditionPerl <b>5 Tutorial</b>, First Edition
Perl <b>5 Tutorial</b>, First Editiontutorialsruby
 
Perl in the Internet of Things
Perl in the Internet of ThingsPerl in the Internet of Things
Perl in the Internet of ThingsDave Cross
 
Distributed Systems
Distributed SystemsDistributed Systems
Distributed Systemsnaveedchak
 
Lecture 1 (distributed systems)
Lecture 1 (distributed systems)Lecture 1 (distributed systems)
Lecture 1 (distributed systems)Fazli Amin
 
Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Tatsuhiko Miyagawa
 
Distributed computing environment
Distributed computing environmentDistributed computing environment
Distributed computing environmentRavi Bhushan
 
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011leo lapworth
 
Distributed computing
Distributed computingDistributed computing
Distributed computingKeshab Nath
 
distributed Computing system model
distributed Computing system modeldistributed Computing system model
distributed Computing system modelHarshad Umredkar
 
Distributed operating system(os)
Distributed operating system(os)Distributed operating system(os)
Distributed operating system(os)Dinesh Modak
 
Clock Synchronization in Distributed Systems
Clock Synchronization in Distributed SystemsClock Synchronization in Distributed Systems
Clock Synchronization in Distributed SystemsZbigniew Jerzak
 
Distributed computing ).ppt him
Distributed computing ).ppt himDistributed computing ).ppt him
Distributed computing ).ppt himHimanshu Saini
 

Viewers also liked (20)

PSGI/Plack OSDC.TW
PSGI/Plack OSDC.TWPSGI/Plack OSDC.TW
PSGI/Plack OSDC.TW
 
Your first website in under a minute with Dancer
Your first website in under a minute with DancerYour first website in under a minute with Dancer
Your first website in under a minute with Dancer
 
Perl <b>5 Tutorial</b>, First Edition
Perl <b>5 Tutorial</b>, First EditionPerl <b>5 Tutorial</b>, First Edition
Perl <b>5 Tutorial</b>, First Edition
 
Dancer's Ecosystem
Dancer's EcosystemDancer's Ecosystem
Dancer's Ecosystem
 
Distributive operating system
Distributive operating systemDistributive operating system
Distributive operating system
 
Dce rpc
Dce rpcDce rpc
Dce rpc
 
Perl in the Internet of Things
Perl in the Internet of ThingsPerl in the Internet of Things
Perl in the Internet of Things
 
Distributed Systems
Distributed SystemsDistributed Systems
Distributed Systems
 
Slide05 Message Passing Architecture
Slide05 Message Passing ArchitectureSlide05 Message Passing Architecture
Slide05 Message Passing Architecture
 
Lecture 1 (distributed systems)
Lecture 1 (distributed systems)Lecture 1 (distributed systems)
Lecture 1 (distributed systems)
 
Aos distibutted system
Aos distibutted systemAos distibutted system
Aos distibutted system
 
Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
 
Distributed computing environment
Distributed computing environmentDistributed computing environment
Distributed computing environment
 
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
 
Distributed computing
Distributed computingDistributed computing
Distributed computing
 
distributed Computing system model
distributed Computing system modeldistributed Computing system model
distributed Computing system model
 
message passing
 message passing message passing
message passing
 
Distributed operating system(os)
Distributed operating system(os)Distributed operating system(os)
Distributed operating system(os)
 
Clock Synchronization in Distributed Systems
Clock Synchronization in Distributed SystemsClock Synchronization in Distributed Systems
Clock Synchronization in Distributed Systems
 
Distributed computing ).ppt him
Distributed computing ).ppt himDistributed computing ).ppt him
Distributed computing ).ppt him
 

Similar to Easy Logging with Log::Message::Structured

London devops logging
London devops loggingLondon devops logging
London devops loggingTomas Doran
 
Cross-platform logging and analytics
Cross-platform logging and analyticsCross-platform logging and analytics
Cross-platform logging and analyticsDrew Crawford
 
Message:Passing - lpw 2012
Message:Passing - lpw 2012Message:Passing - lpw 2012
Message:Passing - lpw 2012Tomas Doran
 
What we Learned Implementing Puppet at Backstop
What we Learned Implementing Puppet at BackstopWhat we Learned Implementing Puppet at Backstop
What we Learned Implementing Puppet at BackstopPuppet
 
The basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwon
The basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwonThe basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwon
The basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwonKenneth Kwon
 
Replication, Durability, and Disaster Recovery
Replication, Durability, and Disaster RecoveryReplication, Durability, and Disaster Recovery
Replication, Durability, and Disaster RecoverySteven Francia
 
Automating MySQL operations with Puppet
Automating MySQL operations with PuppetAutomating MySQL operations with Puppet
Automating MySQL operations with PuppetKris Buytaert
 
Opslogger: Operations code (should be) production quality too!
Opslogger: Operations code (should be) production quality too!Opslogger: Operations code (should be) production quality too!
Opslogger: Operations code (should be) production quality too!Sean Reilly
 
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...Amazon Web Services
 
Tips from Support: Always Carry a Towel and Don’t Panic!
Tips from Support: Always Carry a Towel and Don’t Panic!Tips from Support: Always Carry a Towel and Don’t Panic!
Tips from Support: Always Carry a Towel and Don’t Panic!Perforce
 
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...MongoDB
 
[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc...
[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc...[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc...
[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc...GangSeok Lee
 
Leveling Up at JavaScript
Leveling Up at JavaScriptLeveling Up at JavaScript
Leveling Up at JavaScriptRaymond Camden
 
Trending with Purpose
Trending with PurposeTrending with Purpose
Trending with PurposeJason Dixon
 

Similar to Easy Logging with Log::Message::Structured (20)

London devops logging
London devops loggingLondon devops logging
London devops logging
 
Cross-platform logging and analytics
Cross-platform logging and analyticsCross-platform logging and analytics
Cross-platform logging and analytics
 
Message:Passing - lpw 2012
Message:Passing - lpw 2012Message:Passing - lpw 2012
Message:Passing - lpw 2012
 
What we Learned Implementing Puppet at Backstop
What we Learned Implementing Puppet at BackstopWhat we Learned Implementing Puppet at Backstop
What we Learned Implementing Puppet at Backstop
 
Tweakers Anonymous
Tweakers AnonymousTweakers Anonymous
Tweakers Anonymous
 
The basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwon
The basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwonThe basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwon
The basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwon
 
Replication, Durability, and Disaster Recovery
Replication, Durability, and Disaster RecoveryReplication, Durability, and Disaster Recovery
Replication, Durability, and Disaster Recovery
 
Pinto+Stratopan+Love
Pinto+Stratopan+LovePinto+Stratopan+Love
Pinto+Stratopan+Love
 
Lua pitfalls
Lua pitfallsLua pitfalls
Lua pitfalls
 
Automating MySQL operations with Puppet
Automating MySQL operations with PuppetAutomating MySQL operations with Puppet
Automating MySQL operations with Puppet
 
Fuzzing - Part 1
Fuzzing - Part 1Fuzzing - Part 1
Fuzzing - Part 1
 
Opslogger: Operations code (should be) production quality too!
Opslogger: Operations code (should be) production quality too!Opslogger: Operations code (should be) production quality too!
Opslogger: Operations code (should be) production quality too!
 
Buffer overflow
Buffer overflowBuffer overflow
Buffer overflow
 
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale...
 
Tips from Support: Always Carry a Towel and Don’t Panic!
Tips from Support: Always Carry a Towel and Don’t Panic!Tips from Support: Always Carry a Towel and Don’t Panic!
Tips from Support: Always Carry a Towel and Don’t Panic!
 
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...
 
[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc...
[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc...[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc...
[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc...
 
Tweakers Anonymous
Tweakers AnonymousTweakers Anonymous
Tweakers Anonymous
 
Leveling Up at JavaScript
Leveling Up at JavaScriptLeveling Up at JavaScript
Leveling Up at JavaScript
 
Trending with Purpose
Trending with PurposeTrending with Purpose
Trending with Purpose
 

More from Damien Krotkine

Stockage et analyse temps réel d'événements avec Riak chez Booking.com
Stockage et analyse temps réel d'événements avec Riak chez Booking.comStockage et analyse temps réel d'événements avec Riak chez Booking.com
Stockage et analyse temps réel d'événements avec Riak chez Booking.comDamien Krotkine
 
Using Riak for Events storage and analysis at Booking.com
Using Riak for Events storage and analysis at Booking.comUsing Riak for Events storage and analysis at Booking.com
Using Riak for Events storage and analysis at Booking.comDamien Krotkine
 

More from Damien Krotkine (6)

Stockage et analyse temps réel d'événements avec Riak chez Booking.com
Stockage et analyse temps réel d'événements avec Riak chez Booking.comStockage et analyse temps réel d'événements avec Riak chez Booking.com
Stockage et analyse temps réel d'événements avec Riak chez Booking.com
 
Using Riak for Events storage and analysis at Booking.com
Using Riak for Events storage and analysis at Booking.comUsing Riak for Events storage and analysis at Booking.com
Using Riak for Events storage and analysis at Booking.com
 
Riak introduction
Riak introductionRiak introduction
Riak introduction
 
Comma versus list
Comma versus listComma versus list
Comma versus list
 
Dancing with websocket
Dancing with websocketDancing with websocket
Dancing with websocket
 
Curses::Toolkit
Curses::ToolkitCurses::Toolkit
Curses::Toolkit
 

Recently uploaded

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfjimielynbastida
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 

Recently uploaded (20)

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdf
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 

Easy Logging with Log::Message::Structured

  • 2. Me Damien 'dams' Krotkine Paris.pm member French Perl Monger vice-president Perl Dancer developer 11 modules on CPAN (pretty weak) Author of Moderne Perl (french book, go buy it)
  • 3.
  • 4. • Let’s say I have a big application
  • 5. • Let’s say I have a big application • It processes a lot of data
  • 6. • Let’s say I have a big application • It processes a lot of data • It computes lots of lines
  • 7. • Let’s say I have a big application • It processes a lot of data • It computes lots of lines • Per user, and per account
  • 8. account 1 user 1 lines user 2 process user 3 account n result running on multiple hosts
  • 9.
  • 10. • It runs fine
  • 11. • It runs fine • Well, more or less
  • 12. • It runs fine • Well, more or less • I’d like to know what’s going on with it
  • 13. When the app crashes
  • 14. When the app crashes • Why did it crash ? ( reason, stack trace )
  • 15. When the app crashes • Why did it crash ? ( reason, stack trace ) • At crash time
  • 16. When the app crashes • Why did it crash ? ( reason, stack trace ) • At crash time • What was the situation ?
  • 17. When the app crashes • Why did it crash ? ( reason, stack trace ) • At crash time • What was the situation ? • What was the data it was processing ?
  • 18. When there are issues
  • 19. When there are issues • How bad is this failure ?
  • 20. When there are issues • How bad is this failure ? • Why did it fail to process this line ?
  • 21. When there are issues • How bad is this failure ? • Why did it fail to process this line ? • Is it only this line ?
  • 22. When there are issues • How bad is this failure ? • Why did it fail to process this line ? • Is it only this line ? • Is it reproducible ?
  • 23. When there are issues • How bad is this failure ? • Why did it fail to process this line ? • Is it only this line ? • Is it reproducible ? • Does the rest fail ? (user, account)
  • 24. When the app runs fine
  • 25. When the app runs fine • Information harvesting loop
  • 26. When the app runs fine • Information harvesting loop • 1: get more info about the process run
  • 27. When the app runs fine • Information harvesting loop • 1: get more info about the process run • 2: go see my boss/colleague/...
  • 28. When the app runs fine • Information harvesting loop • 1: get more info about the process run • 2: go see my boss/colleague/... • 3: (s)he asks something I don’t know
  • 29. When the app runs fine • Information harvesting loop • 1: get more info about the process run • 2: go see my boss/colleague/... • 3: (s)he asks something I don’t know • 4: go back to step 1
  • 30. So yeah, I need some logs
  • 31. So yeah, I need some logs But we knew that, didn’t we ?
  • 32. Logs
  • 33. Logs
  • 34. Logs
  • 35.
  • 39. Exceptions • An exception is an issue • All issues are not fatal (important)
  • 40. Exceptions • An exception is an issue • All issues are not fatal (important) • So, try / catch !
  • 42. Exception Module • Pick your own from CPAN
  • 43. Exception Module • Pick your own from CPAN • I wrote mine anyway :)
  • 44. Exception Module • Pick your own from CPAN • I wrote mine anyway :) • Dancer::Exception
  • 45. Exception Module • Pick your own from CPAN • I wrote mine anyway :) • Dancer::Exception • Extracted it as a standalone module
  • 46. Exception Module • Pick your own from CPAN • I wrote mine anyway :) • Dancer::Exception • Extracted it as a standalone module • Exceptions are objects with message pattern, stack trace... raise(), throw(), register(), introspection
  • 47. Exception Module • Pick your own from CPAN • I wrote mine anyway :) • Dancer::Exception • Extracted it as a standalone module • Exceptions are objects with message pattern, stack trace... raise(), throw(), register(), introspection • Should end up on CPAN one day
  • 48. foreach account { try { foreach user { try { foreach data line { try { process_line() } catch { log warning }; } } catch { log important }; } } catch { log important }; } log fatal
  • 49. Logs
  • 50.
  • 52. Logging a line • say "warning, data is not good"
  • 53. Logging a line • say "warning, data is not good" • say "warning, data '$data' is not good"
  • 54. Logging a line • say "warning, data is not good" • say "warning, data '$data' is not good" • say "$level, data '$data' is not good"
  • 55. Logging a line • say "warning, data is not good" • say "warning, data '$data' is not good" • say "$level, data '$data' is not good" • log( in_file => "$level, '$data' is not good")
  • 56. Logging a line • say "warning, data is not good" • say "warning, data '$data' is not good" • say "$level, data '$data' is not good" • log( in_file => "$level, '$data' is not good") • my $logger = MyOwnLogger->new(write_in => 'file', display_level => 'WARNING');
  • 57. Logging a line • say "warning, data is not good" • say "warning, data '$data' is not good" • say "$level, data '$data' is not good" • log( in_file => "$level, '$data' is not good") • my $logger = MyOwnLogger->new(write_in => 'file', display_level => 'WARNING'); • $logger->log(warning =>"$Level, '$data' is not good");
  • 58. Logging a line • say "warning, data is not good" • say "warning, data '$data' is not good" • say "$level, data '$data' is not good" • log( in_file => "$level, '$data' is not good") • my $logger = MyOwnLogger->new(write_in => 'file', display_level => 'WARNING'); • $logger->log(warning =>"$Level, '$data' is not good"); • Put that in a function, then a module, etc
  • 59. Logging a line • say "warning, data is not good" • say "warning, data '$data' is not good" • say "$level, data '$data' is not good" • log( in_file => "$level, '$data' is not good") • my $logger = MyOwnLogger->new(write_in => 'file', display_level => 'WARNING'); • $logger->log(warning =>"$Level, '$data' is not good"); • Put that in a function, then a module, etc
  • 61. The wheel... • Home-made logging system : I've seen that in every single company I've worked.
  • 62. The wheel... • Home-made logging system : I've seen that in every single company I've worked. • Sometimes multiple home-made logging system in a single company
  • 63. The wheel... • Home-made logging system : I've seen that in every single company I've worked. • Sometimes multiple home-made logging system in a single company • Sometimes multiple home-made logging system in a single project
  • 64. The wheel... • Home-made logging system : I've seen that in every single company I've worked. • Sometimes multiple home-made logging system in a single company • Sometimes multiple home-made logging system in a single project • It's so easy to start with a print STDERR...
  • 65. The wheel... • Home-made logging system : I've seen that in every single company I've worked. • Sometimes multiple home-made logging system in a single company • Sometimes multiple home-made logging system in a single project • It's so easy to start with a print STDERR... • Stop reinventing the wheel
  • 66. Pick up a logger
  • 67. Pick up a logger • Many Log modules on CPAN
  • 68. Pick up a logger • Many Log modules on CPAN • Pick one you like
  • 69. Pick up a logger • Many Log modules on CPAN • Pick one you like • I choose Log::Dispatch
  • 70. Pick up a logger • Many Log modules on CPAN • Pick one you like • I choose Log::Dispatch • $log->log(level => 'info', message => 'Blah' );
  • 71. Pick up a logger • Many Log modules on CPAN • Pick one you like • I choose Log::Dispatch • $log->log(level => 'info', message => 'Blah' ); • Good ?
  • 72. Pick up a logger • Many Log modules on CPAN • Pick one you like • I choose Log::Dispatch • $log->log(level => 'info', message => 'Blah' ); • Good ? • No, we are still nowhere !
  • 73. Pick up a logger • Many Log modules on CPAN • Pick one you like • I choose Log::Dispatch • $log->log(level => 'info', message => 'Blah' ); • Good ? • No, we are still nowhere ! • We want contextual information
  • 75. Contextual information • What do we need to log ?
  • 76. Contextual information • What do we need to log ? • A log message - ok, but
  • 77. Contextual information • What do we need to log ? • A log message - ok, but • Hardware info (Mem, CPU, disk, host)
  • 78. Contextual information • What do we need to log ? • A log message - ok, but • Hardware info (Mem, CPU, disk, host) • Software info (time, user / account id...)
  • 79. Contextual information • What do we need to log ? • A log message - ok, but • Hardware info (Mem, CPU, disk, host) • Software info (time, user / account id...) • Message (filename, line nb, stacktrace...)
  • 80. Contextual information • What do we need to log ? • A log message - ok, but • Hardware info (Mem, CPU, disk, host) • Software info (time, user / account id...) • Message (filename, line nb, stacktrace...) • Log line = mix contextual and specific info
  • 81. Contextual information • What do we need to log ? • A log message - ok, but • Hardware info (Mem, CPU, disk, host) • Software info (time, user / account id...) • Message (filename, line nb, stacktrace...) • Log line = mix contextual and specific info • Even with a great logger, need to build that
  • 83. Richer logging • How to pack these information together ?
  • 84. Richer logging • How to pack these information together ? • Use a key-value structure
  • 85. Richer logging • How to pack these information together ? • Use a key-value structure • Better: a class, fields are attributes
  • 86. Richer logging • How to pack these information together ? • Use a key-value structure • Better: a class, fields are attributes • So we can benefit of defaults, lazyness, etc
  • 87. Richer logging • How to pack these information together ? • Use a key-value structure • Better: a class, fields are attributes • So we can benefit of defaults, lazyness, etc • One log line = one class instance
  • 88. Richer logging • How to pack these information together ? • Use a key-value structure • Better: a class, fields are attributes • So we can benefit of defaults, lazyness, etc • One log line = one class instance • We need it as a string at the end
  • 89. Richer logging • How to pack these information together ? • Use a key-value structure • Better: a class, fields are attributes • So we can benefit of defaults, lazyness, etc • One log line = one class instance • We need it as a string at the end • So stringify to JSON,YAML...
  • 91. Log::Message::Structured • A set of roles, consume in MyEvent class
  • 92. Log::Message::Structured • A set of roles, consume in MyEvent class • 4 types of roles :
  • 93. Log::Message::Structured • A set of roles, consume in MyEvent class • 4 types of roles : • L::M::S : basic setup + "" overloading
  • 94. Log::Message::Structured • A set of roles, consume in MyEvent class • 4 types of roles : • L::M::S : basic setup + "" overloading • L::M::S::Components : provides ready to use additional fields
  • 95. Log::Message::Structured • A set of roles, consume in MyEvent class • 4 types of roles : • L::M::S : basic setup + "" overloading • L::M::S::Components : provides ready to use additional fields • L::M::S::Stringify : provides stringifiers
  • 96. Log::Message::Structured • A set of roles, consume in MyEvent class • 4 types of roles : • L::M::S : basic setup + "" overloading • L::M::S::Components : provides ready to use additional fields • L::M::S::Stringify : provides stringifiers • Your custom fields : additional attributes
  • 97. package MyLogEvent; use Moose; with qw/ Log::Message::Structured Log::Message::Structured::Component::Date Log::Message::Structured::Component::Hostname Log::Message::Structured::Stringify::AsJSON /; has message => ( is => 'ro', required => 1); has account_id => ( is => 'ro', required => 1); has user_id => ( is => 'ro' );
  • 98. package MyLogEvent; use Moose; with qw/ Log::Message::Structured Log::Message::Structured::Component::Date Log::Message::Structured::Component::Hostname Log::Message::Structured::Stringify::AsJSON /; has message => ( is => 'ro', required => 1); has account_id => ( is => 'ro', required => 1); has user_id => ( is => 'ro' ); ...elsewhere...
  • 99. package MyLogEvent; use Moose; with qw/ Log::Message::Structured Log::Message::Structured::Component::Date Log::Message::Structured::Component::Hostname Log::Message::Structured::Stringify::AsJSON /; has message => ( is => 'ro', required => 1); has account_id => ( is => 'ro', required => 1); has user_id => ( is => 'ro' ); ...elsewhere... use My::Log::Event; $logger->log( warning => MyLogEvent->new( account_id => 42, user_id => 12, message => "watch out! behind you!" ));
  • 100. package MyLogEvent; use Moose; with qw/ Log::Message::Structured Log::Message::Structured::Component::Date Log::Message::Structured::Component::Hostname Log::Message::Structured::Stringify::AsJSON /; has message => ( is => 'ro', required => 1); has account_id => ( is => 'ro', required => 1); has user_id => ( is => 'ro' ); ...elsewhere... use My::Log::Event; $logger->log( warning => MyLogEvent->new( account_id => 42, user_id => 12, message => "watch out! behind you!" )); That's sending the stringified JSON to Log::Dispatch
  • 103. Outputs as log: '{"__CLASS__":"MyLogEvent", "account_id":42, "user_id":42, "date":"2010-03-28T23:15:52Z", "hostname":"mymachine.domain", message=>"watch out! behind you!"}' L::M::S also supports options passed on the command line $ my_program.pl --account_id=42
  • 104. Let's shorten the code In my application I have:
  • 105. Let's shorten the code In my application I have: while (my $account_id = AccountIterator->next) { while (my $user_id = UserIterator->next) { while (my $data_line = DataIterator->next) { ... do stuff ...
  • 106. Let's shorten the code In my application I have: while (my $account_id = AccountIterator->next) { while (my $user_id = UserIterator->next) { while (my $data_line = DataIterator->next) { ... do stuff ... package MyLogEvent; use Moose; with qw/Log::Message::Structured .... /; use AccountIterator; use UserIterator; has account_id => ( is => 'ro', default => sub { AccountIterator->current } ); has user_id => ( is => 'ro', default => sub { UserIterator->current } );
  • 108. Let's shorten the code Wrap Log::Dispatch call + L::M::S
  • 109. Let's shorten the code Wrap Log::Dispatch call + L::M::S log_warning( message => "Achtung!");
  • 110. Let's shorten the code Wrap Log::Dispatch call + L::M::S log_warning( message => "Achtung!"); actually calls
  • 111. Let's shorten the code Wrap Log::Dispatch call + L::M::S log_warning( message => "Achtung!"); actually calls $logger->log( warning => MyLogEvent->new( @_ );
  • 112. Let's shorten the code Wrap Log::Dispatch call + L::M::S log_warning( message => "Achtung!"); actually calls $logger->log( warning => MyLogEvent->new( @_ ); outputs
  • 113. Let's shorten the code Wrap Log::Dispatch call + L::M::S log_warning( message => "Achtung!"); actually calls $logger->log( warning => MyLogEvent->new( @_ ); outputs '{"__CLASS__":"MyLogEvent", "account_id":42, "user_id":42, "date":"2010-03-28T23:15:52Z", "hostname":"mymachine.domain", message=>"Achtung!"}'
  • 115. Exceptions... Remember ? try { ... } catch { log_warning(exception => $_ ) };
  • 116. Exceptions... Remember ? try { ... } catch { log_warning(exception => $_ ) }; • To be able to write that, you need in your MyLogEvent class:
  • 117. Exceptions... Remember ? try { ... } catch { log_warning(exception => $_ ) }; • To be able to write that, you need in your MyLogEvent class: • these attributes : 'exception', 'stack_trace',
  • 118. Exceptions... Remember ? try { ... } catch { log_warning(exception => $_ ) }; • To be able to write that, you need in your MyLogEvent class: • these attributes : 'exception', 'stack_trace', • with a BUILDARGS
  • 119. Exceptions... Remember ? try { ... } catch { log_warning(exception => $_ ) }; • To be able to write that, you need in your MyLogEvent class: • these attributes : 'exception', 'stack_trace', • with a BUILDARGS • that looks at the exception, and set the 'message' and the 'stack_trace' arguments
  • 120. around BUILDARGS => sub { my $orig = shift; my $class = shift; my $h = $class->$orig(@_); my $e = $h->{exception} or return $h; if ( blessed($e) && $e->isa('My::Exception::Base') ) { $h->{message} = $e->message; $h->{shortmess} = $e->{_shortmess}; } else { $h->{message} = $e } return $h; };
  • 121. around BUILDARGS => sub { my $orig = shift; my $class = shift; my $h = $class->$orig(@_); my $e = $h->{exception} or return $h; if ( blessed($e) && $e->isa('My::Exception::Base') ) { $h->{message} = $e->message; $h->{shortmess} = $e->{_shortmess}; } else { $h->{message} = $e } return $h; }; try { ... } catch { log_warning(exception => $_ ) That would now }; work !
  • 124. Log::Message::Structured • Does the job • Please contribute
  • 125. Log::Message::Structured • Does the job • Please contribute • we need more components
  • 126. Log::Message::Structured • Does the job • Please contribute • we need more components • we need more stringifiers
  • 127. Log::Message::Structured • Does the job • Please contribute • we need more components • we need more stringifiers • compatibility with Moo
  • 128. Log::Message::Structured • Does the job • Please contribute • we need more components • we need more stringifiers • compatibility with Moo • On CPAN / github
  • 129.
  • 130. • We have all we need as JSON
  • 131. • We have all we need as JSON • But that's not enough :(
  • 132. • We have all we need as JSON • But that's not enough :( • Your boss wants to look at the log
  • 133. • We have all we need as JSON • But that's not enough :( • Your boss wants to look at the log • => provide a simple interface
  • 134. • We have all we need as JSON • But that's not enough :( • Your boss wants to look at the log • => provide a simple interface • You need to do complex lookups / research
  • 135. • We have all we need as JSON • But that's not enough :( • Your boss wants to look at the log • => provide a simple interface • You need to do complex lookups / research • thousands of files, grep not good enough
  • 136. • We have all we need as JSON • But that's not enough :( • Your boss wants to look at the log • => provide a simple interface • You need to do complex lookups / research • thousands of files, grep not good enough • => need a powerful search engine
  • 137. • We have all we need as JSON • But that's not enough :( • Your boss wants to look at the log • => provide a simple interface • You need to do complex lookups / research • thousands of files, grep not good enough • => need a powerful search engine • Also, what if you have different log sources
  • 138. • We have all we need as JSON • But that's not enough :( • Your boss wants to look at the log • => provide a simple interface • You need to do complex lookups / research • thousands of files, grep not good enough • => need a powerful search engine • Also, what if you have different log sources • From DB events, Redis MQ, system logs ?
  • 140. Web interfaces • Two interfaces
  • 141. Web interfaces • Two interfaces • First one is easy to use
  • 142. Web interfaces • Two interfaces • First one is easy to use • Based on Dancer + MongoDB
  • 143. Web interfaces • Two interfaces • First one is easy to use • Based on Dancer + MongoDB • Shows logs in natural manner, grouped by job, hostname, and presented by time
  • 144. Web interfaces • Two interfaces • First one is easy to use • Based on Dancer + MongoDB • Shows logs in natural manner, grouped by job, hostname, and presented by time • Second one is more for data mining
  • 145. Web interfaces • Two interfaces • First one is easy to use • Based on Dancer + MongoDB • Shows logs in natural manner, grouped by job, hostname, and presented by time • Second one is more for data mining • Elasticsearch: deep searching, filtering, etc
  • 146. We need some kind of big stuff syslog Standard log files Redis MQ logs $stuff Web interface Other logs Search Engine
  • 147. We need some kind of big stuff syslog Standard log files Redis MQ logs $stuff Web interface Other logs Search Engine $stuff = Message::Passing
  • 150. Message::Passing • Written by Tomas Doran • Logstash-like but in Perl and with style
  • 151. Message::Passing • Written by Tomas Doran • Logstash-like but in Perl and with style • It's a daemon (AnyEvent based)
  • 152. Message::Passing • Written by Tomas Doran • Logstash-like but in Perl and with style • It's a daemon (AnyEvent based) • basic concepts: inputs, filters, outputs
  • 153. Message::Passing • Written by Tomas Doran • Logstash-like but in Perl and with style • It's a daemon (AnyEvent based) • basic concepts: inputs, filters, outputs • run it as : command line, using the DSL, using classes directly.
  • 155. Real Life • My software runs on many machines
  • 156. Real Life • My software runs on many machines • Connected to one syslog-ng server
  • 157. Real Life • My software runs on many machines • Connected to one syslog-ng server • Writing to log files
  • 158. Real Life • My software runs on many machines • Connected to one syslog-ng server • Writing to log files • Configure syslog-ng to output to a pipe
  • 159. Real Life • My software runs on many machines • Connected to one syslog-ng server • Writing to log files • Configure syslog-ng to output to a pipe • Branch M::P on this named pipe
  • 160. Real Life • My software runs on many machines • Connected to one syslog-ng server • Writing to log files • Configure syslog-ng to output to a pipe • Branch M::P on this named pipe • Web interface: Dancer + MongoDB
  • 161. Real Life • My software runs on many machines • Connected to one syslog-ng server • Writing to log files • Configure syslog-ng to output to a pipe • Branch M::P on this named pipe • Web interface: Dancer + MongoDB • Search interface : Elasticsearch + plugin
  • 162. syslog-ng many logs machines standard log files
  • 163. syslog-ng duplicated flow many logs machines standard log files Message::Passing ElasticSearch MongoDB Web GUI Web GUI
  • 164. logs MQ Message::Passing many machines In a better world ElasticSearch MongoDB Web GUI Web GUI
  • 166. Let's use Message::Passing • step 1 : configure & run M::P daemon
  • 167. Let's use Message::Passing • step 1 : configure & run M::P daemon • step 2 : ...
  • 168. Let's use Message::Passing • step 1 : configure & run M::P daemon • step 2 : ... • step 3 : PROFIT
  • 169. Let's use Message::Passing • step 1 : configure & run M::P daemon • step 2 : ... • step 3 : PROFIT Remember the basic concepts? inputs, filters, outputs
  • 170. use Message::Passing::DSL; use Moose; with 'Message::Passing::Role::Script'; sub build_chain { message_chain { input filetail => ( class => 'FileTail', filename => ‘/path/to/logs’, output_to => 'cleanup_logs' ); filter cleanup_logs => ( class => '+My::Filter::DeJSON', output_to => [ 'elasticsearch', 'mongodb' ] ); output elasticsearch_servers => ( class => 'ElasticSearch', elasticsearch_servers => 'localhost:9200' ); output mongodb => ( class => 'MongoDB', hostname => 'localhost', database => 'reporting', collection => 'logs', indexes => [ # specify fields to index ] );} } __PACKAGE__->start;
  • 171. My::Filter::DeJSON package My::Filter::DeJSON; use Moose; sub consume { my ( $self, $message ) = @_; $message =~ m/(w+):JSON:(.*)/ or return; my $structure_log = from_json($2); $structure_log->{log_level} = $1; foreach my $output_to ( @{ $self->output_to } ) { $output_to->consume($structure_log); } }
  • 172. Message::Passing::Output::MongoDB use Moose; use MongoDB; use AnyEvent; with qw/     Message::Passing::Role::Output     Message::Passing::Role::HasUsernameAndPassword     Message::Passing::Role::HasHostnameAndPort /; # ... hostname, port, user/pass attributes ... has _db => (     is => 'ro', isa => 'MongoDB::Database', lazy => 1,     default => sub {         my $self = shift;         my $connection = MongoDB::Connection->new(             host => $self->hostname,             port => $self->port,         );         return $connection->get_database($self->database);     }, );
  • 173. Message::Passing::Output::MongoDB # ... _collection attribute sub _build_logs_collection {     my ($self) = @_;     my $collection_name = $self->collection;     my $collection = $self->_db->$collection_name;       if ($self->_has_indexes) {         foreach my $index (@{$self->indexes}){             $collection->ensure_index(@$index);         }     }     return $collection; }
  • 174. Message::Passing::Output::MongoDB sub consume {     my ($self, $data) = @_;     return unless $data;     my $date;     my $collection = $self->_collection;     $collection->insert($data)       or warn "Insertion failure: " . Dumper($data) . "n";     if ($self->verbose) {         $self->_inc_log_counter;         warn("Total " . $self->_log_counter . " records inserted in MongoDBn");     } } On CPAN, by Bin Shu
  • 176. Dancer web GUI • Very simple Dancer application
  • 177. Dancer web GUI • Very simple Dancer application • Could have used Dancer::Plugin::Mongo
  • 178. Dancer web GUI • Very simple Dancer application • Could have used Dancer::Plugin::Mongo • A screen to display log
  • 179. Dancer web GUI • Very simple Dancer application • Could have used Dancer::Plugin::Mongo • A screen to display log • A screen to search (filter) logs
  • 180. Dancer web GUI • Very simple Dancer application • Could have used Dancer::Plugin::Mongo • A screen to display log • A screen to search (filter) logs • Result page always show logs ordered by time
  • 185. Dancer GUI routes • get / : • a mongoDB group request per host, command, => /result
  • 186. Dancer GUI routes • get / : • a mongoDB group request per host, command, => /result • get /search :
  • 187. Dancer GUI routes • get / : • a mongoDB group request per host, command, => /result • get /search : • a mapreduce to display asearch form, => /result
  • 188. Dancer GUI routes • get / : • a mongoDB group request per host, command, => /result • get /search : • a mapreduce to display asearch form, => /result • get /result :
  • 189. Dancer GUI routes • get / : • a mongoDB group request per host, command, => /result • get /search : • a mapreduce to display asearch form, => /result • get /result : • get search params from url, issue a find request
  • 190. Dancer GUI routes • get / : • a mongoDB group request per host, command, => /result • get /search : • a mapreduce to display asearch form, => /result • get /result : • get search params from url, issue a find request • display in a table
  • 191. Dancer GUI routes • get / : • a mongoDB group request per host, command, => /result • get /search : • a mapreduce to display asearch form, => /result • get /result : • get search params from url, issue a find request • display in a table • clicking on a result brings up a JS detailed result popup
  • 192. Show me the video
  • 194. Elasticsearch • Installation : trivial
  • 195. Elasticsearch • Installation : trivial • Configuration : none
  • 196. Elasticsearch • Installation : trivial • Configuration : none • Web GUI : elasticsearch-head
  • 197. Elasticsearch • Installation : trivial • Configuration : none • Web GUI : elasticsearch-head • Code ? there is no code to show :)
  • 198. Elasticsearch • Installation : trivial • Configuration : none • Web GUI : elasticsearch-head • Code ? there is no code to show :) • Usage : perform advanced search on massive backlog
  • 199.
  • 200.
  • 201.
  • 202. Show me the video
  • 203. Additional stuff • If there is an error in Message::Passing • You should use the error channel • To avoid loop of death
  • 204. Conclusion • That's all there is about it, really • Message::Passing is easy and work great • Log::Message::Structured : an awesome idea
  • 205. Questions ? Thanks ! Damien 'dams' Krotkine

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n
  137. \n
  138. \n
  139. \n
  140. \n
  141. \n
  142. \n
  143. \n
  144. \n
  145. \n
  146. \n
  147. \n
  148. \n
  149. \n
  150. \n
  151. \n
  152. \n
  153. \n
  154. \n
  155. \n
  156. \n
  157. \n
  158. \n
  159. \n
  160. \n
  161. \n
  162. \n
  163. \n
  164. \n
  165. \n
  166. \n
  167. \n
  168. \n
  169. \n
  170. \n
  171. \n
  172. \n
  173. \n
  174. \n
  175. \n
  176. \n
  177. \n
  178. \n
  179. \n
  180. \n
  181. \n
  182. \n
  183. \n
  184. \n
  185. \n