Statistics Extraction

D

doni

Hi,

I wanted to extract specific information of MAC and PHY statistics from
the statistics log file. The Statistics file contains information other
than MAC and PHY also.
I am mainly concerned about "frames with invalid header" and "packets
with invalid length" from the MAC Statistics and "transmit errors" from
PHY Statistics.
Can anyone let me know how can I extract this information.

Here is a snapshot of the Statistics file that gets generated.

MAC statistics:
0 frames with invalid header
546 confirmed frames sent succesfully
1693 confirmed frames sent unsuccesfully
542 confirmed frames received
4597 total frames received
851 data packets received
549 packets sent successfully
152 packets sent unsuccessfully
763 packets queued by network layer
61 packet transmissions timed out
0 packets with invalid length
0 out of order fragments received
87 duplicate fragments received
0 partial packets received
4 packet reassemblies timed out
0 no buffers
PHY statistics:
3404 frames transmitted
105 transmits aborted due to rx
0 transmit errors
0 late transmits
11 tx buffer loads interrupted
0 tx buffer load failures
4598 receive interrupts
4598 frames received
0 received frames lost
0 zero length frames received
0 receive cmd errors
Network statistics:
851 total packets received
0 bad packet length
0 bad version number
0 outgoing packets with no route
0 input packets with bad destination address
0 input packets from wrong channel
0 packets dropped for exceeding TTL
0 packets dropped due to full socket buffers
0 packets dropped due to no receiver
0 packets dropped due to running out of memory
762 total packets sent
549 packets succesfully transmitted
213 packets sent unsuccessfully


Thanks,
doni
 
D

doni

Michele said:
What have you tried thus far? In any case you may try some regexen
like

/(\d+)\s+frames with invalid header/

I was trying to do something other than regexp so that If I need
multiple searches, I can easily incorporate them.
I didnt have much success till now...

#! /usr/bin/perl

use strict;
use warnings;

my $ex_data = 'netstat.log';
open (NETSTAT,$ex_data) || die("Cannot Open File: $!");

### Prompt the User for Input ###
print "Enter the stats(MAC or PHY) information that need to be
extracted:";
my $input = <STDIN>;
chomp($input);
print $input;

foreach $line(<NETSTAT>) {
chomp $line;
if ($input =~ m/^$line/i) {
print "We are going to extract RF MAC Statistics\n";
}
}
close(NETSTAT) || die("Cannot close $ex_data: $!");
 
D

DJ Stunks

doni said:
I was trying to do something other than regexp so that If I need
multiple searches, I can easily incorporate them.
I didnt have much success till now...

#!/usr/bin/perl

use strict;
use warnings;

my (%statistics, $type);
while ( my $line = <DATA> ) {
if ( $line =~ m{^ (\S+) }x ) {
$type = $1;
}
elsif ( $line =~ m{ (\d+) \s+ (.+?) \s* $}mx ) {
$statistics{ $type }{ $2 } = $1;
}
}

print "MAC stats for 'frames with invalid header': ",
$statistics{ MAC }{ 'frames with invalid header' },
"\n";


__DATA__
MAC statistics:
0 frames with invalid header
546 confirmed frames sent succesfully
1693 confirmed frames sent unsuccesfully
542 confirmed frames received
4597 total frames received
851 data packets received
549 packets sent successfully
152 packets sent unsuccessfully
763 packets queued by network layer
61 packet transmissions timed out
0 packets with invalid length
0 out of order fragments received
87 duplicate fragments received
0 partial packets received
4 packet reassemblies timed out
0 no buffers
PHY statistics:
3404 frames transmitted
105 transmits aborted due to rx
0 transmit errors
0 late transmits
11 tx buffer loads interrupted
0 tx buffer load failures
4598 receive interrupts
4598 frames received
0 received frames lost
0 zero length frames received
0 receive cmd errors
Network statistics:
851 total packets received
0 bad packet length
0 bad version number
0 outgoing packets with no route
0 input packets with bad destination address
0 input packets from wrong channel
0 packets dropped for exceeding TTL
0 packets dropped due to full socket buffers
0 packets dropped due to no receiver
0 packets dropped due to running out of memory
762 total packets sent
549 packets succesfully transmitted
213 packets sent unsuccessfully

-jp
 
D

doni

use strict;
use warnings;

my (%statistics, $type);
while ( my $line = <DATA> ) {
if ( $line =~ m{^ (\S+) }x ) {
$type = $1;
}
elsif ( $line =~ m{ (\d+) \s+ (.+?) \s* $}mx ) {
$statistics{ $type }{ $2 } = $1;
}
}

print "MAC stats for 'frames with invalid header': ",
$statistics{ MAC }{ 'frames with invalid header' },
"\n";

I tried the above method but I didnt get any result for "frames with
invalid header"..

Sekar
 
D

DJ Stunks

I tried the above method but I didnt get any result for "frames with
invalid header"..

I only post working code. You need to get rid of any indentation in
the DATA section for the regexs to work.

-jp
 
J

Josef Moellers

doni said:
Michele Dondi wrote:




I was trying to do something other than regexp so that If I need
multiple searches, I can easily incorporate them.

Waht you could try is to build a HoH from your input data and then
satisfy your query from the HoH:

<untested>
my %netstat; # Will be the HOH
my $stats; # some kind of state variable
while (<$netstat>) {
chomp;
if (/^(\S+)\s+statistics:/) {
$stats = $_;
$netstat{$stats} = { };
} elif (/^\s+(\d+)\s+(\S.*)/) {
next unless defined $stats;
$netstat{§stats}->{$2} = $1;
}
}
</untested>

Then you'd find PHY's "tx buffer loads interrupted" in
$netstat{PHY}->{"tx buffer loads interrupted"}.

Still involves regexen, though.
 
D

DJ Stunks

satisfy your query from the HoH:

For some reason I really, really like this approach to this problem!
Sheer genius, IMO :p
<untested>
my %netstat; # Will be the HOH
my $stats; # some kind of state variable
while (<$netstat>) {
chomp;
if (/^(\S+)\s+statistics:/) {
$stats = $_;

ITYM

$stats = $1;
$netstat{$stats} = { };

no need for this step; let autoviv take care of it for you.
} elif (/^\s+(\d+)\s+(\S.*)/) {
next unless defined $stats;

not a bad idea, I didn't have this test in my version of this script.
$netstat{§stats}->{$2} = $1;

a new Perl6 sigil? just kidding. no need for the arrow for the
embedded hash. Perl knows what you mean

$netstat{ $stats }{ $2 } = $1
}}</untested>

Then you'd find PHY's "tx buffer loads interrupted" in
$netstat{PHY}->{"tx buffer loads interrupted"}.

same as before, no arrow required. see perldoc perlref.

-jp
 
J

Josef Moellers

DJ said:
For some reason I really, really like this approach to this problem!
Sheer genius, IMO :p

Thank you, I feel honoured.
ITYM

$stats = $1;

Yes, of course.
no need for this step; let autoviv take care of it for you.




not a bad idea, I didn't have this test in my version of this script.

Most likely, it will never be used, but ... better safe than sorry.
a new Perl6 sigil? just kidding.

No, it's just to show that it's coded according to the law of least
surprise ;-)

no need for the arrow for the
embedded hash. Perl knows what you mean

$netstat{ $stats }{ $2 } = $1




same as before, no arrow required. see perldoc perlref.

Learnt something new today,

Josef
 
D

doni

thanks, for your reply....
Can I understand why we do "next unless defined $stats;" and why it
will never be used.

Can you let me know how can I find out the values in the HoH.

Thanks,
doni
 
J

J. Gleixner

doni said:
On Jan 24, 7:21 am, Josef Moellers


Can you let me know how can I find out the values in the HoH.

By using the hash's keys, of course.

Do some research and try to find the answer. There is a very
good document on many useful data structures that comes with
perl.

perldoc perldsc

Look for "HASH OF HASH".

You can also "use Data::Dumper", to see the structure and values.

perldoc Data::Dumper
 
J

Josef Moellers

doni said:
thanks, for your reply....
Can I understand why we do "next unless defined $stats;" and why it
will never be used.

I did that because the next line references $netstat{$stats}, which will
fail if no line of the form "... statistics:" (to be precise: a line
starting with one or more non-blank characters followed by one or more
blank characters followed by the word "statistics" followed by a colon,
let's call that the "interface header line") were seen before.
It will (most likeley) never be used, becase the structure of the input
data is such that before any lines with the statistics data (i.e. any
line that starts with one or more blanks followed by one or more digits
followed by one or more blanks followed by at least a non-blank followed
by an arbitrary amount of arbitrariy characters), an "interface header
line" is processed, so the first pattern will match once before the
second will.
Can you let me know how can I find out the values in the HoH.

Didn't I write that "you'd find PHY's "tx buffer loads interrupted" in
$netstat{PHY}->{"tx buffer loads interrupted"}.", whereupon DJ Stunks
replied that "no arrow required"?

It is a common understanding in this group that we don't write code for
you, but we're willing to comment on any code that you post. Our
comments may very well contain code e.g. when we want to suggest a
different approach, as I did in my reply.

So, play around with the code that was posted and come back if you have
(unworking) code. Post that code and we're glad to suggest modifications.
 
D

doni

It is a common understanding in this group that we don't write code for
you, but we're willing to comment on any code that you post. Our
comments may very well contain code e.g. when we want to suggest a
different approach, as I did in my reply.
So, play around with the code that was posted and come back if you have
(unworking) code. Post that code and we're glad to suggest modifications.
--

Joseph,

Can you take a look at the code below...


MAC, PHY and Network stats gets generated every 30 minutes and are
copied to a file.
I want to extract all the stats information that is copied to a file
into an hash of hashes and print them.
The file has multiple MAC, PHY and Network Statistics in it and I am
extracting the MAC data in a MAC hash of hashes, PHY data in a PHY hash
of hashes and Network data in a Network hash of hashes.
Here is how the data that is represented in a file. There will be
multiple MAC, PHY and Network Statistics in the file but I am showing
only one of them in here as an example.

For example, if there were 10 MAC Statistics in the file, this is how I
want the data from the "frames with invalid header" stats message to be
copied to a hash.
$mac{'frames with invalid header'}{1} = 0
$mac{'frames with invalid header'}{2} = 0
........ $mac{'frames with invalid header'}{10} = 0


Here is the program I wrote to do the above operation but its not
working as expected. Can anyone let me know where I went wrong.

Thanks,
doni

### Open the netstat file copied to this location ###
my $ex_data = 'netstat.log';
open (NETSTAT,$ex_data) || die("Cannot Open File: $!");

my %mac = (); # Will be the HOH for MAC Statistics
my %phy = (); # Will be the HoH for PHY Statistics
my %bbu = (); # Will be the HoH for BBU Statistics
my %dli = (); # Will be the HoH for DLI Statistics
my $stats; # State Variable
my $i = 0; # Count variable for MAC
my $j = 0; # Count Variable for PHY
my $a = 0; # Count Variable for Network
my $x = 0; # Count Varialbe for Hash

while (<NETSTAT>) {
chomp;
if (/^(\S+)\s+statistics:/) {
$stats = $1;
if ($stats =~ /mac/i)
{ $i++; }
elsif ($stats =~ /phy/i)
{ $j++; }
else
{ $a++; }
}

elsif (/^\s+(\d+)\s+(\S.*)/)
{
($value, $key) = ($1, $2);
if ($stats =~ /mac/i) {
next unless defined $stats;
$mac{$key}{$i} = $value;
}
if ($stats =~ /phy/i) {
next unless defined $stats;
$phy{$key}{$j} = $value;
}
if ($stats =~ /network/i) {
next unless defined $stats;
$network{$key}{$a} = $value;
}
}
else { }
}

foreach $key (keys (%mac)) {
foreach $x (keys %{$mac{$key} })
{
while ($x <= $i) {
print "Message Value is: $mac{$key}{$i}\n";
$i++;
}

}
}

close(NETSTAT) || die("Cannot close $ex_data: $!");
 
D

doni

}foreach $key (keys (%mac)) {
foreach $x (keys %{$mac{$key} })
{
while ($x <= $i) {
print "Message Value is: $mac{$key}{$i}\n";
$i++;

IT IS $x++ and not $i++. I changed that mistake in the
code but still it doesnt work...
 
E

Eric Schwartz

doni said:
For example, if there were 10 MAC Statistics in the file, this is how I
want the data from the "frames with invalid header" stats message to be
copied to a hash.
$mac{'frames with invalid header'}{1} = 0
$mac{'frames with invalid header'}{2} = 0
....... $mac{'frames with invalid header'}{10} = 0

It's not clear from this example what the second-level key is. Is it
the MAC address itself, or simply the index in which it occurred in
the file? If the former, then it makes sense to keep it as a hash,
but if the latter, why not:

$mac{'frames with invalid header'} = [ 1, 13, 28, ... 9 ];

That is, the hash points to an arrayref, where the value of the array
at any position is the number of frames for the MAC at that position.
In your example, it would be the equivalent of doing:

$mac{'frames with invalid header'}{1} = 1
$mac{'frames with invalid header'}{2} = 13
........ $mac{'frames with invalid header'}{10} = 9

Here is the program I wrote to do the above operation but its not
working as expected. Can anyone let me know where I went wrong.

It would help if you could include some data in the example, using the
__DATA__ keyword. And you could please let us know what it did, what
you expected, and how they differ-- almost nobody is interested in
figuring all that out for you.

But:

you start off missing:

#!/usr/bin/perl
use warnings;
use strict;
### Open the netstat file copied to this location ###
my $ex_data = 'netstat.log';
open (NETSTAT,$ex_data) || die("Cannot Open File: $!");

Excellent! In particular, congrats for putting the 'die' in there,
and for putting the $! variable in its argument. You might consider
using the more idiomatic 'or die ....', and the three-arg form of
open, but those are style issues, and not relevant to the program's
functionality:

open my $netstat, '<', $ex_data or die "Cannot open file: $!");
my %mac = (); # Will be the HOH for MAC Statistics
my %phy = (); # Will be the HoH for PHY Statistics
my %bbu = (); # Will be the HoH for BBU Statistics
my %dli = (); # Will be the HoH for DLI Statistics

Why not a single top-level hash %stats that you can treat like so:

$stats{mac}{'frames with invalid header'}[0];

or

$stats{phy}{'retransmitted frames'}[7];

? It is not a big deal, just a thought.
my $stats; # State Variable

This is a bit of a confusing variable name. Maybe you could name it
$stat_type or something a bit more clear?
my $i = 0; # Count variable for MAC
my $j = 0; # Count Variable for PHY
my $a = 0; # Count Variable for Network
my $x = 0; # Count Varialbe for Hash

When I see all those different one-letter count variables, it hurts my
brain. Especially when after I read your code, they're completely
unnecessary. Instead, I recomment you use an array, and simply append
to it.
while (<NETSTAT>) {
chomp;
if (/^(\S+)\s+statistics:/) {
$stats = $1;

You can delete everything from here:
if ($stats =~ /mac/i)
{ $i++; }
elsif ($stats =~ /phy/i)
{ $j++; }
else
{ $a++; }
}

To here. That section is confusingly indented, as is the rest of your
code, so you should look into some automatic indentation-fixer, or at
least try to manually line things up according to a style. 'perldoc
perlstyle' is helpful here, but it's only one option among many-- all
that really matters is that you're consistent in your indentation
style, not so much which one you pick.
elsif (/^\s+(\d+)\s+(\S.*)/)
{
($value, $key) = ($1, $2);
if ($stats =~ /mac/i) {
next unless defined $stats;
$mac{$key}{$i} = $value;

You can replace this line (and the one above, which increments $i) with:

push @{$mac{$key}}, $value;

Or, if you collect all your stats into one top-level hash:

push @{$stats{mac}{$key}}, @value;
}
if ($stats =~ /phy/i) {
next unless defined $stats;
$phy{$key}{$j} = $value;

Likewise,

push @{$phy{$key}}, $value;
}
if ($stats =~ /network/i) {
next unless defined $stats;
$network{$key}{$a} = $value;

and
push @{$network{$key}}, $value;
}
}
else { }
}

foreach $key (keys (%mac)) {
foreach $x (keys %{$mac{$key} })

This is bad, because you don't know the order that you'll get from
'keys' here. At the very least you need 'sort keys'. Also, you have
an extra set of parentheses around %mac at the first 'foreach'.

Or, if you use my suggestion above, which I recommend:

foreach my $type, (keys %stats) {
print "$type stats:\n";

foreach my $message (keys %{$stats{$type}}) {
print "\tmessage is: $message\n";
for my $val (@{$mac{$stat_type}}) {
print "\t\tMessage value is: $val\n";
}
}
}
{
while ($x <= $i) {
print "Message Value is: $mac{$key}{$i}\n";
$i++;
}

}
}
close(NETSTAT) || die("Cannot close $ex_data: $!");

This 'close' should go at the end of the loop which reads from the
filehandle-- just before the 'foreach' which prints them out in your
example.

Let me please say again that the message in which you gave an example
of your data is 8 messages before this one, and I just happened to get
lucky that it was still on my newsserver. If you want the most help
possible, you really need to post, with your example code, an example
of the data you're working on, what you get when you run your code on
it, and what you expected, and how they are different.

-=Eric
 
J

Josef Moellers

doni said:
Joseph,

Can you take a look at the code below...


MAC, PHY and Network stats gets generated every 30 minutes and are
copied to a file.
I want to extract all the stats information that is copied to a file
into an hash of hashes and print them.
The file has multiple MAC, PHY and Network Statistics in it and I am
extracting the MAC data in a MAC hash of hashes, PHY data in a PHY hash
of hashes and Network data in a Network hash of hashes.
Here is how the data that is represented in a file. There will be
multiple MAC, PHY and Network Statistics in the file but I am showing
only one of them in here as an example.

For example, if there were 10 MAC Statistics in the file, this is how I
want the data from the "frames with invalid header" stats message to be
copied to a hash.
$mac{'frames with invalid header'}{1} = 0
$mac{'frames with invalid header'}{2} = 0
....... $mac{'frames with invalid header'}{10} = 0


Here is the program I wrote to do the above operation but its not
working as expected. Can anyone let me know where I went wrong.

It's a very bad description: "its not working as expected".
Maybe you ask perl where you went wrong:

use warnings;
use strict;

When I defined those variables that you didn't ($key, %network, $value),
I got:

Message Value is: 4
Message Value is: 61
Message Value is: 87
Message Value is: 4597
Message Value is: 1693
Message Value is: 0
Message Value is: 0
Message Value is: 542
Message Value is: 0
Message Value is: 851
Message Value is: 152
Message Value is: 546
Message Value is: 0
Message Value is: 763
Message Value is: 0
Message Value is: 549

What did you expect?

There are several other issues in your program (lexical filehandles,
unnecessary initializations), but rather than rewrite it as _I_ would
have written it (which may not be your style), again:

1. ask perl for help ("use ...")
2. specify exactly what you expect and what you get.

Josef
 
D

doni

Can anyone let me know where I went wrong.It would help if you could include some data in the example, using the
__DATA__ keyword. And you could please let us know what it did, what
you expected, and how they differ-- almost nobody is interested in figuring all that out for you.

Here is the data that I was using. I have attached 1 copy of MAC, PHY
and NETWORK Stats in here but in the file there will be atleast 10
copies of MAC, PHY and NETWORK Stats.

__DATA__

MAC statistics:
0 frames with invalid header
546 confirmed frames sent succesfully
1693 confirmed frames sent unsuccesfully
542 confirmed frames received
4597 total frames received
851 data packets received
549 packets sent successfully
152 packets sent unsuccessfully
763 packets queued by network layer
61 packet transmissions timed out
0 packets with invalid length
0 out of order fragments received
87 duplicate fragments received
0 partial packets received
4 packet reassemblies timed out
0 no buffers
PHY statistics:
3404 frames transmitted
105 transmits aborted due to rx
0 transmit errors
0 late transmits
11 tx buffer loads interrupted
0 tx buffer load failures
4598 receive interrupts
4598 frames received
0 received frames lost
0 zero length frames received
0 receive cmd errors
Network statistics:
851 total packets received
0 bad packet length
0 bad version number
0 outgoing packets with no route
0 input packets with bad destination address
0 input packets from wrong channel
0 packets dropped for exceeding TTL
0 packets dropped due to full socket buffers
0 packets dropped due to no receiver
0 packets dropped due to running out of memory
762 total packets sent
549 packets succesfully transmitted
213 packets sent unsuccessfully
Let me please say again that the message in which you gave an example
of your data is 8 messages before this one, and I just happened to get
lucky that it was still on my newsserver. If you want the most help
possible, you really need to post, with your example code, an example
of the data you're working on, what you get when you run your code on
it, and what you expected, and how they are different.

I modified the code as per your suggestions but I am not sure whether I
modified it perfectly...

#! /usr/bin/perl

use warnings;
use strict;

my $ex_data = 'net.log';
open (NETSTAT,$ex_data) || die("Cannot Open File: $!");

my %stats = ();
my $message;

while (<NETSTAT>) {
chomp;
if (/^(\S+)\s+statistics:/)
{
$message = $1;
}
elsif (/^\s+(\d+)\s+(\S.*)/)
{
($value, $key) = ($1, $2);
if ($message =~ /mac/i) {
push @{$stats{mac}{$key}}, @value;
}
if ($message =~ /phy/i) {
push @{$stats{phy}{$key}}, @value;
}
if ($message =~ /network/i) {
push @{$stats{dli}{$key}}, @value;
}
}
else
{ }
}

close(NETSTAT) || die("Cannot close $ex_data: $!");

foreach my $type (keys %stats) {
print "$type stats:\n";

foreach my $messages (keys %{$stats{$type}}) {
print "\tmessages is: $messages\n";

foreach my $val (@{$type{$messages}}) {
print "\t\tMessage value is: $val\n";
}
}
}


The output I got when I ran the code is:

network stats:
messages is: packets dropped for exceeding TTL
messages is: packets dropped due to running out of memory
messages is: bad packet length
messages is: packets dropped due to full socket buffers
messages is: input packets from wrong channel
messages is: input packets with bad destination address
messages is: bad version number
messages is: total packets received
messages is: total packets sent
messages is: packets succesfully transmitted
messages is: packets dropped due to no receiver
messages is: packets sent unsuccessfully
messages is: outgoing packets with no route
phy stats:
messages is: tx buffer load failures
messages is: transmits aborted due to rx
messages is: receive interrupts
messages is: receive cmd errors
messages is: frames received
messages is: zero length frames received
messages is: received frames lost
messages is: late transmits
messages is: frames transmitted
messages is: transmit errors
messages is: tx buffer loads interrupted
mac stats:
messages is: packet transmissions timed out
messages is: confirmed frames sent succesfully
messages is: packet reassemblies timed out
messages is: confirmed frames sent unsuccesfully
messages is: duplicate fragments received
messages is: total frames received
messages is: packets sent successfully
messages is: frames with invalid header
messages is: data packets received
messages is: no buffers
messages is: packets sent unsuccessfully
messages is: packets with invalid length
messages is: packets queued by network layer
messages is: out of order fragments received
messages is: confirmed frames received
messages is: partial packets received


I would also like all the $val part to be printed for each $messages
but there was none when I ran the code. Is there anything wrong with
the code below...

foreach my $type (keys %stats) {
print "$type stats:\n";

foreach my $messages (keys %{$stats{$type}}) {
print "\tmessages is: $messages\n";

foreach my $val (@{$type{$messages}}) {
print "\t\tMessage value is: $val\n";
}
}
}


Thanks,
doni
 
C

Ch Lamprecht

doni said:
Here is the data that I was using. I have attached 1 copy of MAC, PHY
and NETWORK Stats in here but in the file there will be atleast 10
copies of MAC, PHY and NETWORK Stats.

__DATA__ goes to the end of your code (see e.g. perldoc perldata)
__DATA__
[DATA snipped]
I modified the code as per your suggestions but I am not sure whether I
modified it perfectly...

#! /usr/bin/perl

use warnings;
use strict;
The code you give does not run under use strict...
my $ex_data = 'net.log';
There is no need to open when using the DATA handle
open (NETSTAT,$ex_data) || die("Cannot Open File: $!");

[code snipped]
I would also like all the $val part to be printed for each $messages
but there was none when I ran the code. Is there anything wrong with
the code below...

foreach my $type (keys %stats) {
print "$type stats:\n";

foreach my $messages (keys %{$stats{$type}}) {
print "\tmessages is: $messages\n";

foreach my $val (@{$type{$messages}}) {
where does %type come from??? ^^^^^^
print "\t\tMessage value is: $val\n";
}
}
}

HTH, Christoph




use warnings;
use strict;

my %stats = ();
my $message;

while (<DATA>) {
chomp;
if (/^(\S+)\s+statistics:/)
{
$message = $1;
}
elsif (/^\s+(\d+)\s+(\S.*)/)
{
my ($value, $key) = ($1, $2);
if ($message =~ /mac/i) {
push @{$stats{mac}{$key}}, $value;
}
if ($message =~ /phy/i) {
push @{$stats{phy}{$key}}, $value;
}
if ($message =~ /network/i) {
push @{$stats{dli}{$key}}, $value;
}
}
else
{ }
}


foreach my $type (keys %stats) {
print "$type stats:\n";

foreach my $messages (keys %{$stats{$type}}) {
print "\tmessages is: $messages\n";

foreach my $val (@{$stats{$type}{$messages}}) {
print "\t\tMessage value is: $val\n";
}
}
}

__DATA__

MAC statistics:
0 frames with invalid header
546 confirmed frames sent succesfully
1693 confirmed frames sent unsuccesfully
542 confirmed frames received
4597 total frames received
851 data packets received
549 packets sent successfully
152 packets sent unsuccessfully
763 packets queued by network layer
61 packet transmissions timed out
0 packets with invalid length
0 out of order fragments received
87 duplicate fragments received
0 partial packets received
4 packet reassemblies timed out
0 no buffers
PHY statistics:
3404 frames transmitted
105 transmits aborted due to rx
0 transmit errors
0 late transmits
11 tx buffer loads interrupted
0 tx buffer load failures
4598 receive interrupts
4598 frames received
0 received frames lost
0 zero length frames received
0 receive cmd errors
Network statistics:
851 total packets received
0 bad packet length
0 bad version number
0 outgoing packets with no route
0 input packets with bad destination address
0 input packets from wrong channel
0 packets dropped for exceeding TTL
0 packets dropped due to full socket buffers
0 packets dropped due to no receiver
0 packets dropped due to running out of memory
762 total packets sent
549 packets succesfully transmitted
213 packets sent unsuccessfully
 
E

Eric Schwartz

doni said:
Here is the data that I was using. I have attached 1 copy of MAC, PHY
and NETWORK Stats in here but in the file there will be atleast 10
copies of MAC, PHY and NETWORK Stats.

That is helpful, but you really need to read 'perldoc perldata'. In
it, you will see that stuff following __DATA__ in a program is
available to read using the __DATA__ filehandle. That way, you don't
have to open an external file, or tell people "now, make sure you save
things in this file", which God knows they're probably going to typo
when they name it and so forth. It's simple and easy, if done right.
Read perldata, and look for the section on __DATA__.

I modified the code as per your suggestions but I am not sure whether I
modified it perfectly...

You came close, but missed a few obvious steps that indicate that you
never actually tried to run the code you posted. That's a bit rude,
as it means that you're basically asking me to do the work your
computer could do for you. I'm feeling a bit generous today, but
really, you shouldn't do that; others are not likely to feel so
generous, and I myself probably won't again.
#! /usr/bin/perl

use warnings;
use strict;
Good!

my $ex_data = 'net.log';
open (NETSTAT,$ex_data) || die("Cannot Open File: $!");

If you use __DATA__, these two lines aren't needed.
my %stats = ();
my $message;

while (<NETSTAT>) {
chomp;
if (/^(\S+)\s+statistics:/)
{
$message = $1;
}
elsif (/^\s+(\d+)\s+(\S.*)/)
{
($value, $key) = ($1, $2);

This line doesn't compile, because you're using strict (Which is good!
Do that!), but you didn't declare the variables $value and $key.
This, in turn, clearly shows that you can't have tried to run this
program, or Perl would have complained at you that these variables
haven't been declared. Bad doni! No biscuit!

my ($value, $key) = ($1, $2);
if ($message =~ /mac/i) {
push @{$stats{mac}{$key}}, @value;
}
if ($message =~ /phy/i) {
push @{$stats{phy}{$key}}, @value;
}
if ($message =~ /network/i) {
push @{$stats{dli}{$key}}, @value;
}

These statements also could not compile, because you meant to type
$value, not @value. ALWAYS CUT AND PASTE YOUR CODE!!! Do *not*
rewrite it for posting, or you make silly mistakes like this. That's
why we have Posting Guidelines, which are posted here twice a week,
that tell you things like, "Always cut and paste your code, do not
retype it." Please read them-- we didn't write them because we were
bored one day. There is useful info there.

If it is not crucial that the network stats be stored under the key
'dli', then you could just replace these three if statements with:

push @{$stats{lc($message)}{$key}}, $value;

That will create keys under $stats named 'mac', 'phy', and 'network',
and also produces code that's a lot easier to read. I actually had to
look over those if statements two or three times to figure out which
part was different-- at first, they all looked the same. If they all
look about the same, then you should cheat, and make them all the
same.
}
else
{ }
}

close(NETSTAT) || die("Cannot close $ex_data: $!");

If you used the DATA filehandle, this wouldn't be needed either.
foreach my $type (keys %stats) {
print "$type stats:\n";

foreach my $messages (keys %{$stats{$type}}) {
print "\tmessages is: $messages\n";

foreach my $val (@{$type{$messages}}) {

This may or may not be my fault, I'm too lazy to go back and check,
but again, this can't run. There is no hash %type here-- I think you
got $type{$messages} confused with $type. What you *really* want here
is
foreach my $val (@{$stats{$type}{$messages}}) {

Do you see why? If not, please read perlreftut until you do. It's
very important for making multilevel hashes that you understand how to
dereference them-- if all I've done is give you one fix for one
program, then I have done you a disservice, and I'm sorry.
print "\t\tMessage value is: $val\n";
}
}
}


The output I got when I ran the code is:

That's impossible. The code you posted will not run.

-=Eric
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,602
Members
45,184
Latest member
ZNOChrista

Latest Threads

Top