Expose libvips warnings via NODE_DEBUG env var

This commit is contained in:
Lovell Fuller 2017-04-05 23:01:39 +01:00
parent 46aec7eabc
commit 301bfbd271
8 changed files with 92 additions and 8 deletions

View File

@ -1,5 +1,15 @@
# Changelog # 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*" ### v0.17 - "*quill*"
Requires libvips v8.4.2. Requires libvips v8.4.2.

View File

@ -24,6 +24,9 @@ let versions = {
} catch (err) {} } catch (err) {}
})(); })();
// Use NODE_DEBUG=sharp to enable libvips warnings
const debuglog = util.debuglog('sharp');
/** /**
* @class Sharp * @class Sharp
* *
@ -174,6 +177,8 @@ const Sharp = function (input, options) {
tiffSquash: false, tiffSquash: false,
tileSize: 256, tileSize: 256,
tileOverlap: 0, tileOverlap: 0,
// Function to notify of libvips warnings
debuglog: debuglog,
// Function to notify of queue length changes // Function to notify of queue length changes
queueListener: function (queueLength) { queueListener: function (queueLength) {
queue.emit('change', queueLength); queue.emit('change', queueLength);

View File

@ -99,6 +99,7 @@
"cc": { "cc": {
"linelength": "120", "linelength": "120",
"filter": [ "filter": [
"build/c++11",
"build/include", "build/include",
"runtime/indentation_namespace" "runtime/indentation_namespace"
] ]

View File

@ -16,6 +16,8 @@
#include <string> #include <string>
#include <string.h> #include <string.h>
#include <vector> #include <vector>
#include <queue>
#include <mutex>
#include <node.h> #include <node.h>
#include <node_buffer.h> #include <node_buffer.h>
@ -354,6 +356,33 @@ namespace sharp {
} }
} }
/*
Temporary buffer of warnings
*/
std::queue<std::string> 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<std::mutex> lock(vipsWarningsMutex);
vipsWarnings.emplace(message);
}
/*
Pop the oldest warning message from the queue
*/
std::string VipsWarningPop() {
std::string warning;
std::lock_guard<std::mutex> lock(vipsWarningsMutex);
if (!vipsWarnings.empty()) {
warning = vipsWarnings.front();
vipsWarnings.pop();
}
return warning;
}
/* /*
Calculate the (left, top) coordinates of the output image Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity. within the input image, applying the given gravity.

View File

@ -189,6 +189,16 @@ namespace sharp {
*/ */
void FreeCallback(char* data, void* hint); 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 Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity. within the input image, applying the given gravity.

View File

@ -25,9 +25,10 @@
class MetadataWorker : public Nan::AsyncWorker { class MetadataWorker : public Nan::AsyncWorker {
public: public:
MetadataWorker( MetadataWorker(
Nan::Callback *callback, MetadataBaton *baton, Nan::Callback *callback, MetadataBaton *baton, Nan::Callback *debuglog,
std::vector<v8::Local<v8::Object>> const buffersToPersist) std::vector<v8::Local<v8::Object>> const buffersToPersist) :
: Nan::AsyncWorker(callback), baton(baton), buffersToPersist(buffersToPersist) { Nan::AsyncWorker(callback), baton(baton), debuglog(debuglog),
buffersToPersist(buffersToPersist) {
// Protect Buffer objects from GC, keyed on index // Protect Buffer objects from GC, keyed on index
std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0, std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0,
[this](uint32_t index, v8::Local<v8::Object> const buffer) -> uint32_t { [this](uint32_t index, v8::Local<v8::Object> const buffer) -> uint32_t {
@ -132,12 +133,21 @@ class MetadataWorker : public Nan::AsyncWorker {
delete baton->input; delete baton->input;
delete baton; delete baton;
// Handle warnings
std::string warning = sharp::VipsWarningPop();
while (!warning.empty()) {
v8::Local<v8::Value> message[1] = { New(warning).ToLocalChecked() };
debuglog->Call(1, message);
warning = sharp::VipsWarningPop();
}
// Return to JavaScript // Return to JavaScript
callback->Call(2, argv); callback->Call(2, argv);
} }
private: private:
MetadataBaton* baton; MetadataBaton* baton;
Nan::Callback *debuglog;
std::vector<v8::Local<v8::Object>> buffersToPersist; std::vector<v8::Local<v8::Object>> buffersToPersist;
}; };
@ -155,9 +165,12 @@ NAN_METHOD(metadata) {
// Input // Input
baton->input = sharp::CreateInputDescriptor(sharp::AttrAs<v8::Object>(options, "input"), buffersToPersist); baton->input = sharp::CreateInputDescriptor(sharp::AttrAs<v8::Object>(options, "input"), buffersToPersist);
// Function to notify of libvips warnings
Nan::Callback *debuglog = new Nan::Callback(sharp::AttrAs<v8::Function>(options, "debuglog"));
// Join queue for worker thread // Join queue for worker thread
Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>()); Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());
Nan::AsyncQueueWorker(new MetadataWorker(callback, baton, buffersToPersist)); Nan::AsyncQueueWorker(new MetadataWorker(callback, baton, debuglog, buffersToPersist));
// Increment queued task counter // Increment queued task counter
g_atomic_int_inc(&sharp::counterQueue); g_atomic_int_inc(&sharp::counterQueue);

View File

@ -33,9 +33,10 @@
class PipelineWorker : public Nan::AsyncWorker { class PipelineWorker : public Nan::AsyncWorker {
public: public:
PipelineWorker( PipelineWorker(
Nan::Callback *callback, PipelineBaton *baton, Nan::Callback *queueListener, Nan::Callback *callback, PipelineBaton *baton, Nan::Callback *debuglog, Nan::Callback *queueListener,
std::vector<v8::Local<v8::Object>> const buffersToPersist) std::vector<v8::Local<v8::Object>> const buffersToPersist) :
: Nan::AsyncWorker(callback), baton(baton), queueListener(queueListener), buffersToPersist(buffersToPersist) { Nan::AsyncWorker(callback), baton(baton), debuglog(debuglog), queueListener(queueListener),
buffersToPersist(buffersToPersist) {
// Protect Buffer objects from GC, keyed on index // Protect Buffer objects from GC, keyed on index
std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0, std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0,
[this](uint32_t index, v8::Local<v8::Object> const buffer) -> uint32_t { [this](uint32_t index, v8::Local<v8::Object> const buffer) -> uint32_t {
@ -979,6 +980,14 @@ class PipelineWorker : public Nan::AsyncWorker {
}); });
delete baton; delete baton;
// Handle warnings
std::string warning = sharp::VipsWarningPop();
while (!warning.empty()) {
v8::Local<v8::Value> message[1] = { New(warning).ToLocalChecked() };
debuglog->Call(1, message);
warning = sharp::VipsWarningPop();
}
// Decrement processing task counter // Decrement processing task counter
g_atomic_int_dec_and_test(&sharp::counterProcess); g_atomic_int_dec_and_test(&sharp::counterProcess);
v8::Local<v8::Value> queueLength[1] = { New<v8::Uint32>(sharp::counterQueue) }; v8::Local<v8::Value> queueLength[1] = { New<v8::Uint32>(sharp::counterQueue) };
@ -991,6 +1000,7 @@ class PipelineWorker : public Nan::AsyncWorker {
private: private:
PipelineBaton *baton; PipelineBaton *baton;
Nan::Callback *debuglog;
Nan::Callback *queueListener; Nan::Callback *queueListener;
std::vector<v8::Local<v8::Object>> buffersToPersist; std::vector<v8::Local<v8::Object>> buffersToPersist;
@ -1239,12 +1249,15 @@ NAN_METHOD(pipeline) {
baton->accessMethod = VIPS_ACCESS_RANDOM; baton->accessMethod = VIPS_ACCESS_RANDOM;
} }
// Function to notify of libvips warnings
Nan::Callback *debuglog = new Nan::Callback(AttrAs<v8::Function>(options, "debuglog"));
// Function to notify of queue length changes // Function to notify of queue length changes
Nan::Callback *queueListener = new Nan::Callback(AttrAs<v8::Function>(options, "queueListener")); Nan::Callback *queueListener = new Nan::Callback(AttrAs<v8::Function>(options, "queueListener"));
// Join queue for worker thread // Join queue for worker thread
Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>()); Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());
Nan::AsyncQueueWorker(new PipelineWorker(callback, baton, queueListener, buffersToPersist)); Nan::AsyncQueueWorker(new PipelineWorker(callback, baton, debuglog, queueListener, buffersToPersist));
// Increment queued task counter // Increment queued task counter
g_atomic_int_inc(&sharp::counterQueue); g_atomic_int_inc(&sharp::counterQueue);

View File

@ -24,6 +24,9 @@
NAN_MODULE_INIT(init) { NAN_MODULE_INIT(init) {
vips_init("sharp"); vips_init("sharp");
g_log_set_handler("VIPS", static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING),
static_cast<GLogFunc>(sharp::VipsWarningCallback), nullptr);
// Methods available to JavaScript // Methods available to JavaScript
Nan::Set(target, Nan::New("metadata").ToLocalChecked(), Nan::Set(target, Nan::New("metadata").ToLocalChecked(),
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(metadata)).ToLocalChecked()); Nan::GetFunction(Nan::New<v8::FunctionTemplate>(metadata)).ToLocalChecked());