package Log::Saftpresse::Plugin::Amavis;

use Moose;

# ABSTRACT: plugin to parse amavisd-new logs
our $VERSION = '1.1'; # VERSION


extends 'Log::Saftpresse::Plugin';

with 'Log::Saftpresse::Plugin::Role::CounterUtils';

use JSON;

has 'json' => (
	is => 'ro', isa => 'JSON', lazy => 1,
	default => sub { JSON->new; },
);

has 'test_stats' => ( is => 'ro', isa => 'Bool', default => 1 );

sub process {
	my ( $self, $stash ) = @_;
	my $program = $stash->{'program'};
	if( ! defined $program || $program ne 'amavis' ) {
		return;
	}

	if ( my ( $log_id, $msg ) = $stash->{'message'} =~ /^\(([^\)]+)\) (.+)$/ ) {
		$stash->{'log_id'} = $log_id;
		$stash->{'message'} = $msg;
	}

	# if JSON logging is configured decode JSON
	if( $stash->{'message'} =~ /^{/ ) {
		my $json_data;
		eval {
			$json_data = $self->json->decode( $stash->{'message'} );
		};
		if( $@ ) { return; }
		if( ref($json_data) ne 'HASH' ) {
			return;
		}
		@$stash{keys %$json_data} = values %$json_data;
	}

	if( ! defined $stash->{'action'} ) {
		return;
	}

	$self->incr_host_one($stash, 'total' );
	$self->count_fields_occur( $stash, 'content_type' );
	$self->count_array_field_values( $stash, 'action' );
	$self->count_fields_value( $stash, 'size', 'score' );

	if( $self->test_stats ) {
		$self->count_array_field_values( $stash, 'tests' );
	}

	return;
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Log::Saftpresse::Plugin::Amavis - plugin to parse amavisd-new logs

=head1 VERSION

version 1.1

=head1 Description

This plugin parses Amavis log lines. Currently only JSON format log lines are parsed.

=head1 Synopsis

  <Plugin amavis>
    module = "Amavis"
    test_stats = 1
  </Plugin>

=head1 Options

=over

=item test_stats (default: 1)

Enable/disable generation of a counter per spam/ham test.

=back

=head1 Configure Amavis/Rsyslog for JSON output

First increase the maximum message size in rsyslog:

  $MaxMessageSize 32k

Then configure your $log_templ in amavisd.conf for JSON output:

  $logline_maxlen = ( 32*1024 ) - 50; # 32k max message size, keep 50 bytes for syslog
  $log_templ = <<'EOD';
  [:report_json]
  EOD

=head1 Input

This plugin expects a log line with

  'program' => 'amavis'

and an amavis report_json message like

  'message' => '(04529-01) {"@timestamp":"2015-06-12T04:51:48.725Z","action":["PASS"],...}'

=head1 Output

The plugin will outout the field log_id and will copy all fields
in the JSON data structure to the event.

=head1 Counters

The plugin will create the following counters:

  <host>.total
  <host>.content_type.<content_type>
  <host>.action.<action>
  <host>.size
  <host>.score

If option test_stats is enabled:

  <host>.tests.<test>

=head1 AUTHOR

Markus Benning <ich@markusbenning.de>

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 1998 by James S. Seymour, 2015 by Markus Benning.

This is free software, licensed under:

  The GNU General Public License, Version 2, June 1991

=cut
