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
### 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.

View File

@ -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);

View File

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

View File

@ -16,6 +16,8 @@
#include <string>
#include <string.h>
#include <vector>
#include <queue>
#include <mutex>
#include <node.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
within the input image, applying the given gravity.

View File

@ -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.

View File

@ -25,9 +25,10 @@
class MetadataWorker : public Nan::AsyncWorker {
public:
MetadataWorker(
Nan::Callback *callback, MetadataBaton *baton,
std::vector<v8::Local<v8::Object>> const buffersToPersist)
: Nan::AsyncWorker(callback), baton(baton), buffersToPersist(buffersToPersist) {
Nan::Callback *callback, MetadataBaton *baton, Nan::Callback *debuglog,
std::vector<v8::Local<v8::Object>> 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<v8::Object> 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<v8::Value> 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<v8::Local<v8::Object>> buffersToPersist;
};
@ -155,9 +165,12 @@ NAN_METHOD(metadata) {
// Input
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
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
g_atomic_int_inc(&sharp::counterQueue);

View File

@ -33,9 +33,10 @@
class PipelineWorker : public Nan::AsyncWorker {
public:
PipelineWorker(
Nan::Callback *callback, PipelineBaton *baton, Nan::Callback *queueListener,
std::vector<v8::Local<v8::Object>> const buffersToPersist)
: Nan::AsyncWorker(callback), baton(baton), queueListener(queueListener), buffersToPersist(buffersToPersist) {
Nan::Callback *callback, PipelineBaton *baton, Nan::Callback *debuglog, Nan::Callback *queueListener,
std::vector<v8::Local<v8::Object>> 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<v8::Object> 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<v8::Value> 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<v8::Value> queueLength[1] = { New<v8::Uint32>(sharp::counterQueue) };
@ -991,6 +1000,7 @@ class PipelineWorker : public Nan::AsyncWorker {
private:
PipelineBaton *baton;
Nan::Callback *debuglog;
Nan::Callback *queueListener;
std::vector<v8::Local<v8::Object>> 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<v8::Function>(options, "debuglog"));
// Function to notify of queue length changes
Nan::Callback *queueListener = new Nan::Callback(AttrAs<v8::Function>(options, "queueListener"));
// Join queue for worker thread
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
g_atomic_int_inc(&sharp::counterQueue);

View File

@ -24,6 +24,9 @@
NAN_MODULE_INIT(init) {
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
Nan::Set(target, Nan::New("metadata").ToLocalChecked(),
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(metadata)).ToLocalChecked());