Mail-MtPolicyd
view release on metacpan or search on metacpan
lib/Mail/MtPolicyd/Plugin/Accounting.pm view on Meta::CPAN
package Mail::MtPolicyd::Plugin::Accounting;
use Moose;
use namespace::autoclean;
our $VERSION = '2.05'; # VERSION
# ABSTRACT: mtpolicyd plugin for accounting in sql tables
extends 'Mail::MtPolicyd::Plugin';
with 'Mail::MtPolicyd::Plugin::Role::UserConfig' => {
'uc_attributes' => [ 'enabled' ],
};
use Mail::MtPolicyd::Plugin::Result;
use Time::Piece;
has 'enabled' => ( is => 'rw', isa => 'Str', default => 'on' );
has 'fields' => ( is => 'rw', isa => 'Str', required => 1);
has '_fields' => ( is => 'ro', isa => 'ArrayRef', lazy => 1,
default => sub {
my $self = shift;
return [ split('\s*,\s*', $self->fields) ];
},
);
has 'time_pattern' => ( is => 'rw', isa => 'Str', default => '%Y-%m');
with 'Mail::MtPolicyd::Role::Connection' => {
name => 'db',
type => 'Sql',
};
with 'Mail::MtPolicyd::Plugin::Role::SqlUtils';
sub get_timekey {
my $self = shift;
return Time::Piece->new->strftime( $self->time_pattern );
}
has 'table_prefix' => ( is => 'rw', isa => 'Str', default => 'acct_');
sub run {
my ( $self, $r ) = @_;
my $session = $r->session;
if( $self->get_uc( $session, 'enabled') eq 'off' ) {
return;
}
if( $r->is_already_done( $self->name.'-acct' ) ) {
$self->log( $r, 'accounting already done for this mail, skipping...');
return;
}
my $metrics = $self->get_request_metrics( $r );
foreach my $field ( @{$self->_fields} ) {
my $key = $r->attr($field);
if( ! defined $key || $key =~ /^\s*$/ ) {
$self->log( $r, $field.' not defined in request, skipping...');
next;
}
$self->log( $r, 'updating accounting info for '.$field.' '.$key);
$self->update_accounting($field, $key, $metrics);
}
return;
}
sub init {
my $self = shift;
$self->check_sql_tables( %{$self->_table_definitions} );
return;
}
has '_single_table_create' => ( is => 'ro', isa => 'HashRef', lazy => 1,
default => sub { {
'mysql' => 'CREATE TABLE %TABLE_NAME% (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key` VARCHAR(255) NOT NULL,
`time` VARCHAR(255) NOT NULL,
`count` INT UNSIGNED NOT NULL,
`count_rcpt` INT UNSIGNED NOT NULL,
`size` INT UNSIGNED NOT NULL,
`size_rcpt` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `time_key` (`key`, `time`),
KEY(`key`),
KEY(`time`)
) ENGINE=%MYSQL_ENGINE% DEFAULT CHARSET=latin1',
'SQLite' => 'CREATE TABLE %TABLE_NAME% (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`key` VARCHAR(255) NOT NULL,
`time` VARCHAR(255) NOT NULL,
`count` INT UNSIGNED NOT NULL,
`count_rcpt` INT UNSIGNED NOT NULL,
`size` INT UNSIGNED NOT NULL,
`size_rcpt` INT UNSIGNED NOT NULL
)',
} }
);
sub get_table_name {
my ( $self, $field ) = @_;
return( $self->table_prefix . $field );
}
has '_table_definitions' => ( is => 'ro', isa => 'HashRef', lazy => 1,
default => sub {
my $self = shift;
my $tables = {};
foreach my $field ( @{$self->_fields} ) {
my $table_name = $self->get_table_name($field);
$tables->{$table_name} = $self->_single_table_create;
}
return $tables;
},
);
sub get_request_metrics {
my ( $self, $r ) = @_;
my $recipient_count = $r->attr('recipient_count');
my $size = $r->attr('size');
my $metrics = {};
my $rcpt_cnt = defined $recipient_count ? $recipient_count : 1;
$metrics->{'size'} = defined $size ? $size : 0;
$metrics->{'count'} = 1;
$metrics->{'count_rcpt'} = $rcpt_cnt ? $rcpt_cnt : 1;
$metrics->{'size_rcpt'} = $rcpt_cnt ? $size * $rcpt_cnt : $size;
return( $metrics );
}
sub update_accounting {
my ( $self, $field, $key, $metrics ) = @_;
eval {
$self->update_accounting_row($field, $key, $metrics);
};
if( $@ =~ /^accounting row does not exist/ ) {
$self->insert_accounting_row($field, $key, $metrics);
} elsif( $@ ) {
die( $@ );
}
return;
}
sub insert_accounting_row {
my ( $self, $field, $key, $metrics ) = @_;
my $dbh = $self->_db_handle;
my $table_name = $dbh->quote_identifier( $self->get_table_name($field) );
my $values = {
'key' => $key,
'time' => $self->get_timekey,
%$metrics,
};
my $col_str = join(', ', map {
$dbh->quote_identifier($_)
} keys %$values);
my $values_str = join(', ', map {
$dbh->quote($_)
} values %$values);
my $sql = "INSERT INTO $table_name ($col_str) VALUES ($values_str)";
$self->execute_sql($sql);
return;
( run in 0.962 second using v1.01-cache-2.11-cpan-97f6503c9c8 )