- Imager no longer inherits from Exporter (unless you're running an
old, old perl.
+Bug fixes:
+
+ - re-work, document and test Imager's logging facility.
+ https://rt.cpan.org/Ticket/Display.html?id=65227
+
Imager 0.83 - 21 May 2011
===========
}
sub init_log {
- i_init_log($_[0],$_[1]);
- i_log_entry("Imager $VERSION starting\n", 1);
+ Imager->open_log(log => $_[0], level => $_[1]);
}
sub init {
my %parms=(loglevel=>1,@_);
if ($parms{'log'}) {
- init_log($parms{'log'},$parms{'loglevel'});
+ Imager->open_log(log => $parms{log}, level => $parms{loglevel});
}
if (exists $parms{'warn_obsolete'}) {
}
}
+{
+ my $is_logging = 0;
+
+ sub open_log {
+ my $class = shift;
+ my (%opts) = ( loglevel => 1, @_ );
+
+ $is_logging = i_init_log($opts{log}, $opts{loglevel});
+ unless ($is_logging) {
+ Imager->_set_error(Imager->_error_as_msg());
+ return;
+ }
+
+ Imager->log("Imager $VERSION starting\n", 1);
+
+ return $is_logging;
+ }
+
+ sub close_log {
+ i_init_log(undef, -1);
+ $is_logging = 0;
+ }
+
+ sub log {
+ my ($class, $message, $level) = @_;
+
+ defined $level or $level = 1;
+
+ i_log_entry($message, $level);
+ }
+
+ sub is_logging {
+ return $is_logging;
+ }
+}
+
END {
if ($DEBUG) {
print "shutdown code\n";
circle() - L<Imager::Draw/circle()> - draw a filled circle
+close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
+debugging log.
+
colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
colors in an image's palette (paletted images only)
image write functions should write the image in their bilevel (blank
and white, no gray levels) format
+is_logging() L<Imager::ImageTypes/is_logging()> - test if the debug
+log is active.
+
line() - L<Imager::Draw/line()> - draw an interval
load_plugin() - L<Imager::Filters/load_plugin()>
+log() - L<Imager::ImageTypes/log()> - send a message to the debugging
+log.
+
map() - L<Imager::Transformations/"Color Mappings"> - remap color
channel values
open() - L<Imager::Files> - an alias for read()
+open_log() - L<Imager::ImageTypes/open_log()> - open the debug log.
+
=for stopwords IPTC
parseiptc() - L<Imager::Files/parseiptc()> - parse IPTC data from a JPEG
#define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
#define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
+#ifdef IMAGER_LOG
+#define i_log_enabled() 1
+#else
+#define i_log_enabled() 0
+#endif
+
#if i_int_hlines_testing()
typedef i_int_hlines *Imager__Internal__Hlines;
int y
int channels
-void
+int
i_init_log(name_sv,level)
SV* name_sv
int level
PREINIT:
const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
CODE:
- i_init_log(name, level);
+ RETVAL = i_init_log(name, level);
+ OUTPUT:
+ RETVAL
void
i_log_entry(string,level)
char* string
int level
+int
+i_log_enabled()
void
i_img_exorcise(im)
=item *
-C<log> - name of a log file to log Imager's actions to. Not all actions
-are logged, but the debugging memory allocator does log allocations
-here. Ignored if Imager has been built without logging support.
+C<log> - name of a log file to log Imager's actions to. Not all
+actions are logged, but the debugging memory allocator does log
+allocations here. Ignored if Imager has been built without logging
+support. Preferably use the open_log() method instead.
=item *
=back
+=head1 LOGGING METHODS
+
+Imager can open an internal log to send debugging information to.
+This log is extensively used in Imager's tests, but you're unlikely to
+use it otherwise.
+
+If Imager has been built with logging disabled, the methods fail
+quietly.
+
+=over
+
+=item open_log()
+
+Open the Imager debugging log file.
+
+=over
+
+=item *
+
+C<log> - the file name to log to. If this is undef logging information
+is sent to the standard error stream.
+
+=item *
+
+C<loglevel> the level of logging to produce. Default: 1.
+
+=back
+
+Returns a true value if the log file was opened successfully.
+
+ # send debug output to test.log
+ Imager->open_log(log => "test.log");
+
+ # send debug output to stderr
+ Imager->open_log();
+
+=item close_log()
+
+Close the Imager debugging log file and disable debug logging.
+
+No parameters.
+
+ Imager->close_log();
+
+=item log()
+
+ Imager->log($message)
+ Imager->log($message, $level)
+
+This method does not use named parameters.
+
+The default for C<$level> is 1.
+
+Send a message to the debug log.
+
+ Imager->log("My code got here!");
+
+=item is_logging()
+
+Returns a true value if logging is enabled.
+
+=back
+
=head1 REVISION
$Revision$
#include "imconfig.h"
#include "log.h"
#include <stdlib.h>
+#include <errno.h>
+
+#ifdef IMAGER_LOG
#define DTBUFF 50
#define DATABUFF DTBUFF+3+10+1+5+1+1
static char data_buffer[DATABUFF];
-#ifdef IMAGER_LOG
-
/*
* Logging is active
*/
-void
+int
i_init_log(const char* name,int level) {
+ i_clear_error();
log_level = level;
if (level < 0) {
lg_file = NULL;
lg_file = stderr;
} else {
if (NULL == (lg_file = fopen(name, "w+")) ) {
- fprintf(stderr,"Cannot open file '%s'\n",name);
- exit(2);
+ i_push_errorf(errno, "Cannot open file '%s': (%d)", name, errno);
+ return 0;
}
}
}
- setvbuf(lg_file, NULL, _IONBF, BUFSIZ);
- mm_log((0,"Imager - log started (level = %d)\n", level));
+ if (lg_file) {
+ setvbuf(lg_file, NULL, _IONBF, BUFSIZ);
+ mm_log((0,"Imager - log started (level = %d)\n", level));
+ }
+
+ return lg_file != NULL;
}
void
exit(exitcode);
}
-#else
-
-/*
- * Logging is inactive - insert dummy functions
- */
-
-void i_init_log(const char* name,int onoff) {}
-void i_fatal(int exitcode,const char *fmt, ... ) { exit(exitcode); }
-
-
-#endif
/*
=item i_loog(level, format, ...)
sprintf(data_buffer, "[%s] %10s:%-5d ", date_buffer, file, line);
}
}
+
+#else
+
+/*
+ * Logging is inactive - insert dummy functions
+ */
+
+int i_init_log(const char* name,int onoff) {
+ i_clear_error();
+ i_push_error(0, "Logging disabled");
+ return 0;
+}
+
+void i_fatal(int exitcode,const char *fmt, ... ) { exit(exitcode); }
+
+void
+i_loog(int level,const char *fmt, ... ) {
+}
+
+void
+i_lhead(const char *file, int line) { }
+
+#endif
global: creates a global variable FILE* lg_file
*/
+int i_init_log( const char *name, int onoff );
+void i_fatal ( int exitcode,const char *fmt, ... );
void i_lhead ( const char *file, int line );
-void i_init_log( const char *name, int onoff );
void i_loog(int level,const char *msg, ... );
-void i_fatal ( int exitcode,const char *fmt, ... );
/*
=item mm_log((level, format, ...))
-d "testout" or mkdir "testout";
-init_log("testout/t01introvert.log",1);
+Imager->open_log(log => "testout/t01introvert.log");
my $im_g = Imager::ImgRaw::new(100, 101, 1);
image_bounds_checks($im);
}
+Imager->close_log();
+
+unless ($ENV{IMAGER_KEEP_FILES}) {
+ unlink "testout/t01introvert.log";
+}
+
sub check_add {
my ($im, $color, $expected) = @_;
my $index = Imager::i_addcolors($im, $color);
'^DSO_',
'^Inline$',
'^yatf$',
- '^m_init_log$',
'^malloc_state$',
'^init_log$',
'^polybezier$', # not ready for public consumption
--- /dev/null
+#!perl -w
+use strict;
+use Imager;
+use Test::More tests => 6;
+
+my $log_name = "testout/t95log.log";
+
+my $log_message = "test message 12345";
+
+SKIP: {
+ skip("Logging not build", 3)
+ unless Imager::i_log_enabled();
+ ok(Imager->open_log(log => $log_name), "open log")
+ or diag("Open log: " . Imager->errstr);
+ ok(-f $log_name, "file is there");
+ Imager->log($log_message);
+ Imager->close_log();
+
+ my $data = '';
+ if (open LOG, "< $log_name") {
+ $data = do { local $/; <LOG> };
+ close LOG;
+ }
+ like($data, qr/\Q$log_message/, "check message made it to the log");
+}
+
+SKIP: {
+ skip("Logging built", 3)
+ if Imager::i_log_enabled();
+
+ ok(!Imager->open_log(log => $log_name), "should be no logfile");
+ is(Imager->errstr, "Logging disabled", "check error message");
+ ok(!-f $log_name, "file shouldn't be there");
+}