refactor: switch to node-addon-api (#43)
This commit is contained in:
Родитель
4becd02b70
Коммит
0847fc6af5
|
@ -5,7 +5,7 @@ trigger:
|
|||
include: ['*']
|
||||
|
||||
jobs:
|
||||
- job: Windows64
|
||||
- job: Windows
|
||||
pool:
|
||||
vmImage: 'windows-latest'
|
||||
variables:
|
||||
|
@ -13,14 +13,6 @@ jobs:
|
|||
steps:
|
||||
- template: build.yml
|
||||
|
||||
- job: Windows32
|
||||
pool:
|
||||
vmImage: 'windows-latest'
|
||||
variables:
|
||||
NPM_ARCH: 'ia32'
|
||||
steps:
|
||||
- template: build.yml
|
||||
|
||||
- job: macOS
|
||||
pool:
|
||||
vmImage: 'macOS-latest'
|
||||
|
@ -34,9 +26,5 @@ jobs:
|
|||
vmImage: 'Ubuntu-latest'
|
||||
variables:
|
||||
NPM_ARCH: 'x64'
|
||||
dependsOn:
|
||||
- Windows64
|
||||
- Windows32
|
||||
- macOS
|
||||
steps:
|
||||
- template: build.yml
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
{
|
||||
"targets": [{
|
||||
"target_name": "spdlog",
|
||||
'dependencies': [
|
||||
"<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except",
|
||||
],
|
||||
"sources": [
|
||||
"src/main.cc",
|
||||
"src/logger.cc"
|
||||
],
|
||||
"include_dirs": [
|
||||
"<!(node -e \"require('nan')\")",
|
||||
"<!(node -p \"require('node-addon-api').include_dir\")",
|
||||
"deps/spdlog/include"
|
||||
],
|
||||
'cflags!': ['-fno-exceptions'],
|
||||
'cflags_cc!': ['-fno-exceptions'],
|
||||
'msvs_configuration_attributes': {
|
||||
'SpectreMitigation': 'Spectre'
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"dependencies": {
|
||||
"bindings": "^1.5.0",
|
||||
"mkdirp": "^1.0.4",
|
||||
"nan": "^2.17.0"
|
||||
"node-addon-api": "7.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^10.0.0",
|
||||
|
@ -649,11 +649,6 @@
|
|||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.17.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
|
||||
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
|
||||
|
@ -666,6 +661,14 @@
|
|||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz",
|
||||
"integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==",
|
||||
"engines": {
|
||||
"node": "^16 || ^18 || >= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
|
@ -1423,17 +1426,17 @@
|
|||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.17.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
|
||||
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
|
||||
"integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node-addon-api": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz",
|
||||
"integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g=="
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
"ui": "tdd"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "cp -R ~/.node-gyp/$(node -p 'process.versions.node')/include/node deps/node",
|
||||
"test": "mocha"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -20,9 +19,7 @@
|
|||
"spdlog",
|
||||
"logging",
|
||||
"logger",
|
||||
"log",
|
||||
"fast",
|
||||
"performance"
|
||||
"log"
|
||||
],
|
||||
"author": "Microsoft",
|
||||
"license": "MIT",
|
||||
|
@ -33,7 +30,7 @@
|
|||
"dependencies": {
|
||||
"bindings": "^1.5.0",
|
||||
"mkdirp": "^1.0.4",
|
||||
"nan": "^2.17.0"
|
||||
"node-addon-api": "7.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^10.0.0",
|
||||
|
|
397
src/logger.cc
397
src/logger.cc
|
@ -15,315 +15,180 @@
|
|||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
std::string utf8StringAsString(Nan::Utf8String&& str) {
|
||||
return std::string(*str, str.length());
|
||||
Napi::Object Logger::Init(Napi::Env env, Napi::Object exports) {
|
||||
Napi::FunctionReference* constructor = new Napi::FunctionReference();
|
||||
Napi::Function definition = DefineClass(env, "Logger", {
|
||||
InstanceMethod<&Logger::GetLevel>("getLevel"),
|
||||
InstanceMethod<&Logger::SetLevel>("setLevel"),
|
||||
InstanceMethod<&Logger::Flush>("flush"),
|
||||
InstanceMethod<&Logger::Drop>("drop"),
|
||||
InstanceMethod<&Logger::SetPattern>("setPattern"),
|
||||
InstanceMethod<&Logger::ClearFormatters>("clearFormatters"),
|
||||
InstanceMethod<&Logger::Log<spdlog::level::level_enum::critical>>("critical"),
|
||||
InstanceMethod<&Logger::Log<spdlog::level::level_enum::err>>("error"),
|
||||
InstanceMethod<&Logger::Log<spdlog::level::level_enum::warn>>("warn"),
|
||||
InstanceMethod<&Logger::Log<spdlog::level::level_enum::info>>("info"),
|
||||
InstanceMethod<&Logger::Log<spdlog::level::level_enum::debug>>("debug"),
|
||||
InstanceMethod<&Logger::Log<spdlog::level::level_enum::trace>>("trace"),
|
||||
});
|
||||
*constructor = Napi::Persistent(definition);
|
||||
exports.Set("Logger", definition);
|
||||
env.SetInstanceData<Napi::FunctionReference>(constructor);
|
||||
return exports;
|
||||
}
|
||||
|
||||
NAN_METHOD(setLevel) {
|
||||
if (!info[0]->IsNumber()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide level"));
|
||||
Logger::Logger(const Napi::CallbackInfo& info)
|
||||
: Napi::ObjectWrap<Logger>(info) {
|
||||
Napi::Env env(info.Env());
|
||||
|
||||
if (!info[0].IsString()) {
|
||||
throw Napi::Error::New(env, "Provide a logger name");
|
||||
}
|
||||
|
||||
const int64_t levelNumber = Nan::To<int64_t>(info[0]).FromJust();
|
||||
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
|
||||
return Nan::ThrowError(Nan::Error("Invalid level"));
|
||||
}
|
||||
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
|
||||
const std::string name = info[0].As<Napi::String>();
|
||||
|
||||
spdlog::set_level(level);
|
||||
if (name == "rotating" || name == "rotating_async") {
|
||||
if (!info[1].IsString() || !info[2].IsString()) {
|
||||
throw Napi::Error::New(env, "Provide the log name and file name");
|
||||
}
|
||||
if (!info[3].IsNumber() || !info[4].IsNumber()) {
|
||||
throw Napi::Error::New(env, "Provide the max size and max files");
|
||||
}
|
||||
const std::string logName = info[1].As<Napi::String>();
|
||||
logger_ = spdlog::get(logName);
|
||||
|
||||
if (!logger_) {
|
||||
#if defined(_WIN32)
|
||||
const std::string utf8Filename = info[2].As<Napi::String>();
|
||||
const int bufferLen = MultiByteToWideChar(
|
||||
CP_UTF8, 0, utf8Filename.c_str(),
|
||||
static_cast<int>(utf8Filename.size()), NULL, 0);
|
||||
if (!bufferLen) {
|
||||
throw Napi::Error::New(env, "Failed to determine buffer length for converting filename to wstring");
|
||||
}
|
||||
std::wstring fileName(bufferLen, 0);
|
||||
const int status = MultiByteToWideChar(
|
||||
CP_UTF8, 0, utf8Filename.c_str(),
|
||||
static_cast<int>(utf8Filename.size()), &fileName[0], bufferLen);
|
||||
if (!status) {
|
||||
throw Napi::Error::New(env, "Failed to convert filename to wstring");
|
||||
}
|
||||
#else
|
||||
const std::string fileName = info[2].As<Napi::String>();
|
||||
#endif
|
||||
if (logName == "rotating_async") {
|
||||
logger_ = spdlog::rotating_logger_st<spdlog::async_factory>(
|
||||
logName, fileName, static_cast<size_t>(info[3].As<Napi::Number>().Int64Value()),
|
||||
static_cast<size_t>(info[4].As<Napi::Number>().Int64Value()));
|
||||
} else {
|
||||
logger_ = spdlog::rotating_logger_st(
|
||||
logName, fileName, static_cast<size_t>(info[3].As<Napi::Number>().Int64Value()),
|
||||
static_cast<size_t>(info[4].As<Napi::Number>().Int64Value()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger_ = spdlog::stdout_logger_st<spdlog::async_factory>(name);
|
||||
}
|
||||
}
|
||||
|
||||
NAN_METHOD(setFlushOn) {
|
||||
if (!info[0]->IsNumber()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide flush level"));
|
||||
}
|
||||
|
||||
const int64_t levelNumber = Nan::To<int64_t>(info[0]).FromJust();
|
||||
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
|
||||
return Nan::ThrowError(Nan::Error("Invalid level"));
|
||||
}
|
||||
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
|
||||
|
||||
spdlog::flush_on(level);
|
||||
}
|
||||
|
||||
Nan::Persistent<v8::Function> Logger::constructor;
|
||||
|
||||
NAN_MODULE_INIT(Logger::Init) {
|
||||
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
|
||||
tpl->SetClassName(Nan::New("Logger").ToLocalChecked());
|
||||
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
Nan::SetPrototypeMethod(tpl, "critical", Logger::Critical);
|
||||
Nan::SetPrototypeMethod(tpl, "error", Logger::Error);
|
||||
Nan::SetPrototypeMethod(tpl, "warn", Logger::Warn);
|
||||
Nan::SetPrototypeMethod(tpl, "info", Logger::Info);
|
||||
Nan::SetPrototypeMethod(tpl, "debug", Logger::Debug);
|
||||
Nan::SetPrototypeMethod(tpl, "trace", Logger::Trace);
|
||||
|
||||
Nan::SetPrototypeMethod(tpl, "getLevel", Logger::GetLevel);
|
||||
Nan::SetPrototypeMethod(tpl, "setLevel", Logger::SetLevel);
|
||||
Nan::SetPrototypeMethod(tpl, "flush", Logger::Flush);
|
||||
Nan::SetPrototypeMethod(tpl, "drop", Logger::Drop);
|
||||
Nan::SetPrototypeMethod(tpl, "setPattern", Logger::SetPattern);
|
||||
Nan::SetPrototypeMethod(tpl, "clearFormatters", Logger::ClearFormatters);
|
||||
|
||||
constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
|
||||
Nan::Set(target, Nan::New("Logger").ToLocalChecked(),
|
||||
Nan::GetFunction(tpl).ToLocalChecked());
|
||||
}
|
||||
|
||||
Logger::Logger(std::shared_ptr<spdlog::logger> logger) : logger_(logger) {}
|
||||
|
||||
Logger::~Logger() {
|
||||
if (logger_ == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
spdlog::drop(logger_->name());
|
||||
if (logger_)
|
||||
spdlog::drop(logger_->name());
|
||||
} catch (...) {
|
||||
// noop
|
||||
}
|
||||
|
||||
logger_ = NULL;
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::New) {
|
||||
try {
|
||||
if (info.IsConstructCall()) {
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide a logger name"));
|
||||
}
|
||||
template<spdlog::level::level_enum level>
|
||||
void Logger::Log(const Napi::CallbackInfo& info) {
|
||||
Napi::Env env(info.Env());
|
||||
|
||||
const std::string name = utf8StringAsString(Nan::Utf8String(info[0]));
|
||||
std::shared_ptr<spdlog::logger> logger;
|
||||
if (!info[0].IsString()) {
|
||||
throw Napi::Error::New(env, "Provide a message to log");
|
||||
}
|
||||
|
||||
if (name == "rotating" || name == "rotating_async") {
|
||||
if (!info[1]->IsString() || !info[2]->IsString()) {
|
||||
return Nan::ThrowError(
|
||||
Nan::Error("Provide the log name and file name"));
|
||||
}
|
||||
if (!info[3]->IsNumber() || !info[4]->IsNumber()) {
|
||||
return Nan::ThrowError(
|
||||
Nan::Error("Provide the max size and max files"));
|
||||
}
|
||||
const std::string logName = utf8StringAsString(Nan::Utf8String(info[1]));
|
||||
|
||||
logger = spdlog::get(logName);
|
||||
|
||||
if (!logger) {
|
||||
#if defined(_WIN32)
|
||||
const std::string utf8Filename = utf8StringAsString(Nan::Utf8String(info[2]));
|
||||
const int bufferLen = MultiByteToWideChar(
|
||||
CP_UTF8, 0, utf8Filename.c_str(),
|
||||
static_cast<int>(utf8Filename.size()), NULL, 0);
|
||||
if (!bufferLen) {
|
||||
return Nan::ThrowError(
|
||||
Nan::Error("Failed to determine buffer length for converting filename to wstring"));
|
||||
}
|
||||
std::wstring fileName(bufferLen, 0);
|
||||
const int status = MultiByteToWideChar(
|
||||
CP_UTF8, 0, utf8Filename.c_str(),
|
||||
static_cast<int>(utf8Filename.size()), &fileName[0], bufferLen);
|
||||
if (!status) {
|
||||
return Nan::ThrowError(
|
||||
Nan::Error("Failed to convert filename to wstring"));
|
||||
}
|
||||
#else
|
||||
const std::string fileName = utf8StringAsString(Nan::Utf8String(info[2]));
|
||||
#endif
|
||||
|
||||
if (logName == "rotating_async") {
|
||||
logger = spdlog::rotating_logger_st<spdlog::async_factory>(
|
||||
logName, fileName, static_cast<size_t>(Nan::To<int64_t>(info[3]).FromJust()),
|
||||
static_cast<size_t>(Nan::To<int64_t>(info[4]).FromJust()));
|
||||
} else {
|
||||
logger = spdlog::rotating_logger_st(
|
||||
logName, fileName, static_cast<size_t>(Nan::To<int64_t>(info[3]).FromJust()),
|
||||
static_cast<size_t>(Nan::To<int64_t>(info[4]).FromJust()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger = spdlog::stdout_logger_st<spdlog::async_factory>(name);
|
||||
}
|
||||
Logger *obj = new Logger(logger);
|
||||
obj->Wrap(info.This());
|
||||
info.GetReturnValue().Set(info.This());
|
||||
} else {
|
||||
const int argc = 1;
|
||||
v8::Local<v8::Value> argv[argc] = {info[0]};
|
||||
v8::Local<v8::Function> cons = Nan::New(constructor);
|
||||
info.GetReturnValue().Set(
|
||||
Nan::NewInstance(cons, argc, argv).ToLocalChecked());
|
||||
if (logger_) {
|
||||
std::string message = info[0].As<Napi::String>();
|
||||
switch(level) {
|
||||
case spdlog::level::level_enum::critical:
|
||||
logger_->critical(message);
|
||||
break;
|
||||
case spdlog::level::level_enum::err:
|
||||
logger_->error(message);
|
||||
break;
|
||||
case spdlog::level::level_enum::warn:
|
||||
logger_->warn(message);
|
||||
break;
|
||||
case spdlog::level::level_enum::info:
|
||||
logger_->info(message);
|
||||
break;
|
||||
case spdlog::level::level_enum::debug:
|
||||
logger_->debug(message);
|
||||
break;
|
||||
case spdlog::level::level_enum::trace:
|
||||
logger_->trace(message);
|
||||
break;
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
return Nan::ThrowError(Nan::Error(ex.what()));
|
||||
} catch (...) {
|
||||
return Nan::ThrowError(Nan::Error("Unknown error creating log file"));
|
||||
}
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::Critical) {
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide a message to log"));
|
||||
Napi::Value Logger::GetLevel(const Napi::CallbackInfo& info) {
|
||||
Napi::Env env(info.Env());
|
||||
|
||||
if (logger_) {
|
||||
return Napi::Number::New(env, logger_->level());
|
||||
}
|
||||
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
|
||||
obj->logger_->critical(message);
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
return Napi::Number::New(env, 2);
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::Error) {
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide a message to log"));
|
||||
void Logger::SetLevel(const Napi::CallbackInfo& info) {
|
||||
Napi::Env env(info.Env());
|
||||
|
||||
if (!info[0].IsNumber()) {
|
||||
throw Napi::Error::New(env, "Provide level");
|
||||
}
|
||||
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
|
||||
obj->logger_->error(message);
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::Warn) {
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide a message to log"));
|
||||
}
|
||||
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
|
||||
obj->logger_->warn(message);
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::Info) {
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide a message to log"));
|
||||
}
|
||||
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
|
||||
obj->logger_->info(message);
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::Debug) {
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide a message to log"));
|
||||
}
|
||||
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
|
||||
obj->logger_->debug(message);
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::Trace) {
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide a message to log"));
|
||||
}
|
||||
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
std::string message = utf8StringAsString(Nan::Utf8String(info[0]));
|
||||
obj->logger_->trace(message);
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::GetLevel) {
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
info.GetReturnValue().Set(obj->logger_->level());
|
||||
}
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::SetLevel) {
|
||||
if (!info[0]->IsNumber()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide level"));
|
||||
}
|
||||
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
const int64_t levelNumber = Nan::To<int64_t>(info[0]).FromJust();
|
||||
if (logger_) {
|
||||
const int64_t levelNumber = info[0].As<Napi::Number>().Int64Value();
|
||||
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
|
||||
return Nan::ThrowError(Nan::Error("Invalid level"));
|
||||
throw Napi::Error::New(env, "Invalid level");
|
||||
}
|
||||
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
|
||||
obj->logger_->set_level(level);
|
||||
logger_->set_level(level);
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::Flush) {
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
obj->logger_->flush();
|
||||
void Logger::Flush(const Napi::CallbackInfo& info) {
|
||||
if (logger_) {
|
||||
logger_->flush();
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::Drop) {
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
const std::string name = obj->logger_->name();
|
||||
obj->logger_ = NULL;
|
||||
void Logger::Drop(const Napi::CallbackInfo& info) {
|
||||
if (logger_) {
|
||||
const std::string name = logger_->name();
|
||||
logger_.reset();
|
||||
spdlog::drop(name);
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::SetPattern) {
|
||||
if (!info[0]->IsString()) {
|
||||
return Nan::ThrowError(Nan::Error("Provide pattern"));
|
||||
}
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
const std::string pattern = utf8StringAsString(Nan::Utf8String(info[0]));
|
||||
void Logger::SetPattern(const Napi::CallbackInfo& info) {
|
||||
Napi::Env env(info.Env());
|
||||
|
||||
if (obj->logger_) {
|
||||
obj->logger_->set_pattern(pattern);
|
||||
if (!info[0].IsString()) {
|
||||
throw Napi::Error::New(env, "Provide pattern");
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
const std::string pattern = info[0].As<Napi::String>();
|
||||
if (logger_) {
|
||||
logger_->set_pattern(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
NAN_METHOD(Logger::ClearFormatters) {
|
||||
Logger *obj = Nan::ObjectWrap::Unwrap<Logger>(info.This());
|
||||
|
||||
if (obj->logger_) {
|
||||
obj->logger_->set_formatter(
|
||||
void Logger::ClearFormatters(const Napi::CallbackInfo& info) {
|
||||
if (logger_) {
|
||||
logger_->set_formatter(
|
||||
std::unique_ptr<VoidFormatter>(new VoidFormatter()));
|
||||
}
|
||||
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
|
40
src/logger.h
40
src/logger.h
|
@ -4,44 +4,32 @@
|
|||
* license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
#include <nan.h>
|
||||
#include <napi.h>
|
||||
|
||||
// Prevent child processes from inheriting the file handles
|
||||
#define SPDLOG_PREVENT_CHILD_FD
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
NAN_METHOD(setLevel);
|
||||
NAN_METHOD(setFlushOn);
|
||||
|
||||
class Logger : public Nan::ObjectWrap {
|
||||
class Logger : public Napi::ObjectWrap<Logger> {
|
||||
public:
|
||||
static NAN_MODULE_INIT(Init);
|
||||
static Napi::Object Init(Napi::Env env, Napi::Object exports);
|
||||
explicit Logger(const Napi::CallbackInfo& info);
|
||||
|
||||
private:
|
||||
explicit Logger(std::shared_ptr<spdlog::logger> logger);
|
||||
friend class Napi::ObjectWrap<Logger>;
|
||||
~Logger();
|
||||
|
||||
static NAN_METHOD(New);
|
||||
template<spdlog::level::level_enum level>
|
||||
void Log(const Napi::CallbackInfo& info);
|
||||
|
||||
static NAN_METHOD(Critical);
|
||||
static NAN_METHOD(Error);
|
||||
static NAN_METHOD(Warn);
|
||||
static NAN_METHOD(Info);
|
||||
static NAN_METHOD(Debug);
|
||||
static NAN_METHOD(Trace);
|
||||
|
||||
static NAN_METHOD(GetLevel);
|
||||
static NAN_METHOD(SetLevel);
|
||||
static NAN_METHOD(Flush);
|
||||
static NAN_METHOD(Drop);
|
||||
static NAN_METHOD(SetPattern);
|
||||
static NAN_METHOD(ClearFormatters);
|
||||
|
||||
static Nan::Persistent<v8::Function> constructor;
|
||||
Napi::Value GetLevel(const Napi::CallbackInfo& info);
|
||||
void SetLevel(const Napi::CallbackInfo& info);
|
||||
void Flush(const Napi::CallbackInfo& info);
|
||||
void Drop(const Napi::CallbackInfo& info);
|
||||
void SetPattern(const Napi::CallbackInfo& info);
|
||||
void ClearFormatters(const Napi::CallbackInfo& info);
|
||||
|
||||
std::shared_ptr<spdlog::logger> logger_;
|
||||
};
|
||||
|
@ -55,5 +43,3 @@ class VoidFormatter : public spdlog::formatter {
|
|||
return spdlog::details::make_unique<VoidFormatter>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !CONSOLE_H
|
||||
|
|
47
src/main.cc
47
src/main.cc
|
@ -4,15 +4,48 @@
|
|||
* license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
#include <nan.h>
|
||||
#include <napi.h>
|
||||
#include "logger.h"
|
||||
|
||||
NAN_MODULE_INIT(Init) {
|
||||
Nan::Set(target, Nan::New("version").ToLocalChecked(), Nan::New(SPDLOG_VERSION));
|
||||
Nan::SetMethod(target, "setLevel", setLevel);
|
||||
Nan::SetMethod(target, "setFlushOn", setFlushOn);
|
||||
void SetLevel(const Napi::CallbackInfo& info) {
|
||||
Napi::Env env(info.Env());
|
||||
|
||||
Logger::Init(target);
|
||||
if (!info[0].IsNumber()) {
|
||||
throw Napi::Error::New(env, "Provide level");
|
||||
}
|
||||
|
||||
const int64_t levelNumber = info[0].As<Napi::Number>().Int64Value();
|
||||
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
|
||||
throw Napi::Error::New(env, "Invalid level");
|
||||
}
|
||||
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
|
||||
|
||||
spdlog::set_level(level);
|
||||
}
|
||||
|
||||
NODE_MODULE(spdlog, Init)
|
||||
void SetFlushOn(const Napi::CallbackInfo& info) {
|
||||
Napi::Env env(info.Env());
|
||||
|
||||
if (!info[0].IsNumber()) {
|
||||
throw Napi::Error::New(env, "Provide flush level");
|
||||
}
|
||||
|
||||
const int64_t levelNumber = info[0].As<Napi::Number>().Int64Value();
|
||||
if (levelNumber >= spdlog::level::n_levels || levelNumber < spdlog::level::trace) {
|
||||
throw Napi::Error::New(env, "Invalid level");
|
||||
}
|
||||
auto level = static_cast<spdlog::level::level_enum>(levelNumber);
|
||||
|
||||
spdlog::flush_on(level);
|
||||
}
|
||||
|
||||
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set("version", Napi::Number::New(env, SPDLOG_VERSION));
|
||||
exports.Set("setLevel", Napi::Function::New(env, SetLevel));
|
||||
exports.Set("setFlushOn", Napi::Function::New(env, SetFlushOn));
|
||||
|
||||
Logger::Init(env, exports);
|
||||
return exports;
|
||||
}
|
||||
|
||||
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init);
|
||||
|
|
Загрузка…
Ссылка в новой задаче