Mail-MtPolicyd

 view release on metacpan or  search on metacpan

lib/Mail/MtPolicyd/Plugin/Accounting.pm  view on Meta::CPAN

}

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;
}

sub update_accounting_row {
    my ( $self, $field, $key, $metrics ) = @_;
    my $dbh = $self->_db_handle;
    my $table_name = $dbh->quote_identifier( $self->get_table_name($field) );
    my $where = {
        'key' => $key,
        'time' => $self->get_timekey,
    };

    my $values_str = join(', ', map {
        $dbh->quote_identifier($_).'='.
            $dbh->quote_identifier($_).'+'.$dbh->quote($metrics->{$_})
    } keys %$metrics);
    my $where_str = join(' AND ', map {
        $dbh->quote_identifier($_).'='.$dbh->quote($where->{$_})
    } keys %$where );

    my $sql = "UPDATE $table_name SET $values_str WHERE $where_str";
    my $rows = $dbh->do($sql);
    if( $rows == 0 ) {
        die('accounting row does not exist');
    }

    return;
}

__PACKAGE__->meta->make_immutable;

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Mail::MtPolicyd::Plugin::Accounting - mtpolicyd plugin for accounting in sql tables

=head1 VERSION

version 2.05

=head1 SYNOPSIS

  <Plugin acct-clients>
    module = "Accounting"
    # per ip and user
    fields = "client_address,sasl_username"
    # statistics per month
    time_pattern = "%Y-%m"
    table_prefix = "acct_"
  </Plugin>

This will create a table acct_client_address and a table acct_sasl_username.

If a request is received containing the field the plugin will update the row
in the fields table. The key is the fields value(ip or username) and the time
string build from the time_pattern.



( run in 0.951 second using v1.01-cache-2.11-cpan-524268b4103 )