From 3430c898683771c0ecba9b53a55bb817da0e8fe8 Mon Sep 17 00:00:00 2001 From: Thomas Hochstein Date: Fri, 17 Sep 2010 21:53:59 +0200 Subject: [PATCH] Add comments and POD. Add comments NewsStats.pm Add POD to install.pl Add POD to feedlog.pl Add POD and comments to gatherstats.pl Add POD and comments to groupstats.pl, beautify code Signed-off-by: Thomas Hochstein --- NewsStats.pm | 48 ++++--- feedlog.pl | 140 ++++++++++++++++++ gatherstats.pl | 214 +++++++++++++++++++++++++++- groupstats.pl | 348 ++++++++++++++++++++++++++++++++++++++++++--- install/install.pl | 105 ++++++++++++++ 5 files changed, 811 insertions(+), 44 deletions(-) diff --git a/NewsStats.pm b/NewsStats.pm index 34635c1..a8c5b7b 100644 --- a/NewsStats.pm +++ b/NewsStats.pm @@ -58,8 +58,8 @@ our $MyVersion = "$MySelf $::VERSION (NewsStats.pm $VERSION)"; ################################################################################ sub ReadOptions { ################################################################################ -### read commandline options and act on standard options -### IN : $Params: containing list of commandline paramaters (without -h and -V) +### read commandline options and act on standard options -h and -V +### IN : $Params: list of legal commandline paramaters (without -h and -V) ### OUT: a hash containing the commandline options $Getopt::Std::STANDARD_HELP_VERSION = 1; @@ -116,7 +116,9 @@ sub OverrideConfig { ### $OverrideR: reference to a hash containing overrides my ($ConfigR,$OverrideR) = @_; my %Override = %$OverrideR; + # Config hash empty? warn "$MySelf W: Empty configuration hash passed to OverrideConfig().\n" if ( keys %$ConfigR < 1); + # return if no overrides return if (keys %Override < 1 or keys %$ConfigR < 1); foreach my $Key (keys %Override) { $$ConfigR{$Key} = $Override{$Key}; @@ -129,7 +131,7 @@ sub InitDB { ################################################################################ ### initialise database connection ### IN : $ConfigR: reference to configuration hash -### $Die : if TRUE, die if connection failed +### $Die : if TRUE, die if connection fails ### OUT: DBHandle my ($ConfigR,$Die) = @_; my %Conf = %$ConfigR; @@ -147,8 +149,10 @@ sub InitDB { ################################################################################ sub ListNewsgroups { ################################################################################ -### count each newsgroup and each hierarchy level, but only once -### IN : $Newsgroups: a list of newsgroups (content of Newsgroups:) +### explode a (scalar) list of newsgroup names to a list of newsgroup and +### hierarchy names where every newsgroup and hierarchy appears only once: +### de.alt.test,de.alt.admin -> de.ALL, de.alt.ALL, de.alt.test, de.alt.admin +### IN : $Newsgroups: a list of newsgroups (content of Newsgroups: header) ### OUT: %Newsgroups: hash containing all newsgroup and hierarchy names as keys my ($Newsgroups) = @_; my %Newsgroups; @@ -171,7 +175,8 @@ sub ListNewsgroups { ################################################################################ sub ParseHierarchies { ################################################################################ -### get all hierarchies a newsgroup belongs to +### return a list of all hierarchy levels a newsgroup belongs to +### (for de.alt.test.moderated that would be de/de.alt/de.alt.test) ### IN : $Newsgroup : a newsgroup name ### OUT: @Hierarchies: array containing all hierarchies the newsgroup belongs to my ($Newsgroup) = @_; @@ -194,9 +199,11 @@ sub ParseHierarchies { ################################################################################ sub GetTimePeriod { ################################################################################ -### get time period using -m / -p +### get a time period to act on, in order of preference: by default the +### last month; or a month submitted by -m YYYY-MM; or a time period submitted +### by -p YYYY-MM:YYYY-MM ### IN : $Month,$Period: contents of -m and -p -### OUT: $StartMonth, $EndMonth +### OUT: $StartMonth, $EndMonth (identical if period is just one month) my ($Month,$Period) = @_; # exit if -m is set and not like YYYY-MM die "$MySelf: E: Wrong date format - use '$MySelf -m YYYY-MM'!\n" if not &CheckMonth($Month); @@ -220,7 +227,7 @@ sub GetTimePeriod { ################################################################################ sub LastMonth { ################################################################################ -### get last month from today in YYYY-MM format +### get last month from todays date in YYYY-MM format ### OUT: last month as YYYY-MM # get today's date my (undef,undef,undef,undef,$Month,$Year,undef,undef,undef) = localtime(time); @@ -237,7 +244,7 @@ sub LastMonth { ################################################################################ sub CheckMonth { ################################################################################ -### check for valid month +### check if input is a valid month in YYYY-MM form ### IN : $Month: month ### OUT: TRUE / FALSE my ($Month) = @_; @@ -248,7 +255,7 @@ sub CheckMonth { ################################################################################ sub SplitPeriod { ################################################################################ -### split a time period YYYY-MM:YYYY-MM into start and end month +### split a time period denoted by YYYY-MM:YYYY-MM into start and end month ### IN : $Period: time period ### OUT: $StartMonth, Â$EndMonth my ($Period) = @_; @@ -265,7 +272,7 @@ sub SplitPeriod { ################################################################################ sub ListMonth { ################################################################################ -### return a list of month (YYYY-MM) between start and end month +### return a list of months (YYYY-MM) between start and end month ### IN : $StartMonth, $EndMonth ### OUT: @Months: array containing all months from $StartMonth to $EndMonth my ($StartMonth, $EndMonth) = @_; @@ -293,12 +300,11 @@ sub ListMonth { ################################################################################ sub OutputData { ################################################################################ -### output information with formatting from DBHandle +### read database query results from DBHandle and print results with formatting ### IN : $Format : format specifier ### $DBQuery: database query handle with executed query, ### containing $Month, $Key, $Value ### $PadGroup: padding length for newsgroups field (optional) for 'pretty' -### OUT: $Output: formatted output my ($Format, $DBQuery,$PadGroup) = @_; while (my ($Month, $Key, $Value) = $DBQuery->fetchrow_array) { print &FormatOutput($Format, $Month, $Key, $Value, $PadGroup); @@ -308,12 +314,12 @@ sub OutputData { ################################################################################ sub FormatOutput { ################################################################################ -### format information for output +### format information for output according to format specifier ### IN : $Format : format specifier -### $PadGroup: padding length for newsgroups field (optional) for 'pretty' ### $Month : month (as YYYY-MM) ### $Key : newsgroup, client, ... ### $Value : number of postings with that attribute +### $PadGroup: padding length for key field (optional) for 'pretty' ### OUT: $Output: formatted output my ($Format, $Month, $Key, $Value, $PadGroup) = @_; @@ -324,6 +330,7 @@ sub FormatOutput { die "$MySelf: E: Unknown output type '$Format'!\n" if !exists($LegalOutput{$Format}); my ($Output); + # keep last month in mind our ($LastIteration); if ($Format eq 'dump') { # output as dump (ng nnnnn) @@ -348,7 +355,9 @@ sub FormatOutput { ################################################################################ sub SQLHierarchies { ################################################################################ -### amend WHERE clause to include hierarchies +### add exclusion of hierarchy levels (de.alt.ALL) from SQL query by +### amending the WHERE clause if $ShowHierarchies is false (or don't, if it is +### true, accordingly) ### IN : $ShowHierarchies: boolean value ### OUT: SQL code my ($ShowHierarchies) = @_; @@ -358,7 +367,7 @@ sub SQLHierarchies { ################################################################################ sub GetMaxLenght { ################################################################################ -### get length of longest field in query +### get length of longest field in future query result ### IN : $DBHandle : database handel ### $Table : table to query ### $Field : field to check @@ -375,7 +384,8 @@ sub GetMaxLenght { ################################################################################ sub SQLGroupList { ################################################################################ -### create part of WHERE clause for list of newsgroups separated by : +### explode list of newsgroups separated by : (with wildcards) to a SQL WHERE +### clause ### IN : $Newsgroups: list of newsgroups (group.one.*:group.two:group.three.*) ### OUT: SQL code, list of newsgroups my ($Newsgroups) = @_; diff --git a/feedlog.pl b/feedlog.pl index a68b833..f33111d 100755 --- a/feedlog.pl +++ b/feedlog.pl @@ -85,3 +85,143 @@ $DBHandle->disconnect; syslog(LOG_NOTICE, "$MySelf closing down.") if !$Options{'q'}; closelog(); +__END__ + +################################ Documentation ################################# + +=head1 NAME + +feedlog - log data from an INN feed to a database + +=head1 SYNOPSIS + +B [B<-Vhdq>] + +=head1 REQUIREMENTS + +See doc/README: Perl 5.8.x itself and the following modules from CPAN: + +=over 2 + +=item - + +Config::Auto + +=item - + +Date::Format + +=item - + +DBI + +=back + +=head1 DESCRIPTION + +This script will log overview data and complete headers to a database +table for further examination by parsing a feed from INN. It will +parse that information and write it to a mysql database table in real +time. + +All reporting is done to I via I facility. If B +fails to initiate a database connection at startup, it will log to +I with I priority and go in an endless loop, as +terminating would only result in a rapid respawn. + +=head2 Configuration + +F will read its configuration from F which +should be present in the same directory via Config::Auto. + +See doc/INSTALL for an overview of possible configuration options. + +=head1 OPTIONS + +=over 3 + +=item B<-V> (version) + +Print out version and copyright information on B and exit. + +=item B<-h> (help) + +Print this man page and exit. + +=item B<-d> (debug) + +Output debugging information to STDERR while parsing STDIN. You'll +find that information most probably in your B F file. + +=item B<-q> (quiet) + +Suppress logging to syslog. + +=back + +=head1 INSTALLATION + +See doc/INSTALL. + +=head1 EXAMPLES + +Set up a feed like that in your B F file: + + ## gather statistics for NewsStats + newsstats! + :!*,de.* + :Tc,WmtfbsPNH,Ac:/path/to/feedlog.pl + +See doc/INSTALL for further information. + +=head1 FILES + +=over 4 + +=item F + +The script itself. + +=item F + +Library functions for the NewsStats package. + +=item F + +Runtime configuration file for B. + +=back + +=head1 BUGS + +Please report any bugs or feature requests to the author or use the +bug tracker at L! + +=head1 SEE ALSO + +=over 2 + +=item - + +doc/README + +=item - + +doc/INSTALL + +=back + +This script is part of the B package. + +=head1 AUTHOR + +Thomas Hochstein + +=head1 COPYRIGHT AND LICENSE + +Copyright (c) 2010 Thomas Hochstein + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + +=cut diff --git a/gatherstats.pl b/gatherstats.pl index 09157d1..4b4b8dd 100755 --- a/gatherstats.pl +++ b/gatherstats.pl @@ -47,11 +47,11 @@ $ConfOverride{'DBTableHosts'} = $Options{'s'} if $Options{'s'}; $ConfOverride{'TLH'} = $Options{'n'} if $Options{'n'}; &OverrideConfig(\%Conf,\%ConfOverride); -### get type of information to gather, default to 'all' +### get type of information to gather, defaulting to 'all' $Options{'t'} = 'all' if !$Options{'t'}; die "$MySelf: E: Unknown type '-t $Options{'t'}'!\n" if !exists($LegalTypes{$Options{'t'}}); -### get time period +### get time period (-m or -p) my ($StartMonth,$EndMonth) = &GetTimePeriod($Options{'m'},$Options{'p'}); ### init database @@ -94,9 +94,219 @@ foreach my $Month (&ListMonth($StartMonth,$EndMonth)) { $DBQuery->finish; }; }; + } else { + # other types of information go here - later on }; }; ### close handles $DBHandle->disconnect; +__END__ + +################################ Documentation ################################# + +=head1 NAME + +gatherstats - process statistical data from a raw source + +=head1 SYNOPSIS + +B [B<-Vhdo>] [B<-m> I] [B<-p> I] [B<-t> I] [B<-n> I] [B<-r> I] [B<-g> I] [B<-c> I] [B<-s> I] + +=head1 REQUIREMENTS + +See doc/README: Perl 5.8.x itself and the following modules from CPAN: + +=over 2 + +=item - + +Config::Auto + +=item - + +DBI + +=back + +=head1 DESCRIPTION + +This script will extract and process statistical information from a +database table which is fed from F for a given time period +and write its results to (an)other database table(s). + +The time period to act on defaults to last month; you can assign +another month via the B<-m> switch or a time period via the B<-p> +switch; the latter takes preference. + +By default B will process all types of information; you +can change that using the B<-t> switch and assigning the type of +information to process. Currently only processing of the number of +postings per group per month is implemented anyway, so that doesn't +matter yet. + +Possible information types include: + +=over 3 + +=item B (postings per group per month) + +B will examine Newsgroups: headers. Crosspostings will be +counted for each single group they appear in. Groups not in I +will be ignored. + +B will also add up the number of postings for each +hierarchy level, but only count each posting once. A posting to +de.alt.test will be counted for de.alt.test, de.alt.ALL and de.ALL, +respectively. A crossposting to de.alt.test and de.alt.admin, on the +other hand, will be counted for de.alt.test and de.alt.admin each, but +only once for de.alt.ALL and de.ALL. + +Data is written to I (see doc/INSTALL). + +=back + +=head2 Configuration + +F will read its configuration from F +which should be present in the same directory via Config::Auto. + +See doc/INSTALL for an overview of possible configuration options. + +You can override configuration options via the B<-n>, B<-r>, B<-g>, +B<-c> and B<-s> switches, respectively. + +=head1 OPTIONS + +=over 3 + +=item B<-V> (version) + +Print out version and copyright information on B and exit. + +=item B<-h> (help) + +Print this man page and exit. + +=item B<-d> (debug) + +Output debugging information to STDOUT while processing (number of +postings per group). + +=item B<-o> (output only) + +Do not write results to database. You should use B<-d> in conjunction +with B<-o> ... everything else seems a bit pointless. + +=item B<-m> I (month) + +Set processing period to a month in YYYY-MM format. Ignored if B<-p> +is set. + +=item B<-p> I (period) + +Set processing period to a time period between two month, each in +YYYY-MM format, separated by a colon. Overrides B<-m>. + +=item B<-t> I (type) + +Set processing type to one of I and I. Defaults to all +(and is currently rather pointless as only I has been +implemented). + +=item B<-n> I (newsgroup hierarchy) + +Override I from F. + +=item B<-r> I (raw data table) + +Override I from F. + +=item B<-g> I
(postings per group table) + +Override I from F. + +=item B<-c> I
(client data table) + +Override I from F. + +=item B<-s> I
(server/host data table) + +Override I from F. + +=back + +=head1 INSTALLATION + +See doc/INSTALL. + +=head1 EXAMPLES + +Process all types of information for lasth month: + + gatherstats + +Do a dry run, showing results of processing: + + gatherstats -do + +Process all types of information for January of 2010: + + gatherstats -m 2010-01 + +Process only number of postings for the year of 2010: + + gatherstats -p 2010-01:2010-12 -t groups + +=head1 FILES + +=over 4 + +=item F + +The script itself. + +=item F + +Library functions for the NewsStats package. + +=item F + +Runtime configuration file for B. + +=back + +=head1 BUGS + +Please report any bugs or feature requests to the author or use the +bug tracker at L! + +=head1 SEE ALSO + +=over 2 + +=item - + +doc/README + +=item - + +doc/INSTALL + +=back + +This script is part of the B package. + +=head1 AUTHOR + +Thomas Hochstein + +=head1 COPYRIGHT AND LICENSE + +Copyright (c) 2010 Thomas Hochstein + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + +=cut diff --git a/groupstats.pl b/groupstats.pl index b1e31e9..fcacc30 100755 --- a/groupstats.pl +++ b/groupstats.pl @@ -23,10 +23,6 @@ use NewsStats qw(:DEFAULT :TimePeriods :Output :SQLHelper); use DBI; -################################# Definitions ################################## - -# ... - ################################# Main program ################################# ### read commandline options @@ -75,13 +71,9 @@ if ($Options{'l'}) { warn ("$MySelf: W: Output type forced to '-o pretty' due to usage of '-l'.\n"); }; -### get query type, default to 'postings' -#die "$MySelf: E: Unknown query type -q $Options{'q'}!\n" if ($Options{'q'} and !exists($LegalTypes{$Options{'q'}})); -#die "$MySelf: E: You must submit a threshold ('-t') for query type '-q $Options{'q'}'!\n" if ($Options{'q'} and !$Options{'t'}); - ### get time period my ($StartMonth,$EndMonth) = &GetTimePeriod($Options{'m'},$Options{'p'}); -# reset to one month for 'dump' type +# reset to one month for 'dump' output type if ($Options{'o'} eq 'dump' and $Options{'p'}) { $StartMonth = $EndMonth; warn ("$MySelf: W: You cannot combine time periods (-p) with '-o dump'. Month was set to $StartMonth.\n"); @@ -90,80 +82,110 @@ if ($Options{'o'} eq 'dump' and $Options{'p'}) { ### init database my $DBHandle = InitDB(\%Conf,1); -### get data +### create report # get list of newsgroups (-n) my ($QueryPart,@GroupList); my $Newsgroups = $Options{'n'}; if ($Newsgroups) { + # explode list of newsgroups for WHERE clause ($QueryPart,@GroupList) = &SQLGroupList($Newsgroups); } else { + # set to dummy value (always true) $QueryPart = 1; }; # manage thresholds if (defined($Options{'t'})) { if ($Options{'i'}) { + # -i: list groups below threshold $QueryPart .= ' AND postings < ?'; } else { + # default: list groups above threshold $QueryPart .= ' AND postings > ?'; }; + # push threshold to GroupList to match number of binding vars for DBQuery->execute push @GroupList,$Options{'t'}; } # construct WHERE clause +# $QueryPart is "list of newsgroup" (or 1), +# &SQLHierarchies() takes care of the exclusion of hierarchy levels (.ALL) +# according to setting of -s my $WhereClause = sprintf('month BETWEEN ? AND ? AND %s %s',$QueryPart,&SQLHierarchies($Options{'s'})); # get lenght of longest newsgroup delivered by query for formatting purposes +# FIXME my $MaxLength = &GetMaxLenght($DBHandle,$Conf{'DBTableGrps'},'newsgroup',$WhereClause,$StartMonth,$EndMonth,@GroupList); my ($OrderClause,$DBQuery); -# -b (best of) defined? +# -b (best of / top list) defined? if (!defined($Options{'b'}) and !defined($Options{'l'})) { + # default: neither -b nor -l + # set ordering (ORDER BY) to "newsgroups" or "postings", "ASC" or "DESC" + # according to -q and -d $OrderClause = 'newsgroup'; $OrderClause = 'postings' if $Options{'q'}; $OrderClause .= ' DESC' if $Options{'d'}; - # do query: get number of postings per group from groups table for given months and newsgroups + # prepare query: get number of postings per group from groups table for given months and newsgroups $DBQuery = $DBHandle->prepare(sprintf("SELECT month,newsgroup,postings FROM %s.%s WHERE %s ORDER BY month,%s",$Conf{'DBDatabase'},$Conf{'DBTableGrps'},$WhereClause,$OrderClause)); } elsif ($Options{'b'}) { + # -b is set (then -l can't be!) # set sorting order (-i) if ($Options{'i'}) { $OrderClause = 'postings'; } else { $OrderClause = 'postings DESC'; }; - # push LIMIT to GroupList to match number of binding vars + # push LIMIT to GroupList to match number of binding vars for DBQuery->execute push @GroupList,$Options{'b'}; - # do query: get sum of postings per group from groups table for given months and newsgroups with LIMIT + # prepare query: get sum of postings per group from groups table for given months and newsgroups with LIMIT $DBQuery = $DBHandle->prepare(sprintf("SELECT newsgroup,SUM(postings) AS postings FROM %s.%s WHERE %s GROUP BY newsgroup ORDER BY %s,newsgroup LIMIT ?",$Conf{'DBDatabase'},$Conf{'DBTableGrps'},$WhereClause,$OrderClause)); -} else { # -l +} else { + # -l must be set now, as all other cases have been taken care of # set sorting order (-i) if ($Options{'i'}) { $OrderClause = '<'; } else { $OrderClause = '>'; }; - # push level and $StartMonth,$EndMonth - again - to GroupList to match number of binding vars + # push level and $StartMonth,$EndMonth - again - to GroupList to match number of binding vars for DBQuery->execute + # FIXME -- together with the query (see below) push @GroupList,$Options{'l'}; push @GroupList,$StartMonth,$EndMonth; - # do query: get number of postings per group from groups table for given months and + # prepare query: get number of postings per group from groups table for given months and + # FIXME -- this query is ... in dire need of impromevent $DBQuery = $DBHandle->prepare(sprintf("SELECT month,newsgroup,postings FROM %s.%s WHERE newsgroup IN (SELECT newsgroup FROM %s.%s WHERE %s GROUP BY newsgroup HAVING MAX(postings) %s ?) AND %s ORDER BY newsgroup,month",$Conf{'DBDatabase'},$Conf{'DBTableGrps'},$Conf{'DBDatabase'},$Conf{'DBTableGrps'},$WhereClause,$OrderClause,$WhereClause)); }; # execute query -$DBQuery->execute($StartMonth,$EndMonth,@GroupList) or die sprintf("$MySelf: E: Can't get groups data for %s to %s from %s.%s: %s\n",$StartMonth,$EndMonth,$Conf{'DBDatabase'},$Conf{'DBTableGrps'},$DBI::errstr); +$DBQuery->execute($StartMonth,$EndMonth,@GroupList) + or die sprintf("$MySelf: E: Can't get groups data for %s to %s from %s.%s: %s\n",$StartMonth,$EndMonth,$Conf{'DBDatabase'},$Conf{'DBTableGrps'},$DBI::errstr); -# output result +# output results +# print caption (-c) with time period if -m or -p is set +# FIXME - month or period should handled differently printf ("----- Report from %s to %s\n",$StartMonth,$EndMonth) if $Options{'c'} and ($Options{'m'} or $Options{'p'}); +# print caption (-c) with newsgroup list if -n is set printf ("----- Newsgroups: %s\n",join(',',split(/:/,$Newsgroups))) if $Options{'c'} and $Options{'n'}; +# print caption (-c) with threshold if -t is set, taking -i in account printf ("----- Threshold: %s %u\n",$Options{'i'} ? '<' : '>',$Options{'t'}) if $Options{'c'} and $Options{'t'}; if (!defined($Options{'b'}) and !defined($Options{'l'})) { - &OutputData($Options{'o'},$DBQuery,$MaxLength); + # default: neither -b nor -l + &OutputData($Options{'o'},$DBQuery,$MaxLength); } elsif ($Options{'b'}) { - while (my ($Newsgroup,$Postings) = $DBQuery->fetchrow_array) { + # -b is set (then -l can't be!) + # we have to read in the query results ourselves, as they do not have standard layout + while (my ($Newsgroup,$Postings) = $DBQuery->fetchrow_array) { + # we just assign "top x" or "bottom x" instead of a month for the caption + # FIXME print &FormatOutput($Options{'o'}, ($Options{'i'} ? 'Bottom ' : 'Top ').$Options{'b'}, $Newsgroup, $Postings, $MaxLength); }; -} else { # -l - while (my ($Month,$Newsgroup,$Postings) = $DBQuery->fetchrow_array) { +} else { + # -l must be set now, as all other cases have been taken care of + # we have to read in the query results ourselves, as they do not have standard layout + while (my ($Month,$Newsgroup,$Postings) = $DBQuery->fetchrow_array) { + # we just switch $Newsgroups and $Month for output generation + # FIXME print &FormatOutput($Options{'o'}, $Newsgroup, $Month, $Postings, 7); }; }; @@ -171,3 +193,283 @@ if (!defined($Options{'b'}) and !defined($Options{'l'})) { ### close handles $DBHandle->disconnect; +__END__ + +################################ Documentation ################################# + +=head1 NAME + +groupstats - create reports on newsgroup usage + +=head1 SYNOPSIS + +B [B<-Vhiscqd>] [B<-m> I] [B<-p> I] [B<-n> I] [B<-t> I] [B<-l> I] [B<-b> I] [B<-o> I] [B<-g> I] + +=head1 REQUIREMENTS + +See doc/README: Perl 5.8.x itself and the following modules from CPAN: + +=over 2 + +=item - + +Config::Auto + +=item - + +DBI + +=back + +=head1 DESCRIPTION + +This script create reports on newsgroup usage (number of postings per +group per month) taken from result tables created by +F. + +The time period to act on defaults to last month; you can assign +another month via the B<-m> switch or a time period via the B<-p> +switch; the latter takes preference. + +B will process all newsgroups by default; you can limit +that to only some newsgroups by supplying a list of those groups via +B<-n> (see below). You can include hierarchy levels in the output by +adding the B<-s> switch (see below). + +Furthermore you can set a threshold via B<-t> so that only newsgroups +with more postings per month will be included in the report. You can +invert that by the B<-i> switch so only newsgroups with less than +I postings per month will be included. + +You can sort the output by number of postings per month instead of the +default (alphabetical list of newsgroups) by using B<-q>; you can +reverse the sorting order (from highest to lowest or in reversed +alphabetical order) by using B<-d>. + +Furthermore, you can create a list of newsgroups that had consistently +more (or less) than x postings per month during the whole report +period by using B<-l> (together with B as needed). + +Last but not least you can create a "best of" list of the top x +newsgroups via B<-b> (or a "worst of" list by adding B). + +By default, B will dump a very simple alphabetical list of +newsgroups, one per line, followed by the number of postings in that +month. This output format of course cannot sensibly be combined with +time periods, so you can set the output format by using B<-o> (see +below). Captions can be added by setting the B<-c> switch. + +=head2 Configuration + +F will read its configuration from F +which should be present in the same directory via Config::Auto. + +See doc/INSTALL for an overview of possible configuration options. + +You can override configuration options via the B<-g> switch. + +=head1 OPTIONS + +=over 3 + +=item B<-V> (version) + +Print out version and copyright information on B and exit. + +=item B<-h> (help) + +Print this man page and exit. + +=item B<-m> I (month) + +Set processing period to a month in YYYY-MM format. Ignored if B<-p> +is set. + +=item B<-p> I (period) + +Set processing period to a time period between two month, each in +YYYY-MM format, separated by a colon. Overrides B<-m>. + +=item B<-n> I (newsgroups) + +Limit processing to a certain set of newsgroups. I can +be a single newsgroup name (de.alt.test), a newsgroup hierarchy +(de.alt.*) or a list of either of these, separated by colons, for +example + + de.test:de.alt.test:de.newusers.* + +=item B<-t> I (threshold) + +Only include newsgroups with more than I postings per +month. Can be inverted by the B<-i> switch so that only newsgroups +with less than I postings will be included. + +This setting will be ignored if B<-l> or B<-b> is set. + +=item B<-l> I (level) + +Only include newsgroups with more than I postings per +month, every month during the whole reporting period. Can be inverted +by the B<-i> switch so that only newsgroups with less than I +postings every single month will be included. Output will be ordered +by newsgroup name, followed by month. + +This setting will be ignored if B<-b> is set. Overrides B<-t> and +can't be used together with B<-q> or B<-d>. + +=item B<-b> I (best of) + +Create a list of the I newsgroups with the most postings over the +whole reporting period. Can be inverted by the B<-i> switch so that a +list of the I newsgroups with the least postings over the whole +period is generated. Output will be ordered by sum of postings. + +Overrides B<-t> and B<-l> and can't be used together with B<-q> or +B<-d>. Output format is set to I (see below). + +=item B<-i> (invert) + +Used in conjunction with B<-t>, B<-l> or B<-b> to set a lower +threshold or level or generate a "bottom list" instead of a top list. + +=item B<-s> (sum per hierarchy level) + +Include "virtual" groups for every hierarchy level in output, for +example: + + de.alt.ALL 10 + de.alt.test 5 + de.alt.admin 7 + +See the B man page for details. + +=item B<-o> I (output format) + +Set output format. Default is I, consisting of an alphabetical +list of newsgroups, each on a new line, followed by the number of +postings in that month. This default format can't be used with time +periods of more than one month. + +I format is like I, but will print the month in front of +the newsgroup name. + +I format can only be use with a group list (see B<-n>) of +exactly one newsgroup and is like I, but will output months, +followed by the number of postings. + +If you don't need easily parsable output, you'll mostly use I +format, which will print a header for each new month and try to align +newsgroup names and posting counts. Usage of B<-b> will force this +format. + +=item B<-c> (captions) + +Add captions to output (reporting period, newsgroups list, threshold). + +=item B<-q> (quantity of postings) + +Sort by number of postings instead of by newsgroup names. + +Cannot be used with B<-l> or B<-b>. + +=item B<-d> (descending) + +Change sort order to descending. + +Cannot be used with B<-l> or B<-b>. + +=item B<-g> I
(postings per group table) + +Override I from F. + +=back + +=head1 INSTALLATION + +See doc/INSTALL. + +=head1 EXAMPLES + +Show number of postings per group for lasth month in I format: + + groupstats + +Show that report for January of 2010 and de.alt.* plus de.test, +including display of hierarchy levels: + + groupstats -m 2010-01 -n de.alt.*:de.test -s + +Show that report for the year of 2010 in I format: + + groupstats -p 2010-01:2010-12 -o pretty + +Only show newsgroups with less than 30 postings last month, ordered +by number of postings, descending, in I format: + + groupstats -iqdt 30 -o pretty + +Show top 10 for the first half-year of of 2010 in I format: + + groupstats -p 2010-01:2010-06 -b 10 -o pretty + +Report all groups that had less than 30 postings every singele month +in the year of 2010 (I format is forced) + + groupstats -p 2010-01:2010-12 -il 30 + +=head1 FILES + +=over 4 + +=item F + +The script itself. + +=item F + +Library functions for the NewsStats package. + +=item F + +Runtime configuration file for B. + +=back + +=head1 BUGS + +Please report any bugs or feature requests to the author or use the +bug tracker at L! + +=head1 SEE ALSO + +=over 2 + +=item - + +doc/README + +=item - + +doc/INSTALL + +=item - + +gatherstats -h + +=back + +This script is part of the B package. + +=head1 AUTHOR + +Thomas Hochstein + +=head1 COPYRIGHT AND LICENSE + +Copyright (c) 2010 Thomas Hochstein + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + +=cut diff --git a/install/install.pl b/install/install.pl index 8db7d6a..1417e5f 100755 --- a/install/install.pl +++ b/install/install.pl @@ -150,3 +150,108 @@ Enjoy! -thh TODO + +__END__ + +################################ Documentation ################################# + +=head1 NAME + +install - installation script + +=head1 SYNOPSIS + +B [B<-Vh>] + +=head1 REQUIREMENTS + +See doc/README: Perl 5.8.x itself and the following modules from CPAN: + +=over 2 + +=item - + +Config::Auto + +=item - + +DBI + +=back + +=head1 DESCRIPTION + +This script will create database tables as necessary and configured. + +=head2 Configuration + +F will read its configuration from F via +Config::Auto. + +See doc/INSTALL for an overview of possible configuration options. + +=head1 OPTIONS + +=over 3 + +=item B<-V> (version) + +Print out version and copyright information on B and exit. + +=item B<-h> (help) + +Print this man page and exit. + +=back + +=head1 FILES + +=over 4 + +=item F + +The script itself. + +=item F + +Library functions for the NewsStats package. + +=item F + +Runtime configuration file for B. + +=back + +=head1 BUGS + +Please report any bugs or feature requests to the author or use the +bug tracker at L! + +=head1 SEE ALSO + +=over 2 + +=item - + +doc/README + +=item - + +doc/INSTALL + +=back + +This script is part of the B package. + +=head1 AUTHOR + +Thomas Hochstein + +=head1 COPYRIGHT AND LICENSE + +Copyright (c) 2010 Thomas Hochstein + +This program is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + +=cut -- 2.20.1