[ トップ | 一覧 | 更新履歴 ]

Perl/Yaino/LogFile

PerlCGI | FrontPage

CGIのログ出力パッケージ

サンプルの第一弾、Yaino::LogFileです。 どんなCGIでも共通に使えるものは、Yaino/ ディレクトリに入れてperlライブラリパスに追加して使ってます。"Yaino"のところは、Commonでもいいですし、あなたのお名前でもいいです。 Developerの名前なんかがいいかと。意味的にも合ってるし。

なんか、サンプルが欲しい、サンプルがあれば改良して作れる、なんて要望があるのではないかと勝手に想像して公開します。ダメダメなところは掲示板でも、メールででもご指摘ください。

ログ出力

特にCGI用途に絞って、ログ出力のパッケージを作ってみます。

運用ログ

記録。CGIだと運用時のアクセス記録などをファイルに残します。記録をどのように活用するかで、複数のログを残す場合も多いです。 動作した日時、プログラム情報(CGI名、関数名、パラメータ)、アクセス情報(IP)、操作情報など。

記録先は、DBにぶちこむようなこともあるでしょうが、迅速に記録でき、しかも迅速に確認でき、ツール類を駆使できるテキストファイルに出力する場合が多いです。

ここで作るパッケージも、改行区切りの行単位テキストファイルに出力します。

Debug Log

デバッグ中にある時点での変数の状態などをファイルに出力し、分析するためのログです。

実運用のときは余計な負荷になるので通常、出力しないようにします。保険として、運用開始から一定期間、出力 するような場合もあるし、品質が悪いと顧客から「出しておけ、なにかあったらすぐ対処しろ」 なんて感じで、出したくなくても素敵なリクエストがあったりします。

特にCGIの開発では、httpヘッダー出力前に素でprint(標準出力に出力)するとServer Error必至ですから、ファイルに出力して分析したいことがあります。

とても古い手法ですが、着実でもあります。

デバッグツールに劣る点はブレークポイントを設定できない、実行途中にある条件の時に中断し、メモリの状態を確認する、なんてことができないですが。

ただし、デバッグ中は動くのに、デバッグオプション外して、本番環境に合わせると動かない なんてことが起きにくいです。

ログの話じゃなくなるけど、ある条件のときにプログラムを止め、再開させる、なんていうツールも後々作ってみたいと思います。socketあたりを使うことになるでしょうが。

仕様

オブジェクト生成

このパッケージが提供するのは、1つのログファイルにアクセスするオブジェクトになります。

sample(1.)

 $log = new Yaino::LogFile(
             log_dir   => './logs', # 出力ディレクトリ
             file_name => 'CGI',    # 出力ファイル名
             surfix    => '.log'    # ファイル名末尾(拡張子?)
 );

./logディレクトリにCGI.logというファイルに出力します。なければ作成し、あれば追加書きします。(ファイルはまだオープンしません)

             flag_date => 1,

このパラメータを追加すると、ファイル名に日付が追加されます。 sample(1.)に追加したとき、CGI[YYYYMMDD].logというファイル名になります。 YYYY,MM,DDはそれぞれ現在の西暦年、月、日となります。結果、1日ごとのログになります。

sample(2.)

 $log = new Yaino::LogFile;

とりあえず、オブジェクトを作ります。

オープン

 $log->open();

sample(1)のとき、この呼び出し方でオープンできます。

あるいは、new()のパラメータと同様のパラメータでopenを呼ぶことができます。

 $log->open(
             log_dir   => './logs', # 出力ディレクトリ
             file_name => 'CGI',    # 出力ファイル名
             surfix    => '.log'    # ファイル名末尾(拡張子?)
 );

書き込み

 $log->print('log messages', ...);

1行、書き込まれます。書式は、

 [YYYY/MM/DD hh:mm:ss]|[process id]| [message]\n

日付、時刻、プロセスID、そしてprint()の引数の文字列が出力されます。

 2002/10/08 22:08:13|1323| message

クローズ

 $log->close();

クローズします。 クローズ後、オブジェクトを破棄せずに再度openすることもできます。

Yaino::LogFile.pm ソース

WinNT系(ActivePerl), Linuxで動作を確認します。 flockを使うので、Win9xでは動作しません。

    1:  package Yaino::LogFile;
    2:  
    3:  ########################################################
    4:  #
    5:  #   output log-file package
    6:  #
    7:  #   $Id$
    8:  #
    9:  ########################################################
   10:  
   11:  require 5.005;  # Symbol.pmは5.005以降
   12:  
   13:  use strict;
   14:  use vars    qw($RCSID $VERSION);
   15:  
   16:  $VERSION = do{
   17:      my  @r=(q$Revision$ =~ /\d+/g);
   18:      sprintf "%d."."%02d" x $#r, @r
   19:  };
   20:  
   21:  BEGIN{
   22:      use Exporter;
   23:  
   24:      use Fcntl   qw(:DEFAULT :flock);    # import LOCK_* constants
   25:      use Symbol;                         # gensym, ungensym
   26:  
   27:      use vars    qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
   28:      @ISA        =qw(Exporter);
   29:      @EXPORT     =();
   30:      @EXPORT_OK  =();
   31:      %EXPORT_TAGS=(all=>[@EXPORT_OK,@EXPORT]);
   32:  }
   33:  
   34:  use vars    qw(@EXPORT_OK);
   35:  
   36:  ########################################################
   37:  
   38:  #===========================================
   39:  #   new
   40:  #-------------------------------------------
   41:  #   $obj = Yaino::LogFile->new(
   42:  #       log_dir         =>  $dir,
   43:  #       file_name       =>  $filename,
   44:  #       flag_date       =>  1,
   45:  #       surfix          =>  $surfix
   46:  #   );
   47:  #-------------------------------------------
   48:  sub new
   49:  {
   50:      my  $type   = shift;
   51:      my  %para   = @_;
   52:  
   53:      my  $class = ref($type) || $type || "Yaino::LogFile";
   54:  
   55:      my  $self = {
   56:              #--- file handle
   57:              fh          =>  gensym,
   58:              #--- seek parameter
   59:              SEEK_SET    =>  0,
   60:              SEEK_CUR    =>  1,
   61:              SEEK_END    =>  2,
   62:              #---
   63:              open_file   =>  '',
   64:              #--- パラメータをメンバー変数として設定
   65:              %para
   66:      };
   67:  
   68:      bless $self,$class;
   69:  }
   70:  
   71:  #===========================================
   72:  #   DESTROY
   73:  #-------------------------------------------
   74:  DESTROY
   75:  {
   76:      my  $self = shift;
   77:  
   78:      $self->{open_file} ne ''    and close    $self->{fh};
   79:      defined $self->{fh}         and ungensym $self->{fh};
   80:  }
   81:  
   82:  #===========================================
   83:  #   open
   84:  #------------------------------------------
   85:  #   $obj->open(
   86:  #       log_dir         =>  $dir,
   87:  #       file_name       =>  $filename
   88:  #   );
   89:  #------------------------------------------
   90:  #   ディレクトリ指定に'/'(UNIX系)あるいは
   91:  #   'C:/'(Win)のような、ルート指定はしていけない
   92:  #   (対応していない)
   93:  #------------------------------------------
   94:  #   Return
   95:  #       0   :normal end
   96:  #       -1  :parameter error
   97:  #       -2  :open error
   98:  #------------------------------------------
   99:  sub open
  100:  {
  101:      my  $self   =shift;
  102:      my  %para   =@_;
  103:  
  104:      #---------------------------------------------
  105:      #   ファイル名が指定されていないときエラー
  106:      #---------------------------------------------
  107:      return -1   if $para{file_name} eq '' && $self->{file_name} eq '';
  108:  
  109:      #----------------------------------
  110:      #   パラメータをメンバ変数に設定
  111:      #----------------------------------
  112:      grep{$self->{$_} = $para{$_};}  keys %para;
  113:  
  114:      #----------------------------------
  115:      #   ファイル名の末尾を設定
  116:      #----------------------------------
  117:      my  $date_str = (
  118:              defined $self->{flag_date} ?
  119:              $self->get_YYYYMMDD_str_now() :
  120:              ''
  121:      );
  122:  
  123:      #-----------------------
  124:      #   ログディレクトリ名の後ろに'/'があれば除去
  125:      #-----------------------
  126:      chop $self->{log_dir}   if $self->{log_dir} =~ /\/$/;
  127:  
  128:      #-----------------------
  129:      #   ファイル名
  130:      #-----------------------
  131:      #--- ディレクトリ指定なしならカレントを設定
  132:      $self->{log_dir} = '.'  if $self->{log_dir} eq '';
  133:      $self->{open_file} = $self->{log_dir} .
  134:                           '/' . 
  135:                           $self->{file_name} .
  136:                           $date_str .
  137:                           $self->{surfix};
  138:  
  139:      #-----------------------
  140:      #   open
  141:      #-----------------------
  142:      sysopen($self->{fh}, $self->{open_file}, O_RDWR|O_CREAT) or return -2;
  143:  
  144:      0;
  145:  }
  146:  
  147:  #===========================================
  148:  #   get_open_file_name
  149:  #-------------------------------------------
  150:  sub get_open_file_name
  151:  {
  152:      my  $self   =shift;
  153:      $self->{open_file};
  154:  }
  155:  
  156:  #===========================================
  157:  #   close
  158:  #-------------------------------------------
  159:  sub close
  160:  {
  161:      my  $self   =shift;
  162:      my  %para   =@_;
  163:  
  164:      close $self->{fh};
  165:      eval('chmod 0666,$self->{open_file};');
  166:  
  167:      $self->{open_file} = '';
  168:  }
  169:  
  170:  #===========================================
  171:  #   print
  172:  #-------------------------------------------
  173:  sub print
  174:  {
  175:      my  $self   =shift;
  176:      my  @para   =@_;
  177:  
  178:      my  $str_date = get_date_str_now();
  179:  
  180:      #-------------------------------
  181:      #   ファイルをロック
  182:      #-------------------------------
  183:      flock($self->{fh}, LOCK_EX)             or return -1;
  184:  
  185:  #### for Test ####
  186:  #print ">>>log file lock!\n";
  187:  ##################
  188:  
  189:      #---------------------------------------------
  190:      #   他のプロセスが追加している可能性があるため
  191:      #   ファイルポインタを終端に設定する
  192:      #---------------------------------------------
  193:      seek($self->{fh},0,$self->{SEEK_END})   or return -1;
  194:  
  195:      #-------------------------------
  196:      #   ファイル書き込み
  197:      #-------------------------------
  198:      $self->print_one_line($str_date, @para, "\n");
  199:  
  200:  #### for Test ####
  201:  #sleep 1;
  202:  #print "<<<log file unlock!\n";
  203:  ##################
  204:  
  205:      #-------------------------------
  206:      #   ファイルをアンロック
  207:      #-------------------------------
  208:      #   5.005以降ならunlock時にflushされる
  209:      #-------------------------------
  210:      flock($self->{fh}, LOCK_UN)             or return -1;
  211:  
  212:      0;
  213:  }
  214:  
  215:  #===========================================
  216:  #   print_one_line  (for override)
  217:  #-------------------------------------------
  218:  #   次の書式
  219:  #   [YYYYMMDD]|[process id]| comment
  220:  #   で出力する。違う書式で出力するなら、
  221:  #   このsubをoverrideする。
  222:  #-------------------------------------------
  223:  sub print_one_line
  224:  {
  225:      my  $self       = shift;
  226:      my  $str_date   = shift;
  227:      my  @para       = @_;
  228:  
  229:      print {$self->{fh}} $str_date, "|$$| ", @para;
  230:  }
  231:  
  232:  #===========================================
  233:  #   get_date_str_now
  234:  #-------------------------------------------
  235:  #   現在時刻を'YYYY/MM/DD hh:mm:ss'の書式で取得する
  236:  #-------------------------------------------
  237:  sub get_date_str_now
  238:  {
  239:      my  ($sec,$min,$hour,$mday,$mon,$year) = localtime();
  240:      $year += 1900   if $year < 1900;
  241:      $mon  += 1;
  242:      sprintf("%04d/%02d/%02d %02d:%02d:%02d",
  243:              $year, $mon, $mday, $hour, $min, $sec);
  244:  }
  245:  
  246:  #===========================================
  247:  #   get_YYYYMMDD_str_now
  248:  #-------------------------------------------
  249:  #   現在日付を'YYYYMMDD'の書式で取得する
  250:  #-------------------------------------------
  251:  sub get_YYYYMMDD_str_now
  252:  {
  253:      my  ($sec,$min,$hour,$mday,$mon,$year) = localtime();
  254:      $year += 1900   if $year < 1900;
  255:      $mon  += 1;
  256:      sprintf("%04d%02d%02d", $year, $mon, $mday);
  257:  }
  258:  
  259:  1;
  260:  
  261:  __END__
  262:  
  263:  ######################### POD ############################
  264:  
  265:  =pod
  266:  
  267:  開発のためのLogFile出力
  268:  
  269:  =head1 NAME
  270:  
  271:  Yaino::LogFile -- ログファイル出力
  272:  
  273:  =head1 VERSION
  274:  
  275:  $Revision$
  276:  
  277:  =head1 SYNOPSIS
  278:  
  279:      use Yaino::LogFile;
  280:      my $log = new Yaino::LogFile;
  281:  
  282:      $log->open(file_name => "filename");
  283:      $log->print("str", $val, ...);
  284:      $log->close();
  285:  
  286:  =head1 DESCRIPTION
  287:  
  288:   ログファイルにログを出力する。
  289:  テキストを1行づつ追加書きする。
  290:  行の先頭には日付、時刻、プロセスIDが付加される。
  291:  
  292:  log_dirで指定されたディレクトリに、
  293:      [log_dir]/[file_name][surfix]
  294:  の名前のファイルにログを出力する。
  295:  
  296:  flag_dateを0以外で指定すると、
  297:      [log_dir]/[file_name][YYYYMMDD][surfix]
  298:  の名前で1日ごとのファイルにログを出力する。(YYYYMMDDは現在日付)
  299:  
  300:  log_dirが省略されたとき、カレントディレクトリに出力する。
  301:  
  302:  flag_dateを指定したとき、出力するファイルはopen時の日付となる。
  303:  openしてから何日か経過した後にprintしても、そのファイルに出力される。
  304:  (
  305:      CGIで使う分にはありえないが、23:59:59にopen(),次の日にprintすれば、
  306:      前日のログに残ることはありえる。
  307:      プログラムが長時間動くようなときは、区切りでopen,closeを呼ぶべき。
  308:  )
  309:  
  310:  =over 4
  311:  
  312:  =item new()
  313:  
  314:  パラメータ log_dir,file_name,surfixはnew()、open()のどちらで指定してもよい。
  315:  両方でしていしたときopen()のパラメータが優先される。
  316:  
  317:      my $log = Yaino::LogFile->new();
  318:      my $log = Yaino::LogFile->new(log_dir=>"directory",file_name=>"file_name");
  319:  
  320:  =item open()
  321:  
  322:      $log->open(log_dir=>"directory", file_name=>"filename");
  323:      $log->open();
  324:  
  325:  =item print()
  326:  
  327:      $log->print("logstr");
  328:  
  329:  =item print_one_line()
  330:  
  331:      もし、出力書式を変えたいとき、この関数を変更するか、オーバーライドする。
  332:  
  333:  =item close()
  334:      $log->close();
  335:  
  336:  =back
  337:  
  338:  =head1 AUTHOR
  339:  
  340:  yaino <yaino@yaino.com>
  341:  
  342:  =cut
  343:  

解説

実質、100行もないくらいのソースなんで、解説もいらないでしょうけど。

1〜36行目 ソースヘッダ部

1行目はpackage宣言です。ひとつのファイルにpackage名を変えて複数の宣言をすることもできますが、1ソース(.pm)1 packageでいきます。

36行目まではいつもテンプレートからコピーして使ってます。元ネタは、どこかのサイトから 持ってきたか、サンプルコードで気に入ったやつからコピーしたんだと思います。

 $Id$
 $Revision$

これはCVSなどソースコード管理ツールで使います。 公開するようなときは、バージョン管理されたやつを公開するでしょうから、ここにId,Revisionが展開されて入っているのを見たことがあると思います。今回はあえて外して 素のコードを書きました。

 require [perl version];

のところは、私の場合は5.002を指定することが多いですが、今回はコメントにあるとおり、 Symbolを使うので5.005以上を指定してます。

私の場合、このヘッダ部分で変更するところは次の2点だけです。

EXPORT〜変数は私は使わないので、元のコードのまま、触ったことがありません。

38〜69行目 new

SEEK_SET,SEEK_CUR,SEEK_ENDの定数定義がみつからなかったので、ここでblessするhashに設定してます。flockで使うLOCK_〜は use Fcntlすることで定数として使えます。

ユニークなファイルハンドラを得るのにgensymを使ってます。ファイルハンドラは特殊な変数(?)であるため、オブジェクトのインスタンスが複数になったときに問題が起きることがあります。 注意さえすればいいのですが、難しいことは何も考えたくないので、gensymでハンドラを得る ことにしました。

open_fileは実際に開くファイル名です。open時にパラメータのディレクトリ名、ファイル名、surfixを くっつけた文字列が入ります。

そして、どんなパラメータが渡ってこようと、メンバ変数(blessするhashの要素)にしてしまい ます。 渡ってきたパラメータをチェックしてもいいのですが、多くの場合、徒労なので、もう直にメンバー変数です。

使い終わったら、DESTORYでungensymします。

71〜80行目 DESTROY

デストラクタです。オブジェクトが破棄されるときに呼ばれます。

ファイルをopenしたままcloseしてなかったら、closeします。 gensymでもらったハンドラをungensymで返却します。

たとえば、プログラム途中でdieしたときなども、blessされた変数なら、そのclassの DESTROYが呼ばれます。

82〜145行目 open

オープンはsysopen(142行目)を使ってます。ファイルであることがわかりきってる のでsysopen。openだとパイプがまぎれこんだりするので、対象がファイルと分かりきって いるときはsysopenを使ったほうがよさげなので。逆に汎用コーディングを犠牲にしますが。

ハンドラを得るのにFileHandleを使う手もありますが、flock使うのにハンドラを取り出さなければいけなかったり(flockメソッドがない)結局、煩雑なことをしなければならないので、 今回はgensymとsysopenでprint FH 〜することと割り切りました。

ファイルに書き込んでunlockする前にflushしようとしましたが、perl5.003のマイナーバージョンからunlock時にflushされるようになったのと、require 5.005してるのでflushの必要なしと判断しました。

自分のコーディングは、正常:0、異常:!=0を使います。組み込み関数とかと逆ですので注意 してください。

 sysopen($self->{fh}, $self->{open_file}, O_RDWR|O_CREAT)

sysopenを使い、O_RDWR|O_CREATモードでオープンします。ファイルが存在しなければ作成 します、存在すればRDWRモードで開きます。 「存在しなければ作成」はアトミックに行われます。 「存在チェック (-eなどで)」→「なければ作成」のように作ってしまうと、

 process1      process2
 存在チェック
     ↓        存在チェック
 ないので作成       ↓
               ないので作成

のように、作成がかち合うことが起こります。 上記のモードでオープンすると起こりません。

147〜154行目 get_open_file_name

現在オープン中のファイル名を返します。オープンしていなければ''を返します。 (undefの方がいい?)

156〜168行目 close

クローズします。可能であれば全ユーザでRead/Writeできるように属性を変更します。

''openもcloseも、open中にopenが呼ばれたとき、close中にcloseを呼ばれたときに対応 していません。あまりよくない。''

170〜213行目 print

ロック後、ファイルポインタを一番後ろにseekで移動します。 一行書き込んだら、アンロックします。

215〜230行目 print_one_line

実際に書き込む関数です。printのファイルハンドラのパラメータは、 gensymで得たハンドラを{}で囲まないといけない。

POD

PODの書き方、慣習が分かるサイトがあれば教えてください。 書かないでいるよりはいくらかまし、くらいのPODです。

テスト

テストプログラムのサンプルです。少しづついじっては、テストします。

基本動作のテスト

test01.pl

    1:  
    2:  use Yaino::LogFile;
    3:  
    4:      my  $log = new Yaino::LogFile(
    5:              log_dir     => 'logs',
    6:              flag_date   => 1,
    7:              file_name   => 'cgi_test_',
    8:              surfix      => '.log'
    9:      );
   10:  
   11:  print "call open\n";
   12:      $log->open and die print 'open error';
   13:  print "call get_open_file_name\n";
   14:      print 'open file:', $log->get_open_file_name, "\n";
   15:  
   16:  print "call print\n";
   17:      for(my $cnt=0; $cnt<100; $cnt++){
   18:          $log->print('test---', $cnt);
   19:      }
   20:  
   21:  print "call close\n";
   22:      $log->close;
   23:  
   24:  print "call exit\n";
   25:      exit;
   26:  

logs/ディレクトリを作っておきます。今日が2002/10/31だとすると、flag_dateが指定されて るので、日付ごとのログを書き込みます。

winならコマンドプロンプト、Linuxならシェルで実行します。

 % perl test01.pl
 call open
 call get_open_file_name
 open file:logs/cgi_test_20021031.log
 call print
 call close
 call exit

出力されたファイルの内容は、

cgi_test_2002031.log

 2002/10/31 23:04:40|1480| test---0
 2002/10/31 23:04:40|1480| test---1
 2002/10/31 23:04:40|1480| test---2
 2002/10/31 23:04:40|1480| test---3
 2002/10/31 23:04:40|1480| test---4
 2002/10/31 23:04:40|1480| test---5
 (以降省略)

こんな感じです。

ロックのテスト

consoleを2つ開いて、###for test###の部分のコメントを外しましす。書き込みに1秒かかる ようにsleepをいれています。 これで、console2つでテストプログラムを同時に動かします。交互にlockのメッセージが表示 されればロック動作していることが確認できます。

ログの内容がprocess IDが変わりつつ、交互に(とは限りませんが)連続した番号で出力されていればOKとなります。

ピーキーなテスト

###for test###のところをコメントアウトして元に戻します。

今度は、実際に複数プロセスで書き込み起こったときにでもファイル内容が欠落なく連続して 出力されるか確認します。

テストプログラムの$cntの上限を大きくしておきます。2プロセスのアクセスが重なりやすくするためです。 2つのconsoleでテストプログラムを実行します。

Linuxならシェルで

 % perl test01.pl & perl test01.pl

のように、並列で実行してみてもいいです。

かなり高負荷なテストになりますので、複数人で使ってるマシンでやるときは注意してください。

プロセスの切り替えはOS環境に依存しますので、どのような間隔でプロセスIDが変わるか特定はできません。

確認すべき点は、「欠落なく順番に出力される」ことです。

ちなみに、自分のWin2k,Linuxでは、数10行、同じプロセスで出力されて切り替わるような出力になりました。

テストチェックリスト

*open
ファイルがまだないとき
指定したディレクトリがないときエラー
指定したディレクトリがリードオンリーエラー
指定したディレクトリがあるとき指定したディレクトリにファイルが作成される
ディレクトリ名指定あり指定したディレクトリのファイルに書き込む
ディレクトリ名指定なしカレントディレクトリのファイルに書き込む
surfix指定ありfile_name,surfixを連結したファイル名のファイルに書き込む
surfix指定なしfile_name,YYYYMMDD(現在日付)を連結したファイル名のファイルに書き込む
file_name指定なしエラー
ファイルがあるとき
指定したディレクトリがリードオンリーエラー
指定したファイルがリードオンリーエラー
指定したディレクトリがあるとき指定したディレクトリのファイルに書き込む
ディレクトリ名指定あり指定したディレクトリのファイルに書き込む
ディレクトリ名指定なしカレントディレクトリのファイルに書き込む
surfix指定ありfile_name,surfixを連結したファイル名のファイルに書き込む
flag_date指定ありfile_name.YYYYMMDD(現在日付)を連結したファイル名のファイルに書き込む
surfix flag_date 指定ありfile_name.YYYYMMDD.surfixを連結したファイル名のファイルに書き込む
file_name指定なしエラー
*print
追加ファイルの最後に追加書きされる
書式規定の書式でかきこまれる
ロック他プロセスがロック中、書き込みを待つ
*close
呼び出されずオブジェクト破棄されたときcloseする

Yaino::LogFIleを継承して新しいpackageを作る

出力するログのフォーマットを変えてみます。既存package(ここではYaino::LogFile)に手を加えたくないときなんかにも有効です。

MyLog.pm

    1:  package MyLog;
    2:  
    3:  BEGIN{
    4:      use Yaino::LogFile;
    5:      @ISA        =qw(Yaino::LogFile);
    6:  }
    7:  
    8:  sub print_one_line
    9:  {
   10:      my  $self       = shift;
   11:      my  $str_date   = shift;
   12:      my  @para       = @_;
   13:  
   14:      print {$self->{fh}} $str_date, '>>>', @para;
   15:  }
   16:  

@ISAというグローバル配列変数に継承したいパッケージの名前を入れます。

出力のフォーマットを変えやすいように出力部分はprint_one_lineという関数になってますから、オーバーライドして出力形式を変えます。process idを出力しないようになって、メッセージの間に'>>>'が入るようになります。

使うときは、テストプログラムと同じでYaino::LogFileをMyLogに書き換えます。

IPを出力したい、なんて時は、new()するときに

 ip => $ip_address   # x.x.x.x

なんていうパラメータを追加して呼び出し、この関数の中で、

 $self->{ip}

をprintのパラメータに追加すればログに出力できます。 new()が、なんでもメンバ変数にしてしまうようにコーディングしてるからです。


GzuGzu (WikiWikiWeb descendant) ver 1.00 pre2
このページはGzuGzuで作成されました.
yaino.com