Message passing

Damien Krotkine
Damien KrotkineSoftware Engineer at Booking.com
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)
Message passing
• 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
Message passing
• 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
Message passing
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
Message passing
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
Message passing
• 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
Message passing
Message passing
Message passing
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
1 of 205

Recommended

Bottom to Top Stack Optimization - CICON2011 by
Bottom to Top Stack Optimization - CICON2011Bottom to Top Stack Optimization - CICON2011
Bottom to Top Stack Optimization - CICON2011CodeIgniter Conference
2.3K views28 slides
WebAssembly. Neither Web Nor Assembly, All Revolutionary by
WebAssembly. Neither Web Nor Assembly, All RevolutionaryWebAssembly. Neither Web Nor Assembly, All Revolutionary
WebAssembly. Neither Web Nor Assembly, All RevolutionaryC4Media
359 views133 slides
MIND sweeping introduction to PHP by
MIND sweeping introduction to PHPMIND sweeping introduction to PHP
MIND sweeping introduction to PHPBUDNET
2K views40 slides
Malicious Intent: Adventures in JavaScript Obfuscation and Deobfuscation by
Malicious Intent: Adventures in JavaScript Obfuscation and DeobfuscationMalicious Intent: Adventures in JavaScript Obfuscation and Deobfuscation
Malicious Intent: Adventures in JavaScript Obfuscation and DeobfuscationHeadlessZeke
321 views31 slides
Profiling php applications by
Profiling php applicationsProfiling php applications
Profiling php applicationsJustin Carmony
6.1K views92 slides
Php Introduction nikul by
Php Introduction nikulPhp Introduction nikul
Php Introduction nikulNikul Shah
821 views53 slides

More Related Content

What's hot

Mito, a successor of Integral by
Mito, a successor of IntegralMito, a successor of Integral
Mito, a successor of Integralfukamachi
1.8K views53 slides
Spl to the Rescue - Zendcon 09 by
Spl to the Rescue - Zendcon 09Spl to the Rescue - Zendcon 09
Spl to the Rescue - Zendcon 09Elizabeth Smith
2K views69 slides
Blazing Data With Redis (and LEGOS!) by
Blazing Data With Redis (and LEGOS!)Blazing Data With Redis (and LEGOS!)
Blazing Data With Redis (and LEGOS!)Justin Carmony
6.3K views72 slides
rtwerewr by
rtwerewrrtwerewr
rtwerewresolinhighered
348 views40 slides
CPANTS: Kwalitative website and its tools by
CPANTS: Kwalitative website and its toolsCPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its toolscharsbar
1.2K views90 slides
Refactor Dance - Puppet Labs 'Best Practices' by
Refactor Dance - Puppet Labs 'Best Practices'Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'Gary Larizza
1.9K views77 slides

What's hot(19)

Mito, a successor of Integral by fukamachi
Mito, a successor of IntegralMito, a successor of Integral
Mito, a successor of Integral
fukamachi1.8K views
Blazing Data With Redis (and LEGOS!) by Justin Carmony
Blazing Data With Redis (and LEGOS!)Blazing Data With Redis (and LEGOS!)
Blazing Data With Redis (and LEGOS!)
Justin Carmony6.3K views
CPANTS: Kwalitative website and its tools by charsbar
CPANTS: Kwalitative website and its toolsCPANTS: Kwalitative website and its tools
CPANTS: Kwalitative website and its tools
charsbar1.2K views
Refactor Dance - Puppet Labs 'Best Practices' by Gary Larizza
Refactor Dance - Puppet Labs 'Best Practices'Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'
Gary Larizza1.9K views
Puppet Camp Portland 2015: Introduction to Hiera (Beginner) by Puppet
Puppet Camp Portland 2015: Introduction to Hiera (Beginner)Puppet Camp Portland 2015: Introduction to Hiera (Beginner)
Puppet Camp Portland 2015: Introduction to Hiera (Beginner)
Puppet2.7K views
Socket applications by João Moura
Socket applicationsSocket applications
Socket applications
João Moura601 views
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo... by Puppet
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...
Puppet6.6K views
Getting Hiera and Hiera by Puppet
Getting Hiera and HieraGetting Hiera and Hiera
Getting Hiera and Hiera
Puppet2.7K views
Writing and using php streams and sockets tek11 by Elizabeth Smith
Writing and using php streams and sockets   tek11Writing and using php streams and sockets   tek11
Writing and using php streams and sockets tek11
Elizabeth Smith2.3K views
MITH Digital Dialogues: Intro to Programming for Humanists (with Ruby) by joegilbert
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)
joegilbert12.3K views
Day 7 - Make it Fast by Barry Jones
Day 7 - Make it FastDay 7 - Make it Fast
Day 7 - Make it Fast
Barry Jones897 views
Lessons learned while building Omroep.nl by bartzon
Lessons learned while building Omroep.nlLessons learned while building Omroep.nl
Lessons learned while building Omroep.nl
bartzon376 views
Using hiera with puppet by Scott Lackey
Using hiera with puppetUsing hiera with puppet
Using hiera with puppet
Scott Lackey1.6K views
Puppet101 by Puppet
Puppet101Puppet101
Puppet101
Puppet3K views

Viewers also liked

PSGI/Plack OSDC.TW by
PSGI/Plack OSDC.TWPSGI/Plack OSDC.TW
PSGI/Plack OSDC.TWTatsuhiko Miyagawa
3.1K views118 slides
Your first website in under a minute with Dancer by
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
2.9K views20 slides
Perl <b>5 Tutorial</b>, First Edition by
Perl <b>5 Tutorial</b>, First EditionPerl <b>5 Tutorial</b>, First Edition
Perl <b>5 Tutorial</b>, First Editiontutorialsruby
21.2K views241 slides
Dancer's Ecosystem by
Dancer's EcosystemDancer's Ecosystem
Dancer's EcosystemAlexis Sukrieh
1.2K views67 slides
Distributive operating system by
Distributive operating systemDistributive operating system
Distributive operating systemMuhammad Adeel Rajput
516 views23 slides
Dce rpc by
Dce rpcDce rpc
Dce rpcpratosh123
1.5K views19 slides

Viewers also liked(20)

Your first website in under a minute with Dancer by xSawyer
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
xSawyer2.9K views
Perl <b>5 Tutorial</b>, First Edition by tutorialsruby
Perl <b>5 Tutorial</b>, First EditionPerl <b>5 Tutorial</b>, First Edition
Perl <b>5 Tutorial</b>, First Edition
tutorialsruby21.2K views
Perl in the Internet of Things by Dave Cross
Perl in the Internet of ThingsPerl in the Internet of Things
Perl in the Internet of Things
Dave Cross4.6K views
Distributed Systems by naveedchak
Distributed SystemsDistributed Systems
Distributed Systems
naveedchak1.2K views
Lecture 1 (distributed systems) by Fazli Amin
Lecture 1 (distributed systems)Lecture 1 (distributed systems)
Lecture 1 (distributed systems)
Fazli Amin3.6K views
Deploying Plack Web Applications: OSCON 2011 by Tatsuhiko Miyagawa
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
Tatsuhiko Miyagawa8.2K views
Distributed computing environment by Ravi Bhushan
Distributed computing environmentDistributed computing environment
Distributed computing environment
Ravi Bhushan8.9K views
Plack basics for Perl websites - YAPC::EU 2011 by leo lapworth
Plack basics for Perl websites - YAPC::EU 2011Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
leo lapworth18K views
Distributed computing by Keshab Nath
Distributed computingDistributed computing
Distributed computing
Keshab Nath3.6K views
distributed Computing system model by Harshad Umredkar
distributed Computing system modeldistributed Computing system model
distributed Computing system model
Harshad Umredkar24.7K views
message passing by Ashish Kumar
 message passing message passing
message passing
Ashish Kumar23.7K views
Distributed operating system(os) by Dinesh Modak
Distributed operating system(os)Distributed operating system(os)
Distributed operating system(os)
Dinesh Modak20.7K views
Clock Synchronization in Distributed Systems by Zbigniew Jerzak
Clock Synchronization in Distributed SystemsClock Synchronization in Distributed Systems
Clock Synchronization in Distributed Systems
Zbigniew Jerzak55.6K views
Distributed computing ).ppt him by Himanshu Saini
Distributed computing ).ppt himDistributed computing ).ppt him
Distributed computing ).ppt him
Himanshu Saini23.6K views

Similar to Message passing

London devops logging by
London devops loggingLondon devops logging
London devops loggingTomas Doran
17.3K views97 slides
Cross-platform logging and analytics by
Cross-platform logging and analyticsCross-platform logging and analytics
Cross-platform logging and analyticsDrew Crawford
1.3K views141 slides
Message:Passing - lpw 2012 by
Message:Passing - lpw 2012Message:Passing - lpw 2012
Message:Passing - lpw 2012Tomas Doran
1.5K views150 slides
What we Learned Implementing Puppet at Backstop by
What we Learned Implementing Puppet at BackstopWhat we Learned Implementing Puppet at Backstop
What we Learned Implementing Puppet at BackstopPuppet
3.1K views96 slides
Tweakers Anonymous by
Tweakers AnonymousTweakers Anonymous
Tweakers AnonymousJohn Anderson
667 views65 slides
The basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwon by
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
856 views63 slides

Similar to Message passing(20)

London devops logging by Tomas Doran
London devops loggingLondon devops logging
London devops logging
Tomas Doran17.3K views
Cross-platform logging and analytics by Drew Crawford
Cross-platform logging and analyticsCross-platform logging and analytics
Cross-platform logging and analytics
Drew Crawford1.3K views
Message:Passing - lpw 2012 by Tomas Doran
Message:Passing - lpw 2012Message:Passing - lpw 2012
Message:Passing - lpw 2012
Tomas Doran1.5K views
What we Learned Implementing Puppet at Backstop by Puppet
What we Learned Implementing Puppet at BackstopWhat we Learned Implementing Puppet at Backstop
What we Learned Implementing Puppet at Backstop
Puppet3.1K views
The basics of hacking and penetration testing 이제 시작이야 해킹과 침투 테스트 kenneth.s.kwon by Kenneth 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
Kenneth Kwon856 views
Replication, Durability, and Disaster Recovery by Steven Francia
Replication, Durability, and Disaster RecoveryReplication, Durability, and Disaster Recovery
Replication, Durability, and Disaster Recovery
Steven Francia9.9K views
Automating MySQL operations with Puppet by Kris Buytaert
Automating MySQL operations with PuppetAutomating MySQL operations with Puppet
Automating MySQL operations with Puppet
Kris Buytaert1.8K views
Opslogger: Operations code (should be) production quality too! by Sean Reilly
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 Reilly514 views
(BDT402) Performance Profiling in Production: Analyzing Web Requests at Scale... by Amazon Web Services
(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 Services1.7K views
Tips from Support: Always Carry a Towel and Don’t Panic! by Perforce
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!
Perforce1.1K views
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv... by MongoDB
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...
MongoDB602 views
[2010 CodeEngn Conference 04] passket - Taint analysis for vulnerability disc... by GangSeok Lee
[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 Lee2.4K views
Leveling Up at JavaScript by Raymond Camden
Leveling Up at JavaScriptLeveling Up at JavaScript
Leveling Up at JavaScript
Raymond Camden2.1K views
Trending with Purpose by Jason Dixon
Trending with PurposeTrending with Purpose
Trending with Purpose
Jason Dixon2.1K views

More from Damien Krotkine

Stockage et analyse temps réel d'événements avec Riak chez Booking.com by
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
1.6K views119 slides
Using Riak for Events storage and analysis at Booking.com by
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
3.9K views112 slides
Riak introduction by
Riak introductionRiak introduction
Riak introductionDamien Krotkine
2.7K views61 slides
Comma versus list by
Comma versus listComma versus list
Comma versus listDamien Krotkine
344 views55 slides
Dancing with websocket by
Dancing with websocketDancing with websocket
Dancing with websocketDamien Krotkine
3.8K views28 slides
Curses::Toolkit by
Curses::ToolkitCurses::Toolkit
Curses::ToolkitDamien Krotkine
3.1K views28 slides

More from Damien Krotkine(6)

Stockage et analyse temps réel d'événements avec Riak chez Booking.com by Damien Krotkine
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
Damien Krotkine1.6K views
Using Riak for Events storage and analysis at Booking.com by Damien Krotkine
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
Damien Krotkine3.9K views

Recently uploaded

Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ... by
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...ShapeBlue
146 views15 slides
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online by
KVM Security Groups Under the Hood - Wido den Hollander - Your.OnlineKVM Security Groups Under the Hood - Wido den Hollander - Your.Online
KVM Security Groups Under the Hood - Wido den Hollander - Your.OnlineShapeBlue
181 views19 slides
Ransomware is Knocking your Door_Final.pdf by
Ransomware is Knocking your Door_Final.pdfRansomware is Knocking your Door_Final.pdf
Ransomware is Knocking your Door_Final.pdfSecurity Bootcamp
90 views46 slides
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti... by
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...ShapeBlue
98 views29 slides
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue by
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlueElevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlueShapeBlue
179 views7 slides
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ... by
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...ShapeBlue
144 views12 slides

Recently uploaded(20)

Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ... by ShapeBlue
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
ShapeBlue146 views
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online by ShapeBlue
KVM Security Groups Under the Hood - Wido den Hollander - Your.OnlineKVM Security Groups Under the Hood - Wido den Hollander - Your.Online
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online
ShapeBlue181 views
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti... by ShapeBlue
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...
DRaaS using Snapshot copy and destination selection (DRaaS) - Alexandre Matti...
ShapeBlue98 views
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue by ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlueElevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
ShapeBlue179 views
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ... by ShapeBlue
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
ShapeBlue144 views
DRBD Deep Dive - Philipp Reisner - LINBIT by ShapeBlue
DRBD Deep Dive - Philipp Reisner - LINBITDRBD Deep Dive - Philipp Reisner - LINBIT
DRBD Deep Dive - Philipp Reisner - LINBIT
ShapeBlue140 views
NTGapps NTG LowCode Platform by Mustafa Kuğu
NTGapps NTG LowCode Platform NTGapps NTG LowCode Platform
NTGapps NTG LowCode Platform
Mustafa Kuğu365 views
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P... by ShapeBlue
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...
ShapeBlue154 views
Digital Personal Data Protection (DPDP) Practical Approach For CISOs by Priyanka Aash
Digital Personal Data Protection (DPDP) Practical Approach For CISOsDigital Personal Data Protection (DPDP) Practical Approach For CISOs
Digital Personal Data Protection (DPDP) Practical Approach For CISOs
Priyanka Aash153 views
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or... by ShapeBlue
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
ShapeBlue158 views
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ... by ShapeBlue
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...
How to Re-use Old Hardware with CloudStack. Saving Money and the Environment ...
ShapeBlue123 views
State of the Union - Rohit Yadav - Apache CloudStack by ShapeBlue
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStack
ShapeBlue253 views
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue by ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlueMigrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
ShapeBlue176 views
The Role of Patterns in the Era of Large Language Models by Yunyao Li
The Role of Patterns in the Era of Large Language ModelsThe Role of Patterns in the Era of Large Language Models
The Role of Patterns in the Era of Large Language Models
Yunyao Li80 views
Business Analyst Series 2023 - Week 4 Session 7 by DianaGray10
Business Analyst Series 2023 -  Week 4 Session 7Business Analyst Series 2023 -  Week 4 Session 7
Business Analyst Series 2023 - Week 4 Session 7
DianaGray10126 views
The Power of Heat Decarbonisation Plans in the Built Environment by IES VE
The Power of Heat Decarbonisation Plans in the Built EnvironmentThe Power of Heat Decarbonisation Plans in the Built Environment
The Power of Heat Decarbonisation Plans in the Built Environment
IES VE69 views

Message passing

  • 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)
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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