Skip to content

Instantly share code, notes, and snippets.

@inakianduaga
Last active August 29, 2015 14:19
Show Gist options
  • Save inakianduaga/ef2220f975d8fe6aa88d to your computer and use it in GitHub Desktop.
Save inakianduaga/ef2220f975d8fe6aa88d to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
#
# Json Wrapper: Wraps Stdin input into json template for logging purposes.
#
# The idea is to use this script to wrap logs from cli commands so they can be used
# for rsyslog @cee log processing.
#
# Author: Inaki Anduaga <inaki@inakianduaga.com>
#
# Usage: <COMMAND> | ./jsonWrap.pl <MODE> <CHANNEL> <KEY1:VAL1> <KEY2:VAL2> ...
#
# Where <MODE>: line|block.
# Line block will json wrap each line into an individual json entry,
# block will json wrap the entire output
# <CHANNEL>: String used to identifiy to what group this log belongs to
# <COMMAND>: Anything script that generates stdin output
# <KEY:VAL>: These optional key/value pairs will be added to the log entry
#
# Requires perls json package (in ubuntu, `apt-get install libconfig-json-perl`)
use strict;
use warnings;
package main;
use JSON;
# Set mode from command line arguments
# Defaults to line when undefined / non-matching
my $mode = defined($ARGV[0]) && $ARGV[0] eq 'block' ? 'block' : 'line';
my $channel = $ARGV[1];
# Parse extra CLI parameters into hash
my %extraLogParameters = parseExtraCliParameters(@ARGV);
#
# Line mode: Pipe each line through the log formatter
#
if($mode eq 'line') {
# Read stdin and wrap each line in a json block
# http://alumnus.caltech.edu/~svhwan/prodScript/perlGettingInput.html
while (<STDIN>) {
# Remove trailing linebreaks on input
# http://perldoc.perl.org/functions/chomp.html
chomp;
# Format line
my $formatted = LogFormatter($_);
# Print output prepended by rsyslog @cee log tag
print '@cee: '. $formatted . "\n";
}
}
#
# Block mode: Buffer input and format
#
else {
my $stdin = '';
while(<STDIN>) {
$stdin .= $_;
}
# Format line
my $formatted = LogFormatter($stdin);
# Print output prepended by rsyslog @cee log tag
print '@cee: '. $formatted . "\n";
}
#
# Log formatter
#
# Formats the input string around a json string w/ additional metadata
#
# http://stackoverflow.com/questions/8463919/how-to-convert-a-simple-hash-to-json-in-perl
#
# @param string the message we want to format
# @param channel The log channel
# @params string additional `key:value` pairs to add to each log entry
#
sub LogFormatter {
my $JSON = JSON->new->utf8;
$JSON->convert_blessed(1);
my $message = $_[0];
my %log = ("timestamp" => scalar(localtime()), "log_level" => "INFO", "channel" => $channel, "msg" => $message);
# Merge additional log parameters
@log{keys %extraLogParameters} = values %extraLogParameters;
# Json Encode
return $JSON->encode(\%log);
}
#
# Maps arguments of the form key:value into a hash
#
sub parseExtraCliParameters {
my %hash = ();
if(@_ + 1 > 2) {
for (my $i=2; $i < @_; $i++) {
my ($key, $value) = split /:/, $_[$i];
$hash{$key} = $value;
}
}
return %hash;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment