Skip to content

Commit

Permalink
Feature/issue 869 backport console log (#870)
Browse files Browse the repository at this point in the history
* add 'log' function to JavaScript UDA/UDF for debugging. close #4912 (#4997)

* minor refinement for javascript log console (#5018)

* change LOG_DEBUG to LOG INFO  and add try-catch (#5631)

* change LOG_DEBUG to LOG INFO  and add try-catch

* clang-format

* add map,set transform

* remove useless include

* fix some comments

* move comments

* format code

* fix last comments

* fix catch

* fix compile error

---------

Co-authored-by: sunset3000 <tian.fan@timeplus.io>
Co-authored-by: Ken Chen <zlchen.ken@gmail.com>
Co-authored-by: chhtimeplus <162944718+chhtimeplus@users.noreply.github.com>
  • Loading branch information
4 people authored Dec 9, 2024
1 parent 0cc5119 commit dccb20f
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/AggregateFunctions/tests/gtest_uda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,4 +712,4 @@ TEST_F(UDATestCase, prepareArgumentsUInt8)
};

checkPrepareArguments("uint8", create_uint8_arr, check_uint8);
}
}
3 changes: 3 additions & 0 deletions src/Common/ProtonCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <base/types.h>

#include <vector>
#include <map>

namespace DB
{
Expand Down Expand Up @@ -66,6 +67,8 @@ const String JSON_VALUES_PREFIX = "__json_values_";
const String UDF_XML_PATTERN = "*_function.xml";
/// UDF VERSION used by this version of proton
const uint32_t UDF_VERSION = 1;
/// Prefix for all Javascript UDF or UDA loggers
const String PROTON_JAVASCRIPT_UDF_LOGGER_PREFIX = "JavaScriptUDF";

/// Storage modes
const String APPEND_MODE = "append";
Expand Down
1 change: 1 addition & 0 deletions src/V8/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include("${proton_SOURCE_DIR}/cmake/dbms_glob_sources.cmake")

add_headers_and_sources(V8 .)
add_headers_and_sources(V8 Modules)

add_library(V8 ${V8_headers} ${V8_sources})

Expand Down
84 changes: 84 additions & 0 deletions src/V8/Modules/Console.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <V8/ConvertDataTypes.h>
#include <V8/Modules/Console.h>

#include <Common/ProtonCommon.h>
#include <Common/logger_useful.h>

namespace DB
{

namespace V8
{

void log(const v8::FunctionCallbackInfo<v8::Value> & args)
{
v8::Isolate * isolate = args.GetIsolate();
assert(args.Length() >= 0);
std::vector<String> result(args.Length());
try
{
auto context = isolate->GetCurrentContext();
for (int i = 0; i < args.Length(); i++)
{
if (args[i]->IsString() || args[i]->IsNumber())
{
result[i] = from_v8<String>(isolate, args[i]);
}
else if (args[i]->IsObject())
{
/// trans Object to String
bool is_key_value = false;
auto obj = args[i].As<v8::Object>();
/// trans Map,Set to String
auto array = obj->PreviewEntries(&is_key_value);
if (!array.IsEmpty())
result[i] = from_v8<String>(isolate, array.ToLocalChecked()->ToString(context).ToLocalChecked());
else if (obj->IsRegExp())
result[i] = from_v8<String>(isolate, obj->ToString(context).ToLocalChecked());
else
result[i] = from_v8<String>(isolate, v8::JSON::Stringify(context, obj).ToLocalChecked());
}
else
{
/// default trans to String
result[i] = from_v8<String>(isolate, args[i]->ToString(context).ToLocalChecked());
}
}
LOG_INFO(&Poco::Logger::get(from_v8<String>(isolate, args.Data())), "{}", fmt::join(result, " "));
}
catch (DB::Exception & e)
{
LOG_ERROR(&Poco::Logger::get(from_v8<String>(isolate, args.Data())), "Hit an udf/uda error : {}", e.what());
}
catch(...)
{
tryLogCurrentException(__PRETTY_FUNCTION__);
}
}

v8::Local<v8::Object> WrapObject(v8::Isolate * isolate, const std::string & func_name)
{
v8::EscapableHandleScope handle_scope(isolate);

v8::Local<v8::ObjectTemplate> module = v8::ObjectTemplate::New(isolate);

module->SetInternalFieldCount(1);

/// add 'log' function
v8::Local<v8::Value> logger_name = to_v8(isolate, fmt::format("{}({})", DB::ProtonConsts::PROTON_JAVASCRIPT_UDF_LOGGER_PREFIX, func_name));
module->Set(isolate, "log", v8::FunctionTemplate::New(isolate, log, logger_name));

/// create instance
v8::Local<v8::Object> result = module->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();

return handle_scope.Escape(result);
}

void installConsole(v8::Isolate * isolate, v8::Local<v8::Context> & ctx, const std::string & func_name)
{
v8::Local<v8::Object> console = WrapObject(isolate, func_name);
ctx->Global()->Set(ctx, to_v8(isolate, "console"), console).Check();
}

}
}
17 changes: 17 additions & 0 deletions src/V8/Modules/Console.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <v8.h>

#include <string>

namespace DB
{

namespace V8
{
/// Install the module console to the specified v8 context,
/// \param func_name the function name of Javascript UDF or UDA, which is used to get the corresponding function logger
void installConsole(v8::Isolate * isolate, v8::Local<v8::Context> & ctx, const std::string & func_name);

}
}
10 changes: 9 additions & 1 deletion src/V8/Utils.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include <V8/ConvertDataTypes.h>
#include <V8/Modules/Console.h>
#include <V8/Utils.h>

#include <Core/DecimalFunctions.h>
#include <Functions/FunctionsConversion.h>
#include <base/getMemoryAmount.h>


#define FOR_V8_BASIC_NUMERIC_TYPES(M) \
M(UInt16) \
Expand Down Expand Up @@ -289,9 +292,14 @@ void compileSource(
/// try_catch.SetVerbose(true);
try_catch.SetCaptureMessage(true);

v8::Local<v8::Context> local_ctx = v8::Context::New(isolate);
/// Setup global object
v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
v8::Local<v8::Context> local_ctx = v8::Context::New(isolate, nullptr, global);
v8::Context::Scope context_scope(local_ctx);

/// Setup 'console' object
installConsole(isolate, local_ctx, func_name);

v8::Local<v8::String> script_code
= v8::String::NewFromUtf8(isolate, source.data(), v8::NewStringType::kNormal, static_cast<int>(source.size())).ToLocalChecked();

Expand Down

0 comments on commit dccb20f

Please sign in to comment.