Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Trying to write a log function

Reply
Thread Tools

Trying to write a log function

 
 
Simon
Guest
Posts: n/a
 
      07-04-2007
Hi guys!

Hope you can help.
Im a newbie to this, but have some sample code that Im trying to understand.
The goal is that I can successfully write a log function that writes
messages to a log file.
Please bare with me as I dont fully understand the below code, which is
where I need your gurus expertise.
Here is the code, which is not working, but Id like to try and find out how
i can get it to work to write messages to a log file.
Any help appreciated.
Thank you.

================================================== ==================== code

sub Log {

@g = localtime time;
open(LOG,">>$LogFile");
printf LOG "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];
printf "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];
close(LOG);

}

sub WaitForInstall() {

Log " Waiting for installation to complete";
sleep 10;
$finished = 0;
while (!$finished) {
sleep 5;
$finished = 1; # assume we're finished
open(PS,"$PSCMD|");
while (<PS>) {

if ($_ =~ /$Product Setup/i) {
$finished = 0; # not finished
}
elsif ($_ =~ /$Product/i) {
$finished = 0; # not finished
}
}
close(PS);
}

}


$LogFile = "C:\\logs\\$Product.log";

================================================== ==================== code

So basically, what Im trying to do is, insert a Log function into particular
parts of the script, and wherever I insert the Log function, to write that
line to Product.log.
The above is only a snippet.
Any help will be great.
I just dont know how to call the Log function, or how to actually write it
to be honest.
The below is my objective.

1) Write a log function (subroutine)
2) Being able to call that log subroutine anywhere in my script, and log
messages from that call to a text file.

Thanku in advance.



 
Reply With Quote
 
 
 
 
John W. Krahn
Guest
Posts: n/a
 
      07-04-2007
Simon wrote:
>
> Hope you can help.
> Im a newbie to this, but have some sample code that Im trying to understand.
> The goal is that I can successfully write a log function that writes
> messages to a log file.
> Please bare with me as I dont fully understand the below code, which is
> where I need your gurus expertise.
> Here is the code, which is not working, but Id like to try and find out how
> i can get it to work to write messages to a log file.
> Any help appreciated.
> Thank you.
>
> ================================================== ==================== code


You should have these two lines at the beginning of your program and let perl
help you find mistakes:

use warnings;
use strict;


> sub Log {
>
> @g = localtime time;
> open(LOG,">>$LogFile");


You should *ALWAYS* verify that your file opened correctly:

open LOG, '>>', $LogFile or die "Cannot open '$LogFile' $!";

This would have caught the error that $LogFile has *no* value here because it
is not assigned a value until later in the program.


> printf LOG "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];


The correct way to get the year (as described in 'perldoc -f localtime') is to
add 1900 to the sixth element of the list returned from localtime so that
expression could be more concisely written as:

printf LOG "%04d/%02d/%02d %02d:%02d:%02d %s\n", $g[ 5 ] + 1900, $g[ 4 ]
+ 1, @g[ 3, 2, 1, 0 ], $_[ 0 ];


> printf "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];


Same as above.


> close(LOG);
>
> }
>
> sub WaitForInstall() {
>
> Log " Waiting for installation to complete";
> sleep 10;
> $finished = 0;
> while (!$finished) {
> sleep 5;
> $finished = 1; # assume we're finished
> open(PS,"$PSCMD|");


You should *ALWAYS* verify that your file opened correctly:

open PS, '-|', $PSCMD or die "Cannot open pipe from '$PSCMD' $!";


> while (<PS>) {
>
> if ($_ =~ /$Product Setup/i) {
> $finished = 0; # not finished
> }
> elsif ($_ =~ /$Product/i) {
> $finished = 0; # not finished
> }
> }
> close(PS);


And with a pipe you should also verify that it closed correctly:

close PS or warn $! ? "Error closing '$PSCMD' pipe: $!"
: "Exit status $? from '$PSCMD'";


> }
>
> }



John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
 
Reply With Quote
 
 
 
 
Mumia W.
Guest
Posts: n/a
 
      07-04-2007
On 07/03/2007 09:35 PM, Simon wrote:
> Hi guys!
>
> Hope you can help.
> Im a newbie to this, but have some sample code that Im trying to understand.
> The goal is that I can successfully write a log function that writes
> messages to a log file.
> Please bare with me as I dont fully understand the below code, which is
> where I need your gurus expertise.
> Here is the code, which is not working, but Id like to try and find out how
> i can get it to work to write messages to a log file.
> Any help appreciated.
> Thank you.
>
> ================================================== ==================== code
>
> sub Log {
>
> @g = localtime time;
> open(LOG,">>$LogFile");
> printf LOG "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];
> printf "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];
> close(LOG);
>
> }
>
> sub WaitForInstall() {
>
> Log " Waiting for installation to complete";
> sleep 10;
> $finished = 0;
> while (!$finished) {
> sleep 5;
> $finished = 1; # assume we're finished
> open(PS,"$PSCMD|");
> while (<PS>) {
>
> if ($_ =~ /$Product Setup/i) {
> $finished = 0; # not finished
> }
> elsif ($_ =~ /$Product/i) {
> $finished = 0; # not finished
> }
> }
> close(PS);
> }
>
> }
>
>
> $LogFile = "C:\\logs\\$Product.log";
>
> ================================================== ==================== code
>
> So basically, what Im trying to do is, insert a Log function into particular
> parts of the script, and wherever I insert the Log function, to write that
> line to Product.log.
> The above is only a snippet.
> Any help will be great.
> I just dont know how to call the Log function, or how to actually write it
> to be honest.
> The below is my objective.
>
> 1) Write a log function (subroutine)
> 2) Being able to call that log subroutine anywhere in my script, and log
> messages from that call to a text file.
>
> Thanku in advance.
>
>
>


These are the problems I see with your program so far:
$LogFile is defined too late for it to be useful for the Log function.
The code in Log is too convoluted even though it probably just prints
the time and some text. Parenthesis are needed with function calls if
Perl hasn't been made aware ahead of time that the function is a function.

This site can help you learn about Perl:
http://perldoc.perl.org/perl.html

After reading that page, you should read "perlintro."
 
Reply With Quote
 
Simon
Guest
Posts: n/a
 
      07-04-2007
Hi Mumia!

Thank you so much for your input and help.
Appreciate your comments.
Thanks again :>)

"Mumia W." <(E-Mail Removed)> wrote in message
news:b8Kii.4035$(E-Mail Removed) ink.net...
> On 07/03/2007 09:35 PM, Simon wrote:
>> Hi guys!
>>
>> Hope you can help.
>> Im a newbie to this, but have some sample code that Im trying to
>> understand.
>> The goal is that I can successfully write a log function that writes
>> messages to a log file.
>> Please bare with me as I dont fully understand the below code, which is
>> where I need your gurus expertise.
>> Here is the code, which is not working, but Id like to try and find out
>> how i can get it to work to write messages to a log file.
>> Any help appreciated.
>> Thank you.
>>
>> ================================================== ====================
>> code
>>
>> sub Log {
>>
>> @g = localtime time;
>> open(LOG,">>$LogFile");
>> printf LOG "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
>> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
>> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];
>> printf "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
>> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
>> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];
>> close(LOG);
>>
>> }
>>
>> sub WaitForInstall() {
>>
>> Log " Waiting for installation to complete";
>> sleep 10;
>> $finished = 0;
>> while (!$finished) {
>> sleep 5;
>> $finished = 1; # assume we're finished
>> open(PS,"$PSCMD|");
>> while (<PS>) {
>>
>> if ($_ =~ /$Product Setup/i) {
>> $finished = 0; # not finished
>> }
>> elsif ($_ =~ /$Product/i) {
>> $finished = 0; # not finished
>> }
>> }
>> close(PS);
>> }
>>
>> }
>>
>>
>> $LogFile = "C:\\logs\\$Product.log";
>>
>> ================================================== ====================
>> code
>>
>> So basically, what Im trying to do is, insert a Log function into
>> particular parts of the script, and wherever I insert the Log function,
>> to write that line to Product.log.
>> The above is only a snippet.
>> Any help will be great.
>> I just dont know how to call the Log function, or how to actually write
>> it to be honest.
>> The below is my objective.
>>
>> 1) Write a log function (subroutine)
>> 2) Being able to call that log subroutine anywhere in my script, and log
>> messages from that call to a text file.
>>
>> Thanku in advance.
>>
>>
>>

>
> These are the problems I see with your program so far:
> $LogFile is defined too late for it to be useful for the Log function. The
> code in Log is too convoluted even though it probably just prints the time
> and some text. Parenthesis are needed with function calls if Perl hasn't
> been made aware ahead of time that the function is a function.
>
> This site can help you learn about Perl:
> http://perldoc.perl.org/perl.html
>
> After reading that page, you should read "perlintro."



 
Reply With Quote
 
Simon
Guest
Posts: n/a
 
      07-04-2007
John!

Youre so kind to have spent some time on this for me.
I really appreciate your comments.
Thansk John.

Simon

"John W. Krahn" <(E-Mail Removed)> wrote in message
news:i_Fii.26076$xk5.3904@edtnps82...
> Simon wrote:
>>
>> Hope you can help.
>> Im a newbie to this, but have some sample code that Im trying to
>> understand.
>> The goal is that I can successfully write a log function that writes
>> messages to a log file.
>> Please bare with me as I dont fully understand the below code, which is
>> where I need your gurus expertise.
>> Here is the code, which is not working, but Id like to try and find out
>> how i can get it to work to write messages to a log file.
>> Any help appreciated.
>> Thank you.
>>
>> ================================================== ====================
>> code

>
> You should have these two lines at the beginning of your program and let
> perl help you find mistakes:
>
> use warnings;
> use strict;
>
>
>> sub Log {
>>
>> @g = localtime time;
>> open(LOG,">>$LogFile");

>
> You should *ALWAYS* verify that your file opened correctly:
>
> open LOG, '>>', $LogFile or die "Cannot open '$LogFile' $!";
>
> This would have caught the error that $LogFile has *no* value here because
> it is not assigned a value until later in the program.
>
>
>> printf LOG "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
>> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
>> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];

>
> The correct way to get the year (as described in 'perldoc -f localtime')
> is to add 1900 to the sixth element of the list returned from localtime so
> that expression could be more concisely written as:
>
> printf LOG "%04d/%02d/%02d %02d:%02d:%02d %s\n", $g[ 5 ] + 1900,
> $g[ 4 ] + 1, @g[ 3, 2, 1, 0 ], $_[ 0 ];
>
>
>> printf "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
>> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
>> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];

>
> Same as above.
>
>
>> close(LOG);
>>
>> }
>>
>> sub WaitForInstall() {
>>
>> Log " Waiting for installation to complete";
>> sleep 10;
>> $finished = 0;
>> while (!$finished) {
>> sleep 5;
>> $finished = 1; # assume we're finished
>> open(PS,"$PSCMD|");

>
> You should *ALWAYS* verify that your file opened correctly:
>
> open PS, '-|', $PSCMD or die "Cannot open pipe from '$PSCMD' $!";
>
>
>> while (<PS>) {
>>
>> if ($_ =~ /$Product Setup/i) {
>> $finished = 0; # not finished
>> }
>> elsif ($_ =~ /$Product/i) {
>> $finished = 0; # not finished
>> }
>> }
>> close(PS);

>
> And with a pipe you should also verify that it closed correctly:
>
> close PS or warn $! ? "Error closing '$PSCMD' pipe: $!"
> : "Exit status $? from '$PSCMD'";
>
>
>> }
>>
>> }

>
>
> John
> --
> Perl isn't a toolbox, but a small machine shop where you
> can special-order certain sorts of tools at low cost and
> in short order. -- Larry Wall



 
Reply With Quote
 
Tim Southerwood
Guest
Posts: n/a
 
      07-04-2007
Mumia W. wrote:

> On 07/03/2007 09:35 PM, Simon wrote:
>> Hi guys!
>>
>> Hope you can help.
>> Im a newbie to this, but have some sample code that Im trying to
>> understand. The goal is that I can successfully write a log function that
>> writes messages to a log file.
>> Please bare with me as I dont fully understand the below code, which is
>> where I need your gurus expertise.
>> Here is the code, which is not working, but Id like to try and find out
>> how i can get it to work to write messages to a log file.
>> Any help appreciated.
>> Thank you.
>>
>> ================================================== ====================
>> code
>>
>> sub Log {
>>
>> @g = localtime time;
>> open(LOG,">>$LogFile");
>> printf LOG "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
>> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
>> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];
>> printf "%02d%02d/%02d/%02d %02d:%02d:%02d $_[0]\n",
>> sprintf("%02d",(substr sprintf("%03d",$g[5]), 0, 1) + 19),(substr
>> sprintf("%03d",$g[5]), 1, 2),$g[4]+1,$g[3],$g[2],$g[1],$g[0];
>> close(LOG);
>>
>> }
>>
>> sub WaitForInstall() {
>>
>> Log " Waiting for installation to complete";
>> sleep 10;
>> $finished = 0;
>> while (!$finished) {
>> sleep 5;
>> $finished = 1; # assume we're finished
>> open(PS,"$PSCMD|");
>> while (<PS>) {
>>
>> if ($_ =~ /$Product Setup/i) {
>> $finished = 0; # not finished
>> }
>> elsif ($_ =~ /$Product/i) {
>> $finished = 0; # not finished
>> }
>> }
>> close(PS);
>> }
>>
>> }
>>
>>
>> $LogFile = "C:\\logs\\$Product.log";
>>
>> ================================================== ====================
>> code
>>
>> So basically, what Im trying to do is, insert a Log function into
>> particular parts of the script, and wherever I insert the Log function,
>> to write that line to Product.log.
>> The above is only a snippet.
>> Any help will be great.
>> I just dont know how to call the Log function, or how to actually write
>> it to be honest.
>> The below is my objective.
>>
>> 1) Write a log function (subroutine)
>> 2) Being able to call that log subroutine anywhere in my script, and log
>> messages from that call to a text file.
>>
>> Thanku in advance.
>>
>>
>>

>
> These are the problems I see with your program so far:
> $LogFile is defined too late for it to be useful for the Log function.
> The code in Log is too convoluted even though it probably just prints
> the time and some text. Parenthesis are needed with function calls if
> Perl hasn't been made aware ahead of time that the function is a function.
>
> This site can help you learn about Perl:
> http://perldoc.perl.org/perl.html
>
> After reading that page, you should read "perlintro."


I agree, and I would add:

Opening and closing the file on every call to Log() is expensive. One
usually opens it once and then keeps the file handle around.

In this case, it might be considered "good manners" to have the program
respond to SIGHUP to close and reopen the log file for the benefit of
logrotation, though logrotate can work around this if necessary.

Hint to the OP: Try POSIX::strftime()

Cheers

Tim
 
Reply With Quote
 
Jürgen Exner
Guest
Posts: n/a
 
      07-04-2007
Tim Southerwood wrote:
> Opening and closing the file on every call to Log() is expensive.


True.

> One
> usually opens it once and then keeps the file handle around.


Depends. If you want to capture the last breath of your program before it
dies an untimely death then you don't want to risk loosing its last words in
an unsaved buffer.

jue


 
Reply With Quote
 
Tim Southerwood
Guest
Posts: n/a
 
      07-04-2007
Jürgen Exner wrote:

> Tim Southerwood wrote:
>> Opening and closing the file on every call to Log() is expensive.

>
> True.
>
>> One
>> usually opens it once and then keeps the file handle around.

>
> Depends. If you want to capture the last breath of your program before it
> dies an untimely death then you don't want to risk loosing its last words
> in an unsaved buffer.
>
> jue


That's fair, but then it would still be cheaper to sysopen the file with
O_SYNC
and call syswrite(). Imagine that the program gets into a whinge-loop an
spews messages at the rate of 100's per second which isn't unknown. A basic
step like this can make a noticeable difference.

Cheers

Tim
 
Reply With Quote
 
Peter J. Holzer
Guest
Posts: n/a
 
      07-07-2007
On 2007-07-04 11:23, Tim Southerwood <(E-Mail Removed)> wrote:
>
> Opening and closing the file on every call to Log() is expensive. One
> usually opens it once and then keeps the file handle around.


Yup.


> In this case, it might be considered "good manners" to have the program
> respond to SIGHUP to close and reopen the log file for the benefit of
> logrotation, though logrotate can work around this if necessary.


Another way is to switch log files automatically from the logging
routine. A handy way to do this is to include a timestamp (e.g. the
current day) in the log file name and for every entry (or at other
convenient moments such as when a new client connects) check if the log
file name has changed:


{
my $log_filename_template = "/var/log/whatever/%Y-%m-%d";
my $log_filename = '';
my $log_fh;

sub log {
my ($msg) = @_;
my @lt = localtime();
my $ts = strftime("%Y-%m-%dT%H:%M:%S%z", @lt);
my $fn = strftime($log_filename_template, @lt);
if ($fn ne $log_filename) {
if ($log_fh) {
close($log_fh) or die "error closing $log_filename: $!";
}
$log_filename = $fn;
open($log_fh, ">>", $log_filename) or die "error opening $log_filename: $!";
$log_fh->autoflush(1);
}
$log_fh->print("$ts $msg\n") or die "error writing $log_filename: $!";
}
}

You still need a cronjob to compress and/or delete old logfiles.

hp


--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | http://www.velocityreviews.com/forums/(E-Mail Removed) |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
 
Reply With Quote
 
Peter J. Holzer
Guest
Posts: n/a
 
      07-07-2007
On 2007-07-04 11:26, Jrgen Exner <(E-Mail Removed)> wrote:
> Tim Southerwood wrote:
>> Opening and closing the file on every call to Log() is expensive.

>
> True.
>
>> One usually opens it once and then keeps the file handle around.

>
> Depends. If you want to capture the last breath of your program before it
> dies an untimely death then you don't want to risk loosing its last words in
> an unsaved buffer.


You should generally turn autoflush on on log files. Apart from the
reason you just mentioned there are two others:

1) If your program only prints log entries only infrequently, it may
take a long time until the (typically 4kB or 8kB) buffer fills up.
Normally you want every log message in the log immediately, not a
bunch of messages every few hours.

2) Buffers usually have a fixed size, so the blocks written to the log
file will not start and end at line boundaries. If you have several
processes writing to the same log file lines will be mixed. If you
flush after every line that can't happen (at least on Unix, the
kernel makes sure that a single write on a file in append mode is
written atomically). For the same reason you should write the whole
message with a single print call.

hp


--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | (E-Mail Removed) |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Write to error log using redirect:write Petterson Mikael XML 1 09-11-2006 12:06 PM
ASP Problem: "IIS log failed to write entry" in Event Log cherryparadise001@gmail.com ASP General 0 05-26-2006 01:52 AM
write a function such that when ever i call this function in some other function .it should give me tha data type and value of calling function parameter komal C++ 6 01-25-2005 11:13 AM
Using write function within email Module to write get_payload to afile. Chuck Amadi Python 0 06-22-2004 12:13 PM
SecurityException when trying to write to event log. Suhail Salman ASP .Net 2 11-22-2003 03:27 AM



Advertisments