view release on metacpan or search on metacpan
devdata/http_advent.perldancer.org_2018_16 view on Meta::CPAN
use MyJob::JobQueue;
use MyJob::Log4p;
use MyJob::Util::Logger;
use MyJob::Util::SysTools qw(get_hostname);
my $config = MyJob::Config->new->config;
my $hostconfig = get_hostconfig();
my $minion = MyJob::JobQueue->new;
my $worker = $minion->runner->worker;
my $log_eng = MyJob::Log4p->new({ logger_name => "Minion" });
my $logger = MyJob::Util::Logger->new->logger($log_eng);</pre>
<p>The above is mostly typical boilerplate for us. Read our configuration, and create a logger the worker can use.</p>
<p>Next, when a job is dequeued, we want to log that the worker picked up a job (needed for auditing purposes) and we alter the process name so if a process hangs, we know what that process
was attempting to run. If an unchecked exception occurs in a job, the worker will catch it and log it for us:</p>
<pre class="prettyprint">$worker->on( dequeue => sub( $worker, $job ) {
my $id = $job->id;
my $notes = $job->info->{ notes };
my $title = $notes->{ title };
my $guid = $notes->{ guid };
$job->on( spawn => sub( $job, $pid ) {
$0 = "$title $guid";
$logger->info(
"$title: Created child process $pid for job $id by parent $$ - $guid");
});
$job->on( failed => sub( $job, $error ) {
chomp $error;
$logger->error( $error );
});
});</pre>
<p>To help us for future capacity planning, we want our workers to tell us if they are running at peak capacity, so log when this event occurs:</p>
<pre class="prettyprint">$worker->on( busy => sub( $worker ) {
my $max = $worker->status->{ jobs };
$logger->log( "$0: Running at capacity (performing $max jobs)." );
});</pre>
<p>Now, we apply the configuration (read below) to the worker. When the worker starts, it tells us information about how it was configured (this was really useful during development):</p>
<pre class="prettyprint">my $max_jobs = $hostconfig->{ max_children };
my @queues = @{ $hostconfig->{ queues }};
if( $minion->has_invalid_queues( @queues ) ){
print "Invalid job queues specified: " . join( ',',
$minion->get_invalid_queues( @queues ) );
say ". Aborting!";
devdata/http_advent.perldancer.org_2018_16 view on Meta::CPAN
if( exists $minion_config->{ $hostname }) {
return $minion_config->{ $hostname };
} else {
return $minion_config->{ default };
}
}</pre>
<h2><a name="monitoring_the_workers"></a>Monitoring the Workers</h2>
<p>Our Minion dashboard was virtually identical to the one that @preaction posted in <a href="https://mojolicious.io/blog/2018/12/11/who-watches-the-minions/#section-2">Who Watches the Minions?</a>.
If you'd like to know more, I highly recommend reading his article.</p>
<h2><a name="outcome"></a>Outcome</h2>
<p>Within about a two-week timespan, we went from having zero practical knowledge of Minion to having things up and running. We've made some refinements and improvements along the way, but the quick turnaround
is a true testament to the simplicity of working with Minion.</p>
<p>We now have all the necessary pieces in place to scale our XML rendering both horizontally and vertically: thanks to Minion, we can easily run XML jobs across multiple boxes, and can more efficiently run
more jobs concurrently on the same hardware as before. This setup allows us to grow as quickly as our customer base does.</p>
<h2><a name="author"></a>Author</h2>
<p>This article has been written by Jason Crome (CromeDome) for the Perl Dancer
devdata/http_advent.perldancer.org_2018_17 view on Meta::CPAN
<h2><a name="inline_images"></a>Inline images</h2>
<p>You can simply deliver emails with links to images, but usually email clients would not load them without user interaction.
It is possible though to attached the images to the email and reference them in the email body with a custom HTML tag:</p>
<pre class="prettyprint"> email {
from => 'foo@perl.dance',
to => 'bar@perl.dance',
subject => 'Welcome to the dancefloor!',
body => q{<p>Image embedded: <img src="cid:mycid"/></p>},
type => 'html',
attach => [ { Id => 'mycid', Path => '/dancefloor/dcr-header-logo.png' }],
multipart => 'related'
};</pre>
<h2><a name="providing_plain_text_part"></a>Providing plain text part</h2>
<p><a href="https://metacpan.org/pod/HTML::FormatText::WithLinks">HTML::FormatText::WithLinks</a> makes it easy to provide a plain text version
of your HTML email:</p>
<pre class="prettyprint">my $html = template $template, $tokens, { layout => 'email' };
my $f = HTML::FormatText::WithLinks->new;
devdata/http_advent.perldancer.org_2018_19 view on Meta::CPAN
<li><a href="http://github.com/PerlDancer/Dancer">Dancer on GitHub</a></li>
<li><a href="http://github.com/PerlDancer/Dancer2">Dancer 2 on GitHub</a></li>
<li><a class="feed" href="/feed/2018">RSS</a></li>
</ul>
</li>
</ul>
</div>
<div id="content">
<div class="pod-document"><h1><a name="logging_with_dancer2__logger__log4perl"></a>Logging with Dancer2::Logger::Log4perl</h1>
<h2><a name="history"></a>History</h2>
<p>It's late summer 2018, and there has been a hole in the logging ecosystem of Dancer2 for some time
now - we've been missing a Log4perl plugin. There are certainly a lot of great logging options
available (<code>Dancer2::Logger::LogAny</code>, <code>Dancer2::Logger::Syslog</code>, and <code>Dancer2::Logger::LogReport</code>
to name a few), and a couple of them even include appenders for Log4perl. In looking at our own
needs, however, they all seemed to be overkill.</p>
<p>At <code>$work</code>, everything is based on Log4perl (and, in our client-facing Java apps, Log4j), so
there has never been need for another logger. We'd been happily using <code>Dancer::Logger::Log4perl</code>
for years, and wanted to continue to use something familar to us. Before investing some time in
writing our own Log4perl plugin for Dancer2, we expanded our search beyond metacpan, and were
rewarded in doing so.</p>
<p>We stumbled across a project from Ryan Larscheidt and Jon Miner at the University of Wisconsin.
They wrote a Log4perl plugin for Dancer2 with the intent of releasing it, but as their priorities
and projects shifted, it never made its way to CPAN. I used to go to MadMongers (Madison Perl Mongers),
so before long, I was able to track them down and they gave me their blessing to release it.</p>
<p>A little packaging and a few tests later, <code>Dancer2::Logger::Log4perl</code> was on its way to CPAN!</p>
<h2><a name="configuration"></a>Configuration</h2>
<p>First, we need to create a basic Log4perl configuration. Create a new Dancer2 application (I'll call
mine <code>TestLog4perl</code>), and in the application directory create a <i>log4perl.conf</i> file with the following:</p>
<pre class="prettyprint">log4perl.rootLogger = DEBUG, LOG1
log4perl.appender.LOG1 = Log::Log4perl::Appender::File
log4perl.appender.LOG1.filename = logs/mylog.log
log4perl.appender.LOG1.mode = append
log4perl.appender.LOG1.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.LOG1.layout.ConversionPattern = %d %p %m %n</pre>
<p>The first one defines our root application logger. The first parameter after the equals sign says
what is the minimum level we should log. Since we are saying the minimum log level should be <code>DEBUG</code>,
any messages from Dancer2 itself, and anything logged at the <code>core</code> level will be ignored.</p>
<p>After the minimum log level is a comma-separated list of appenders to write to. For now, we will create a
single appender named <code>LOG1</code> (we will see how to add a second appender below). This will write
to a file in the <i>logs/</i> directory named <i>mylog.log</i>, using the <a href="https://metacpan.org/pod/Log::Log4perl::Appender::File">Log::Log4perl::Appender::File</a>
appender. When the app is started, it will append to an existing log file of that name (or create the file
if necessary), and will write to it with a format specified by <a href="https://metacpan.org/pod/Log::Log4perl::Layout::PatternLayout">Log::Log4perl::Layout::PatternLayout</a>.</p>
<p>Each appender can have its own configuration directives. Please consult the pod for each appender for a list
of its configuration parameters.</p>
<p>Next, we have to tell our application that we are using <code>Dancer2::Logger::Log4perl</code> as our preferred logger.
Edit your <i>environments/development.yml</i> file, and comment out the <code>logger: "console"</code> line. Replace it
with the following:</p>
<pre class="prettyprint">logger: log4perl
log: core
engines:
logger:
log4perl:
config_file: log4perl.conf</pre>
<p>This tells Dancer2 to use <code>Dancer2::Logger::Log4perl</code> as its logging engine, and to send all levels of message to
it. Finally, Log4perl should look for its configuration file in the root application directory in a file called
<i>log4perl.conf</i>.</p>
<h2><a name="usage"></a>Usage</h2>
<p>Using Log4perl is simple: use the logging keywords you are already familiar with in Dancer:</p>
<pre class="prettyprint">get '/' => sub {
debug "I'M IN UR INDEX";
template 'index' => { 'title' => 'TestLog4perl' };
};</pre>
<p>Start your application and visit <code>http://localhost:5000/</code>. You will see the following in your <i>logs/mylog.log</i> file:</p>
<pre class="prettyprint">2018/12/18 21:36:02 DEBUG I'M IN UR INDEX</pre>
<h2><a name="hey__i_can_t_see_my_log_messages_on_the_screen_"></a>Hey, I can't see my log messages on the screen!</h2>
<p>That's because we didn't add a screen appender! With Log4perl, adding another appender is easy. Let's
add another section to our <i>log4perl.conf</i> file:</p>
<pre class="prettyprint">log4perl.appender.SCREEN = Log::Log4perl::Appender::Screen
log4perl.appender.SCREEN.stderr = 0
log4perl.appender.SCREEN.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.SCREEN.layout.ConversionPattern = %m %n</pre>
<p>This creates another appender named <code>SCREEN</code>. We then need to tell our root logger to use this appender
as well:</p>
<pre class="prettyprint">log4perl.rootLogger = DEBUG, LOG1, SCREEN</pre>
<p>Now, restart your application, and visit a route that has logging installed, and you will see your log
message not only goes to the <i>logs/mylog.log</i> file, but also displays on the console running your
application. Easy!</p>
<h2><a name="some_gotchas"></a>Some Gotchas</h2>
<p>There are a couple of important nuances you should be aware of:</p>
<ul>
<li><a name="item_Environment_configuration_replaces_logging_configuration"></a><b>Environment configuration replaces logging configuration</b>
<p>If you put your logging configuration in <i>config.yml</i> rather than one of your environment-specific
configuration files (such as <i>environments/development.yml</i>), you stand a good chance of not using
the logging configuration you think you are using. The default configuration file for the development
environment, for example, logs only to the console. If you put your Log4perl configuration in <i>config.yml</i>
and don't change your development configuration file, your Log4perl configuration will be passed over
for the default console logger.</p>
<p>From my own experience, <b>always</b> configure your logger in your environment-specific configuration, unless
you use the same configuration across all environments (I don't endorse this practice).</p>
</li>
<li><a name="item_Core_level_messages_are_passed_as_log_level_trace__but_will_not_be_passed_unless_Dancer2_s_log_level_is_core_"></a><b>Core level messages are passed as log level trace, but will not be passed unless Dancer2's log level is core.</b>
<p>Since <code>core</code> doesn't have a good corresponding level in Log4perl, <code>core</code> level messages are sent
over to Log4perl at the <code>trace</code> log level. This <b>only</b> happens when you set Dancer2's log level in your
<i>config.yml</i> file to <code>core</code> however. So your preferred log level setting is respected, even if <code>core</code> level
messages have to be reported at a different level.</p>
</li>
<li><a name="item__code_log__code__should_be_set_a_lower_priority_than_the_lowest_priority_as_set_in_your_Log4perl_configuration_"></a><b><code>log</code> should be set a lower priority than the lowest priority as set in your Log4perl configuration.<...
<p>If it isn't, the log messages will not be passed to Log4perl.</p>
</li>
</ul>
<h2><a name="conclusion"></a>Conclusion</h2>
<p>If Log4perl is all the logging you need in your Dancer2 applications, then <code>Dancer2::Logger::Log4perl</code> is well worth
a look. It gives you much of the functionality available to Log4perl while using the logging syntax built into Dancer2.
This article should give you sufficient grounding to get going with Log4perl in your Dancer2 applications.</p>
<h2><a name="further_reading"></a>Further Reading</h2>
<ul>
<li><a name="item__a_href__https___metacpan_org_pod_Dancer2__Logger__Log4perl__Dancer2__Logger__Log4perl__a_"></a><b><a href="https://metacpan.org/pod/Dancer2::Logger::Log4perl">Dancer2::Logger::Log4perl</a></b>
</li>
<li><a name="item__a_href__https___metacpan_org_pod_Log__Log4perl__Log4perl__a_"></a><b><a href="https://metacpan.org/pod/Log::Log4perl">Log4perl</a></b>
</li>
<li><a name="item__a_href__https___www_perl_com_pub_2002_09_11_log4perl_html___Log4Perl_Tutorial__a_"></a><b><a href="https://www.perl.com/pub/2002/09/11/log4perl.html/">Log4Perl Tutorial</a></b>
</li>
</ul>
<h2><a name="author"></a>Author</h2>
<p>This article has been written by Jason Crome (CromeDome) for the Perl Dancer
Advent Calendar 2018.</p>
<h2><a name="copyright"></a>Copyright</h2>
<p>No copyright retained. Enjoy.</p>
<p>Jason A. Crome</p>
devdata/http_advent.perldancer.org_2018_20 view on Meta::CPAN
</li>
</ul>
</div>
<div id="content">
<div class="pod-document"><h1><a name="testing_dancer_with_test__mojo"></a>Testing Dancer with Test::Mojo</h1>
<p>Authors of Dancer (and other) PSGI applications are probably accustomed to <a href="https://metacpan.org/pod/distribution/Dancer2/lib/Dancer2/Manual.pod#TESTING">testing</a> with <a href="https://metacpan.org/pod/Plack::Test">Plack::Test</a>, and ...
<p>During advent last year, I wrote about <a href="https://mojolicious.org/perldoc/Test/Mojo">Test::Mojo</a>, showing the many easy and (dare I say) fun ways that you can use it to test your Mojolicious applications.
If you missed it, go <a href="https://mojolicious.io/blog/2017/12/09/day-9-the-best-way-to-test/">check it out</a>.</p>
<p>I expect there are at least a few of you out there who read that and think, "I'd love to use that, but I don't use Mojolicious!"; well, you're in luck!
With just a little role to bridge the gap, you can use Test::Mojo to test your PSGI applications too!</p>
<h2><a name="mounting_psgi_applications"></a>Mounting PSGI Applications</h2>
<p>Mojolicious itself doesn't use the <a href="https://metacpan.org/pod/PSGI">PSGI</a> protocol, owing to certain features that it doesn't provide and which are necessary for certain asynchronous operations.
That said, you can serve a Mojolicious application on a PSGI server by using <a href="https://mojolicious.org/perldoc/Mojo/Server/PSGI">Mojo::Server::PSGI</a>.
This Mojolicious-core module is automatically used for you when your Mojolicious-based app detects that it has started under a PSGI server (e.g. plackup or Starman).</p>
<p>While translating between a Mojo app and a PSGI server is core functionality, doing the opposite, translating between a PSGI app and a Mojolicious server (or app, as you'll see) is available as a third party module.
<a href="https://metacpan.org/pod/Mojolicious::Plugin::MountPSGI">Mojolicious::Plugin::MountPSGI</a>, as it's name implies, can mount a PSGI application into a Mojolicious-based one.
To do so, it builds a new, empty Mojolicious application that translates all requests to PSGI environments before dispatching to it as with any <a href="https://mojolicious.org/perldoc/Mojolicious/Plugin/Mount">mount</a>-ed application.</p>
<h2><a name="testing_using_test__mojo"></a>Testing using Test::Mojo</h2>
<p>Once you can do that, it is trivial to take a PSGI application, wrap it with MountPSGI, and set it as the application for use with Test::Mojo.
Still, to make it even easier, that has all been done for you in <a href="https://metacpan.org/pod/Test::Mojo::Role::PSGI">Test::Mojo::Role::PSGI</a>.</p>
<p>Like any <a href="https://mojolicious.io/blog/2017/12/13/day-13-more-about-roles/">Mojolicious Role</a>, we can use <code>with_roles</code> to create a (mostly anonymous) subclass with the role applied.
You can use the shortcut <code>+</code> to stand in for <code>Test::Mojo::Role::</code>.</p>
<pre class="prettyprint">use Test::Mojo;
my $class = Test::Mojo->with_roles('+PSGI');</pre>
<p>Then you instantiate that role with the path to the PSGI application, or else the PSGI application itself.</p>
<p>Since you're using roles, which are all about composition, you can also apply other roles that you might <a href="https://metacpan.org/search?q=%22Test%3A%3AMojo%3A%3ARole%22">find on CPAN</a>.</p>
<h2><a name="an_example"></a>An Example</h2>
<p>As an example, let's say we have a simple application script (named <code>app.psgi</code>) that can render a <code>"hello world"</code> or <code>"hello $user"</code> in several formats.
I'll allow a plain text response, JSON, and templated HTML (using the <a href="https://metacpan.org/pod/Dancer2::Template::Simple">simple</a> template to keep this concise).</p>
devdata/http_advent.perldancer.org_2018_20 view on Meta::CPAN
<pre class="prettyprint"><dl id="data">
<dt id="hello">hello</dt>
<dd><% name %></dd>
</dl></pre>
<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl">dl</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt">dt</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd">dd</a> tags...
The HTML I've built, while nice for display isn't necessarily nice for querying programmatically, this is on purpose for the example.</p>
<h2><a name="the_tests"></a>The Tests</h2>
<p>Of course we could start the application with <a href="https://metacpan.org/pod/distribution/Plack/script/plackup">plackup</a> but that's not what we're trying to do.
I'll break the test script down a bit but if you want to see any of these files look at the <a href="https://github.com/MojoliciousDotIO/mojolicious.io/tree/master/blog/2018/12/20/testing-dancer/ex">blog repo</a> for a full listing.
Instead, let's load this into a test script.</p>
<pre class="prettyprint">use Mojo::Base -strict;</pre>
<p>Now if you aren't familiar, <code>use Mojo::Base -strict</code> is a quick way to say</p>
<pre class="prettyprint">use strict;
use warnings;
use utf8;
use IO::Handle;
use feature ':5.10';</pre>
devdata/http_advent.perldancer.org_2018_20 view on Meta::CPAN
->content_type_like(qr[text/html])
->text_is('dl#data dt#hello + dd', 'world');
$t->post_ok('/html' => form => { name => 'grinch' })
->status_is(200)
->content_type_like(qr[text/html])
->text_is('dl#data dt#hello + dd', 'grinch');
done_testing;</pre>
<p>In this year's Mojolicious advent calendar, we've already seen <a href="https://mojolicious.io/blog/2018/12/05/compound-selectors/">some</a> <a href="https://mojolicious.io/blog/2018/12/14/a-practical-example-of-mojo-dom/">great</a> <a href="https...
The point remains however, testing HTML responses with CSS selectors allows you to make your tests targetd in a way that allows you to write more and better tests since you don't have to hack around extracting the bits you want.</p>
<h2><a name="testing_websockets"></a>Testing WebSockets</h2>
<p>Ok so that's great and all, but of course now it comes to the point you've all been waiting for: can you test WebSockets?
As Jason Crome mentioned in his <a href="http://advent.perldancer.org/2018/13">Twelve Days of Dancer</a> "State of Dancer", you can now dance with WebSockets via <a href="https://metacpan.org/pod/Dancer2::Plugin::WebSocket">Dancer2::Plugin::WebSocket...
<p>Well, so far not via the role I showed above.
It might be possible, but it would involve learning deep PSGI magick that I'm not sure I'm smart enough to do; patches welcome obviously :D.</p>
<p>Still I mentioned above that Test::Mojo can test anything it can access via an fully qualified URL, so let's just start up a server and test it!
I'll use the <a href="https://github.com/yanick/Dancer2-Plugin-WebSocket/tree/releases/example">example bundled with the plugin</a> for simplicty.</p>
<pre class="prettyprint">use Mojo::Base -strict;
devdata/http_advent.perldancer.org_2018_21 view on Meta::CPAN
<p>Screen readers know to ignore this because it's hidden, and because it's hidden, the page won't show this field.
As a user, you won't ever have to fill it in.</p>
<p>Thankfully, a lot of spam bots are stupid, and blindly fill in any form field they see. They can't parse the CSS
in such a way that they can tell one of the fields is unusably hidden, and they often don't pay attention to
the hidden attribute... so they fall right into our trap. Enjoy your free education, spambot!</p>
<h2><a name="final_thoughts"></a>Final thoughts</h2>
<p>Is it foolproof? No, not by a longshot. Anyone who really wants to is going to find a way to spam you anyhow,
given a sufficient amount of time and motivation. But this will slow many down, and prevent a bunch, and
you won't drive sighted users away from your site. In the three and a half years I have used this, only two
spambots have made it through, and my server logs indicate that many others have tried.</p>
<h2><a name="author"></a>Author</h2>
<p>This article has been written by Jason Crome (CromeDome) for the Perl Dancer
Advent Calendar 2018.</p>
<h2><a name="copyright"></a>Copyright</h2>
<p>No copyright retained. Enjoy.</p>
<p>Jason A. Crome</p>
</div>
devdata/http_advent.perldancer.org_2018_23 view on Meta::CPAN
<li><a href="http://github.com/PerlDancer/Dancer">Dancer on GitHub</a></li>
<li><a href="http://github.com/PerlDancer/Dancer2">Dancer 2 on GitHub</a></li>
<li><a class="feed" href="/feed/2018">RSS</a></li>
</ul>
</li>
</ul>
</div>
<div id="content">
<div class="pod-document"><h1><a name="dancer2__logger__console__colored"></a>Dancer2::Logger::Console::Colored</h1>
<p>During development the console output of your app is often one of the most important tools.
But sometimes there is just too much noise, and changing the log settings all the time is not convenient.
Of course you can grep the log or scroll, but wouldn't it be nice to get visual clues for what you're looking for?</p>
<p>With <a href="https://metacpan.org/module/Dancer2::Logger::Console::Colored">Dancer2::Logger::Console::Colored</a> you can do that. It's a drop-in replacement for the default
console logger, but with color. It will make the message appear in color depending on the levels. You can turn
it on by setting your logger in your environment config file:</p>
<pre class="prettyprint">logger: "Console::Colored"</pre>
<p>Your log will instantly become cheerful and seasonal according to this default configuration:</p>
<pre class="prettyprint"># config.yml (these are the defaults)
engines:
logger:
Console::Colored:
colored_origin: "cyan"
colored_levels:
core: "bold bright_white"
debug: "bold bright_blue"
info: "bold green"
warning: "bold yellow"
error: "bold yellow on_red"
colored_messages:
core: "bold bright_white"
debug: "bold bright_blue"
info: "bold green"
warning: "bold yellow"
error: "bold yellow on_red"</pre>
<img src="/images/2018/23/log-1.png">
<p>The <code>colored_origin</code> refers to the part of the message that shows the package that this
message originated in, as well as the file name and line.</p>
<pre class="prettyprint">>> Dancer2 v0.207000 server 28764 listening on http://0.0.0.0:3000
[main:28764] debug @2018-12-19 20:31:06> Hello World in test.pl l. 6
^^^^ ^^^^^^^ ^</pre>
<p>The <code>colored_levels</code> are the log levels themselves.</p>
<pre class="prettyprint">[main:28764] debug @2018-12-19 20:31:06> Hello World in test.pl l. 6
^^^^^</pre>
<p>And the <code>colored_messages</code> refer to the actual message.</p>
<pre class="prettyprint">[main:28764] debug @2018-12-19 20:31:06> Hello World in test.pl l. 6
^^^^^^^^^^^</pre>
<p>The colors are the same kind of color strings used by <a href="https://metacpan.org/module/Term::ANSIColor">Term::ANSIColor</a>. The first
color refers to the foreground, and the second one to the background. You can add an optional <code>bold</code>.</p>
<pre class="prettyprint">[bold] [foreground] [on_background]</pre>
<h2><a name="changing_the_log_message"></a>Changing the log message</h2>
<p>If you don't like the default log format, you can change it with the <code>log_format</code> setting, which is
documented in detail in <a href="https://metacpan.org/module/Dancer2::Core::Role::Logger">Dancer2::Core::Role::Logger</a>. You can just stick it in with the other configuration.</p>
<pre class="prettyprint"># config.yml (this is the default)
engines:
logger:
Console::Colored:
log_format: "[%a:%P] %L @%T> %m in %f l. %l"</pre>
<p>Usually you would run a single-worker server during development, so there is no need for request IDs.
And since the message is now colored, we can also drop the log level. How about a simple format like
the following:</p>
<pre class="prettyprint">%t %f:%l> %m
# 20/Dec/2018 16:41:07 MyApp.pm:22> Hello World</pre>
<h2><a name="i_know_regular_expressions_"></a>I know regular expressions!</h2>
<p>Sometimes just reading the log is not enough. You're looking for a specific piece of information. There
are three pages of log for a single request, and debugging is hard work. Grepping is an option,
but you need to look for a complex pattern. Maybe a product SKU, a date or some other piece of information.</p>
<p>With Dancer2::Logger::Console::Colored you can actually make it come out with a background color so you
can spot it easily, without having to change your code (or your added debugging log statements). Instead,
you can put a regular expression into your configuration file.</p>
<pre class="prettyprint"># config.yml
engines:
logger:
Console::Colored:
colored_regex:
- re: "customer number \d+"
color: "bold red"</pre>
<p>This will find customer numbers according to the pattern and make them bold and red. You can supply
a regular expression pattern and a color setting.</p>
<img src="/images/2018/23/log-2.png">
<p>Note that there is a list under the <code>colored_regex</code> key. This means you can actually have
multiple patterns. Even really simple ones that make <code>print</code> style debugging easy
and attractive.</p>
<pre class="prettyprint"># config.yml
engines:
logger:
Console::Colored:
colored_regex:
- re: "customer number \d+"
color: "bold red"
- re: "\bhere\b"
color: "white on_green"</pre>
<p>If you want to highlight an entire log message in a specific color, you can set a pattern that captures
everything. However, this works on the message only, and not on the entire formatted line of log output.
(Patches welcome!)</p>
<pre class="prettyprint"># config.yml
engines:
logger:
Console::Colored:
colored_regex:
- re: ".+here.+"
color: "white on_red"</pre>
<img src="/images/2018/23/log-3.png">
<p>This opens up a lot of possibilities, for debugging as well as for general logging during development.</p>
<h2><a name="what_else"></a>What else?</h2>
<p>There are still some feature ideas in the backlog, but it's already pretty useful. If you would
like to see additional features, please feel free to
[open an issue on github](https://github.com/simbabque/Dancer2-Logger-Console-Colored/issues).</p>
<p>And if you happen to use Mojolicious as well and need something similar, take a look at
<a href="https://metacpan.org/module/Mojo::Log::Colored">Mojo::Log::Colored</a>, which is in the early stages of development, but works quite well.</p>
<h2><a name="author"></a>Author</h2>
<p>This article has been written by Julien Fiegehenn (simbabque) for the Perl Dancer
Advent Calendar 2018.</p>
<h2><a name="copyright"></a>Copyright</h2>
devdata/http_advent.perldancer.org_2018_24 view on Meta::CPAN
</li>
<li><a name="item_New_Website"></a><b>New Website</b>
<p>There's a lot of great information on the Dancer website, but it's looking tired. There's a
lot of new information to be added, and with a fresh coat of paint, Dancer's website will be as
great as the software powering it.</p>
</li>
<li><a name="item_More_configuration_options"></a><b>More configuration options</b>
<p>Configuration in Dancer2 leaves a lot to be desired (and I'll admit that I am a big part of
the reason for why that is). Look for an overhaul of the configuration system in 2019, which
starts with a barebones configuration system and allows for pluggable configuration engines
(much like loggers and sessions in Dancer2). Since we are dedicated to not breaking working
code, all of the existing configuration logic would be packaged as a plugin and enabled
out of the box.</p>
</li>
<li><a name="item_Inline_parameter_type_checking"></a><b>Inline parameter type checking</b>
<p>Very similar in many ways to Sawyer's <a href="https://metacpan.org/pod/Dancer2::Plugin::ParamTypes">Dancer2::Plugin::ParamTypes</a>
plugin, but provided as core functionality. SysPete is actively developing a way to provide
(optional) type checking of parameters within the core of Dancer2.</p>
<p>In case you haven't read <a href="http://advent.perldancer.org/2018/22">Sawyer's article</a>
about type checking parameters passed to your Dancer applications, I highly recommend
it. It will change the way you do data validation.</p>
</li>
devscripts/update view on Meta::CPAN
ignore_empty => 1,
namespace => 'Acme::CPANModules::Import::PerlDancerAdvent',
user_agent => 'Mozilla/5.0',
dist_dir => "$Bin/..",
},
'app',
);
Perinci::CmdLine::Any->new(
url => '/main/app',
log => 1,
)->run;