« January 2007 | Main | March 2007 »

February 27, 2007

Threading

Why it wasn't threadsafe. cross the road? did the chicken

Technorati Tags:

February 23, 2007

Rhapsody Updates

The Rhapsody website player now sports a shuffle (and repeat) button. Yay! Random new band I like thanks to a tip from a Rhapsody sysadmin: Explosions In The Sky.

Perl Module Use

Avoid plain use Module::Name in favor of either an empty import list, or a specific list of items to trample on the local namespace with:

use CGI; # expensive! use CGI (); # much better use POSIX; # slow and much trampling use POSIX qw(strftime); # just this subroutine

Limiting module imports saves time, and lessens the risk that two functions with the same name will be used. A quick review of the use statements will generally reveal exactly what has been imported, such as strftime in the example above. Should a new module version export more by default, the explicit import list will avoid any namespace changes to scripts.

Technorati Tags:

Benchmarking use properly is tricky…

#!/usr/bin/perl -w use strict; use Benchmark qw(cmpthese); cmpthese( -5, { 'use-import' => sub { eval "use CGI;" }, 'use-empty' => sub { eval "use CGI ();" }, });

February 19, 2007

Wikipedia Moment

Cliff Stoll (author, The Cuckoo's Egg) sells Klein Bottles online. And now you know!

February 18, 2007

Sicilian Opening

Technorati Tags:

February 15, 2007

parse-sudoers - reformat sudoers data

parse-sudoers does not follow the sudoers BNF, though will tidy up the data, especially where unsorted users reside in sprawling multiline blocks.

$ cat input User_Alias SOME_USERS = finell, dobbs, bialy, \ garib, cavaluzzi, kubica, \ deutschman, noth, standford, mcelmurry $ parse-sudoers input User_Alias SOME_USERS = bialy, cavaluzzi,⏎ deutschman, dobbs, finell, garib, kubica,⏎ mcelmurry, noth, standford

Technorati Tags:

February 12, 2007

Delimited Data Generation

Output from the following code may fail validation where a downstream system expects key:value pairs and does not support empty fields at the end of the record.

print "OK:foo:" . join(':', @key_value_pairs) . "\n"

If @key_value_pairs is empty, resulting in the unacceptable OK:foo:. Safer code would include this prefix as an argument to the join function:

my @OUTPUT_PREFIX = qw(OK foo); print join(':', @OUTPUT_PREFIX, @key_value_pairs) . "\n"

This way a proper colon delimited list is generated, or an empty string should both arrays be empty.

No, I haven’t been bitten by this gotcha. No, really!

Technorati Tags: ,

February 10, 2007

Sightseeing

Chess/Shogi take III. Shogi set arrived at work, but could not round up enough folks for a try at bughouse Shogi…

Technorati Tags:

February 06, 2007

kronsoon - generate crontab timestamp for near future run

kronsoon generates a crontab(5) compatible timestamp in the near future, optionally followed by a command, optionally preceded by a comment. Similar to what an at(1) job can do, though handy where a utility must run from cron(8) to replicate the state of another command normally run under cron.

Technorati Tags: ,

February 03, 2007

Debug Daylight Time Changes

The forum post how to test Daylight Saving Time settings for 2007 contains a script that tests daylight saving changes without altering the system time.

Like Y2K, the early daylight savings change this year gives management something to fuss over. I’m personally in favor of more gmtime(3) and less localtime(3) use, as a code review at work reveals many needless localtime uses. Unfortunately these uses will require a fair amount of work to convert to gmtime, especially where the data wanders off to other groups.

February 01, 2007

URL Monitoring Thoughts

In addition to the HTTP status code, URL monitors must capture the request latency: a site may be responding, but slowly enough to impact customers. The following code outlines a URL monitor in Perl, using LWP::UserAgent to request the URL and Time::HiRes to measure latency:

#!/usr/bin/perl -w use strict; my $url = shift || die "Usage: $0 url\n"; use LWP::UserAgent (); use Time::HiRes qw(gettimeofday tv_interval); my %output; my $ua = LWP::UserAgent->new; my $start = [gettimeofday]; my $response = $ua->get($url); $output{latency} = sprintf '%.2f', tv_interval($start); $output{status} = $response->code; # TODO template %output as demanded by # the monitoring system for my $key ( keys %output ) { print "$key=$output{$key}\n"; }

Metrics & Alerts

Graph the HTTP status code along with the latency. This avoids the information loss produced by mapping the codes into arbitrary “good” or “bad” values. The alerting framework should handle translation of the code into an alert, as appropriate for the URL: >= 400 pages someone, while >= 300 only warns about the unexpected redirection response.

The latency graph provides clues into the problem: assuming a 200 HTTP status code in each case, a ledge at N seconds indicates a timeout of some sort (check for DNS problems), while a scattered graph points to network packet loss or similar load induced problem. Watch the average latency over time, then set an appropriate alert threshold, perhaps five seconds. Another option: alert should a “major” increase occur in the latency, perhaps one or two standard deviations above a moving average. This will catch sudden latency increases, but will fail to alert in the event latency slowly rises beyond the Service Level Agreement (SLA) threshold.

Latency ledge exampleExample latency due to packet loss

If possible, negotiate the SLA in advance, to ensure a proper solution can be developed. Also consider how far below the SLA alerts must be set, to allow triage before a system breaks SLA.

Check Multiple URL

A single script can check multiple related URL as plugin for Nagios or comparable monitoring systems. Do not number the URL arguments in the output; instead, associate short aliases for each URL monitored. Numbered URL force the question “well, what URL is actually in error?” while aliases provide a hint while not exceeding any length limits on monitoring output. If the monitoring system allows, include the full URL in the output, so a reader can copy or click on the URL directly from the alarm message.

#!/usr/bin/perl -w use strict; die "Usage: $0 alias.url [.. alias.url]\n" unless @ARGV; use LWP::UserAgent (); use Time::HiRes qw(gettimeofday tv_interval); my @results; my $ua = LWP::UserAgent->new; for my $target (@ARGV) { my %output; ( $output{alias}, $output{url} ) = split /\./, $target, 2; my $start = [gettimeofday]; my $response = $ua->get( $output{url} ); $output{latency} = sprintf '%.2f', tv_interval($start); $output{status} = $response->code; push @results, \%output; } for my $result (@results) { print join( ':', map { $result->{$_} } qw(alias status latency) ), "\n"; }

Consider Deeper Content Checks

If necessary, also setup content checks that ensure websites contain the expected content. A site may return 200 status codes within the SLA, but contain no data if a software bug or caching problem omits some or all of the page content.

Technorati Tags: