From 301bfbd27161e3b8cd632334c0f7af65ace58bcc Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Wed, 5 Apr 2017 23:01:39 +0100 Subject: [PATCH] Expose libvips warnings via NODE_DEBUG env var --- docs/changelog.md | 10 ++++++++++ lib/constructor.js | 5 +++++ package.json | 1 + src/common.cc | 29 +++++++++++++++++++++++++++++ src/common.h | 10 ++++++++++ src/metadata.cc | 21 +++++++++++++++++---- src/pipeline.cc | 21 +++++++++++++++++---- src/sharp.cc | 3 +++ 8 files changed, 92 insertions(+), 8 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 07140798..c35218b9 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,15 @@ # Changelog +### v0.18 - "*ridge*" + +Requires libvips v8.5.2. + +#### v0.18.0 - TBD + +* Expose warnings from libvips via NODE_DEBUG=sharp environment variable. + [#607](https://github.com/lovell/sharp/issues/607) + [@puzrin](https://github.com/puzrin) + ### v0.17 - "*quill*" Requires libvips v8.4.2. diff --git a/lib/constructor.js b/lib/constructor.js index af289602..e942001a 100644 --- a/lib/constructor.js +++ b/lib/constructor.js @@ -24,6 +24,9 @@ let versions = { } catch (err) {} })(); +// Use NODE_DEBUG=sharp to enable libvips warnings +const debuglog = util.debuglog('sharp'); + /** * @class Sharp * @@ -174,6 +177,8 @@ const Sharp = function (input, options) { tiffSquash: false, tileSize: 256, tileOverlap: 0, + // Function to notify of libvips warnings + debuglog: debuglog, // Function to notify of queue length changes queueListener: function (queueLength) { queue.emit('change', queueLength); diff --git a/package.json b/package.json index cc3f92bc..df5560bc 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "cc": { "linelength": "120", "filter": [ + "build/c++11", "build/include", "runtime/indentation_namespace" ] diff --git a/src/common.cc b/src/common.cc index 57e1d6b7..70d4ba8d 100644 --- a/src/common.cc +++ b/src/common.cc @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -354,6 +356,33 @@ namespace sharp { } } + /* + Temporary buffer of warnings + */ + std::queue vipsWarnings; + std::mutex vipsWarningsMutex; + + /* + Called with warnings from the glib-registered "VIPS" domain + */ + void VipsWarningCallback(char const* log_domain, GLogLevelFlags log_level, char const* message, void* ignore) { + std::lock_guard lock(vipsWarningsMutex); + vipsWarnings.emplace(message); + } + + /* + Pop the oldest warning message from the queue + */ + std::string VipsWarningPop() { + std::string warning; + std::lock_guard lock(vipsWarningsMutex); + if (!vipsWarnings.empty()) { + warning = vipsWarnings.front(); + vipsWarnings.pop(); + } + return warning; + } + /* Calculate the (left, top) coordinates of the output image within the input image, applying the given gravity. diff --git a/src/common.h b/src/common.h index 20790c5f..a6cf922a 100644 --- a/src/common.h +++ b/src/common.h @@ -189,6 +189,16 @@ namespace sharp { */ void FreeCallback(char* data, void* hint); + /* + Called with warnings from the glib-registered "VIPS" domain + */ + void VipsWarningCallback(char const* log_domain, GLogLevelFlags log_level, char const* message, void* ignore); + + /* + Pop the oldest warning message from the queue + */ + std::string VipsWarningPop(); + /* Calculate the (left, top) coordinates of the output image within the input image, applying the given gravity. diff --git a/src/metadata.cc b/src/metadata.cc index 32f8dc44..fb9e352e 100644 --- a/src/metadata.cc +++ b/src/metadata.cc @@ -25,9 +25,10 @@ class MetadataWorker : public Nan::AsyncWorker { public: MetadataWorker( - Nan::Callback *callback, MetadataBaton *baton, - std::vector> const buffersToPersist) - : Nan::AsyncWorker(callback), baton(baton), buffersToPersist(buffersToPersist) { + Nan::Callback *callback, MetadataBaton *baton, Nan::Callback *debuglog, + std::vector> const buffersToPersist) : + Nan::AsyncWorker(callback), baton(baton), debuglog(debuglog), + buffersToPersist(buffersToPersist) { // Protect Buffer objects from GC, keyed on index std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0, [this](uint32_t index, v8::Local const buffer) -> uint32_t { @@ -132,12 +133,21 @@ class MetadataWorker : public Nan::AsyncWorker { delete baton->input; delete baton; + // Handle warnings + std::string warning = sharp::VipsWarningPop(); + while (!warning.empty()) { + v8::Local message[1] = { New(warning).ToLocalChecked() }; + debuglog->Call(1, message); + warning = sharp::VipsWarningPop(); + } + // Return to JavaScript callback->Call(2, argv); } private: MetadataBaton* baton; + Nan::Callback *debuglog; std::vector> buffersToPersist; }; @@ -155,9 +165,12 @@ NAN_METHOD(metadata) { // Input baton->input = sharp::CreateInputDescriptor(sharp::AttrAs(options, "input"), buffersToPersist); + // Function to notify of libvips warnings + Nan::Callback *debuglog = new Nan::Callback(sharp::AttrAs(options, "debuglog")); + // Join queue for worker thread Nan::Callback *callback = new Nan::Callback(info[1].As()); - Nan::AsyncQueueWorker(new MetadataWorker(callback, baton, buffersToPersist)); + Nan::AsyncQueueWorker(new MetadataWorker(callback, baton, debuglog, buffersToPersist)); // Increment queued task counter g_atomic_int_inc(&sharp::counterQueue); diff --git a/src/pipeline.cc b/src/pipeline.cc index b7968a0e..fe16d537 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -33,9 +33,10 @@ class PipelineWorker : public Nan::AsyncWorker { public: PipelineWorker( - Nan::Callback *callback, PipelineBaton *baton, Nan::Callback *queueListener, - std::vector> const buffersToPersist) - : Nan::AsyncWorker(callback), baton(baton), queueListener(queueListener), buffersToPersist(buffersToPersist) { + Nan::Callback *callback, PipelineBaton *baton, Nan::Callback *debuglog, Nan::Callback *queueListener, + std::vector> const buffersToPersist) : + Nan::AsyncWorker(callback), baton(baton), debuglog(debuglog), queueListener(queueListener), + buffersToPersist(buffersToPersist) { // Protect Buffer objects from GC, keyed on index std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0, [this](uint32_t index, v8::Local const buffer) -> uint32_t { @@ -979,6 +980,14 @@ class PipelineWorker : public Nan::AsyncWorker { }); delete baton; + // Handle warnings + std::string warning = sharp::VipsWarningPop(); + while (!warning.empty()) { + v8::Local message[1] = { New(warning).ToLocalChecked() }; + debuglog->Call(1, message); + warning = sharp::VipsWarningPop(); + } + // Decrement processing task counter g_atomic_int_dec_and_test(&sharp::counterProcess); v8::Local queueLength[1] = { New(sharp::counterQueue) }; @@ -991,6 +1000,7 @@ class PipelineWorker : public Nan::AsyncWorker { private: PipelineBaton *baton; + Nan::Callback *debuglog; Nan::Callback *queueListener; std::vector> buffersToPersist; @@ -1239,12 +1249,15 @@ NAN_METHOD(pipeline) { baton->accessMethod = VIPS_ACCESS_RANDOM; } + // Function to notify of libvips warnings + Nan::Callback *debuglog = new Nan::Callback(AttrAs(options, "debuglog")); + // Function to notify of queue length changes Nan::Callback *queueListener = new Nan::Callback(AttrAs(options, "queueListener")); // Join queue for worker thread Nan::Callback *callback = new Nan::Callback(info[1].As()); - Nan::AsyncQueueWorker(new PipelineWorker(callback, baton, queueListener, buffersToPersist)); + Nan::AsyncQueueWorker(new PipelineWorker(callback, baton, debuglog, queueListener, buffersToPersist)); // Increment queued task counter g_atomic_int_inc(&sharp::counterQueue); diff --git a/src/sharp.cc b/src/sharp.cc index 64187c51..c9b0dd18 100644 --- a/src/sharp.cc +++ b/src/sharp.cc @@ -24,6 +24,9 @@ NAN_MODULE_INIT(init) { vips_init("sharp"); + g_log_set_handler("VIPS", static_cast(G_LOG_LEVEL_WARNING), + static_cast(sharp::VipsWarningCallback), nullptr); + // Methods available to JavaScript Nan::Set(target, Nan::New("metadata").ToLocalChecked(), Nan::GetFunction(Nan::New(metadata)).ToLocalChecked());