Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/grantstreetgroup/p5-dbg
A collection of perl debugging code that accelerates development, particularly of distributed, multi-process apps for which one cannot use the standard debugger.
https://github.com/grantstreetgroup/p5-dbg
Last synced: about 1 month ago
JSON representation
A collection of perl debugging code that accelerates development, particularly of distributed, multi-process apps for which one cannot use the standard debugger.
- Host: GitHub
- URL: https://github.com/grantstreetgroup/p5-dbg
- Owner: GrantStreetGroup
- License: other
- Created: 2020-01-10T20:14:15.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2020-01-24T19:49:52.000Z (almost 5 years ago)
- Last Synced: 2023-08-20T23:00:58.302Z (over 1 year ago)
- Language: Perl
- Size: 33.2 KB
- Stars: 1
- Watchers: 14
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# NAME
DBG - A collection of debugging functions
# VERSION
version v0.4.1
# SYNOPSIS
package Foo::Bar::Baz;
use DBG;...
dbg "log this $message";
...
png; # do I ever get here?
...
trc; # how did I get here?
...
dmp $obj; # what is this?
...
cyc $obj; # does this have reference cycles?
...
my $ts = ts; # get me the current time
...
rt $ts, ts; # how long did that take?
...
prp "is it so", $val; # prints message plus "yes" or "no"
...
pkg $obj, 'doit'; # prints package providing obj's doit method
...# DESCRIPTION
This is just a collection of functions useful for debugging. Instead of adding
use Data::Dumper;
use B::Deparse;
use Devel::Size qw(total_size);and so forth you can just type
use DBG;
at the top of the script. If you're using git, or another version control system
with similar functionality, you can write a simple pre-commit hook to prevent
yourself from committing debugging lines to the repository. Once you've deleted
the `use DBG;` line you can find all the other stuff you may have left in by
trying to compile the code and looking at the errors.All functions have short names to make debugging quick(er).
All debugging messages are printed both to the screen and to a log. The log will
be `~/DBG.log` unless otherwise specified. See `$ENV{DBG_LOG}`. This facilitates
examining debugging output at one's leisure without having to visually cull away
any other output produced by the program.All debugging functions are exported by default.
A timestamp will be printed before any debugging output to facilitate
distinguising one debugging session from another.# FUNCTIONS
## ts(;$) -- "get timestamp"
Returns a [DateTime](https://metacpan.org/pod/DateTime)-based timestamp. The optional argument is a label for the
timestamp. The label will be accessible via the timestamp's `text` method.my $t = ts 'foo';
say $t->text; # foo
say $t; # 2014-05-31T22:31:52## rt($$) -- "report timestamp"
Report time difference. This function expects two objects generated by the
`ts` function, the earlier first. It returns the second timestamp to facilitate
themy $ts = ts;
# some code
$ts = rt $ts, tspattern.
The report will vary according to whether the first timestamp holds a label.
my $t1 = ts 'foo';
my $t2 = rt $t1, ts 'bar';
sleep 1;
my $t3 = rt $t2, ts;
sleep 61;
rt $t3, ts;# timestamp foo
# negligible time elapsed
# timestamp bar
# 1 second
# 1 minute
# 1 second## trc() -- "trace"
Prints a stack trace, skipping its own frame. Each line of the trace is
formatted asframe number) code name (file:line)
This involves munging the frames as returned by `caller` so instead of saying
"you got here when called from here" it says simply "you are here". The next
line says how you got here. That is, the code name is the name of the code
you're in, not the code that just called you. I simply find this easier to
follow.sub foo { bar() }
sub bar { baz() }
sub baz { plugh() }
sub plugh { trc }
foo();# TRACE
# 1) main::plugh (test.pl:11)
# 2) main::baz (test.pl:10)
# 3) main::bar (test.pl:9)
# 4) main::foo (test.pl:8)
# END TRACE## dmp($) -- "dump"
Prints a pretty data dump. This uses a combination of [Perl::Tidy](https://metacpan.org/pod/Perl%3A%3ATidy) and
[Data::Dumper](https://metacpan.org/pod/Data%3A%3ADumper).my $r = { a => [qw(1 2 3)], c => { d => undef, egg => [ {}, {} ] } };
dmp $r;# {
# a => [ '1', '2', '3' ],
# c => {
# d => undef,
# egg => [ {}, {} ]
# }
# }## dbg($) -- "debug"
Prints a message to the debugging log.
dbg 'foo'; # foo
## png(;$) -- "ping"
Prints a ping message to the debugging log. If optional argument is true, just
prints "in code <code name> -- <optional arg>", where `code name` is the name
of the function or method minus the package. If the optional argument is just
"1", it is not suffixed to the ping message.sub foo { png }
sub bar { png 1 }
sub baz { png 'la la la la la' }
foo();
bar();
baz();# PING main::foo (test.pl:11)
# in code bar
# in code baz -- la la la la la## cyc($) -- "cycles"
Checks for cycles in a reference, teeing out the entire object graph.
This is like a condensed dump concerning itself only with references.my $a = {};
my $b = { b => $a };
my $c = { c => $b };
$a->{a} = $c;
cyc $a;# HASH (140416464744656 <- base)
# HASH (140416464745304 <- 140416464744656)
# HASH (140416464744992 <- 140416464745304)
# HASH (140416464744656 <- 140416464744992) -- ref count: 2## prp($$) -- "property"
Takes a message and a scalar to be evaluated as a boolean and submits this to
`dbg` as `"$message? yes/no"`.prp 'true', 1;
prp 'true', 0;# true? yes
# true? no## cnm($;$) -- "code name"
cnm $ua->can('request'); # LWP::UserAgent::request
Converts a code reference to the place in the source code it comes from. This
uses B::svref\_2object to do its magic. Sometimes it will provide the file and
line number, sometimes not.If the optional second parameter is provided, the information is only returned,
not teed out.## pkg($$;$) -- "package"
Determines the package providing a method to an object. The first parameter is
the object and the second the method name. Unless the optional third parameter
is true, the file and line are also provided.my $d = DateTime->now;
pkg $d, 'ymd';# package: DateTime; file: /Users/houghton/perl5/lib/perl5/darwin-thread-multi-2level/DateTime.pm; line: 820
pkg $d, 'ymd', 1;
# DateTime
## sz($;$) -- "size"
Tees out the size of a scalar. If two arguments are given, the first is taken
as a label and the second the scalar.sz {}; # 128
sz 'foo', {}; # foo 128This delegates to the `total_size` function in [Devel::Size](https://metacpan.org/pod/Devel%3A%3ASize). If you do not
have [Devel::Size](https://metacpan.org/pod/Devel%3A%3ASize), the `sz` will only emit a warning that it requires
[Devel::Size](https://metacpan.org/pod/Devel%3A%3ASize).## mtd($;$) -- "method"
Dumps out a sorted list of the object's method names, fully qualified. If the
optional parameter is provided, it also lists where the code for each method
can be found.my $d = DateTime->now;
mtd $d;# Class: DateTime
# [
# 'DateTime::DefaultLanguage',
# 'DateTime::DefaultLocale',
# 'DateTime::INFINITY',
# 'DateTime::MAX_NANOSECONDS',
# ... # many lines omitted
# ]mtd $d, 1;
# Class: DateTime
# UNIVERSAL::DOES
# DefaultLanguage : /Users/houghton/perl5/lib/perl5/darwin-thread-multi-2level/DateTime.pm 106
# DefaultLocale : /Users/houghton/perl5/lib/perl5/darwin-thread-multi-2level/DateTime.pm 106
# INFINITY : /Users/houghton/perl5/lib/perl5/constant.pm 30
# MAX_NANOSECONDS : /Users/houghton/perl5/lib/perl5/darwin-thread-multi-2level/Class/MOP/Mixin/HasMethods.pm 131
# ...## inh($) -- "inheritance"
Takes an object or class and prints out a sorted list of all the classes in
that object or class's inheritance tree.package Plugh;
package Foo;
our @ISA = qw(Plugh);
package Bar;
package Baz;
our @ISA = qw(Foo Bar);
package main;inh 'Baz';
# Classes in the inheritance hierarchy of Baz:
# Bar
# Baz
# Foo
# Plugh## dpr -- "deparse"
Takes a code reference and any optional parameters to pass to [B::Deparse](https://metacpan.org/pod/B%3A%3ADeparse).
Tees out the result of deparsing this reference.my $foo = sub { print "foo\n" };
...
dpr $foo; # what is this mystery code ref?# {
# use warnings;
# use strict 'refs';
# print "foo\n";
# }## flt($;$) -- "flatten"
Takes a parameter and flattens it. For an ordinary scalar this just
means it returns it. For containers -- hash or array references -- it returns
copies with flattened values. Anything blessed it stringifies.flt { bar => 1, baz => DateTime->now };
# {
# 'bar' => 1,
# 'baz' => '2014-05-31T21:04:07'
# };This is useful for dumping hashes containing huge objects whose innards you
don't need to see.If the optional second parameter is provided, the information is only returned,
not also dumped out via `dmp`.# VARIABLES
### $ENV{DBG\_LOG}
If the `DBG_LOG` environment variable is set and is not equal to 0, this will
be understood as the file into which debugging output should be dumped. If it
is set to 0, the debugging output will only be sent to STDERR. If it is
undefined, the log will be `~/DBG.log`.### $ENV{DBG\_ON}
If the `DBG_ON` environment variable is set, its boolean value will be used to
determine the value of `$DBG::ON`.### $ENV{DBG\_HEADER}
If the `DBG_HEADER` environment variable is set, its boolean value will be used to
determine the value of `$DBG::HEADER`.### $DBG::ON
If `$DBG::ON` is true, which it is by default, all debugging code is executed.
If it is false, debugging code is ignored (aside from the initial timestamp).
The state of `$ON` can be manipulated programmatically or set by the
`$ENV{DBG_ON}` environment variable. This can be used to constrain debugging
output to a particular section of a program. For instance, one may set debugging
to off and then locally set it to one within a particular method.sub foo {
local $DBG::ON = 1;
my self = shift;
...
}### $DBG::HEADER
Unless `$DBG::HEADER` is false, a timestamp and process ID will be logged for
a debugging process. The header is not printed until the first debugging line
is logged, so this need not be set in a BEGIN block.# PRE-COMMIT HOOK
You probably don't want debugging code, at least not that associated with
DBG, getting into your repository. Here's a sample git pre-commit hook script
for screening it out:my $rx = qr/
( (?&line){0,3} (?&dbg) (?&line){0,3} )
(?(DEFINE)
(? ^.*?(?:\R|\z) )
(? ^\+\s*use\s+DBG\b.*?(?:\R|\z) )
)
/mx;
my $text = `git diff --staged`;
if ( my @matches = $text =~ /$rx/g ) {
@matches = grep defined, @matches;
exit 0 unless @matches;
print STDERR "DBG lines: \n\n" . join "\n", @matches;
print STDERR "\nRun with --no-verify if you want to skip the DBG check.\n";
print STDERR "Aborting commit.\n";
exit 1;
}
exit 0;# AUTHOR
Grant Street Group
# COPYRIGHT AND LICENSE
This software is Copyright (c) 2014 - 2020 by Grant Street Group.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)