日志

每个使用 C++、Java 或 Python 编写的 UDx 都有一个关联的 ServerInterface 实例。ServerInterface 类提供了写入 Vertica 日志的功能,C++ 实施还提供了在系统表中记录事件的功能。

将消息写入 Vertica 日志

可以使用 ServerInterface.log() 函数将消息写入到日志文件。此函数的工作方式与 printf() 相似,它使用已设置格式的字符串和一个可选值集,并将字符串写入到日志文件。将消息写入到的位置取决于函数在隔离模式还是非隔离模式下运行。

  • 在非隔离模式下运行的函数会将其消息写入到编录目录中的 vertica.log 文件。

  • 在隔离模式下运行的函数会将其消息写入到编录目录中名为 UDxLogs/UDxFencedProcesses.log 的日志文件。

为了帮助标识函数的输出,Vertica 会将绑定到 UDx 的 SQL 函数名称添加到日志消息中。

以下示例将记录 UDx 的输入值:

    virtual void processBlock(ServerInterface &srvInterface,
                              BlockReader &argReader,
                              BlockWriter &resWriter)
    {
        try {
            // While we have inputs to process
            do {
                if (argReader.isNull(0) || argReader.isNull(1)) {
                    resWriter.setNull();
                } else {
                    const vint a = argReader.getIntRef(0);
                    const vint b = argReader.getIntRef(1);
                    <span class="code-input">srvInterface.log("got a: %d and b: %d", (int) a, (int) b);</span>
                    resWriter.setInt(a+b);
                }
                resWriter.next();
            } while (argReader.next());
        } catch(std::exception& e) {
            // Standard exception. Quit.
            vt_report_error(0, "Exception while processing block: [%s]", e.what());
        }
    }
        @Override
        public void processBlock(ServerInterface srvInterface,
                                 BlockReader argReader,
                                 BlockWriter resWriter)
                    throws UdfException, DestroyInvocation
        {
            do {
                // Get the two integer arguments from the BlockReader
                long a = argReader.getLong(0);
                long b = argReader.getLong(1);

                // Log the input values
                <span class="code-input">srvInterface.log("Got values a=%d and b=%d", a, b);</span>

                long result = a+b;
                resWriter.setLong(result);
                resWriter.next();
            } while (argReader.next());
        }
    }
    def processBlock(self, server_interface, arg_reader, res_writer):
        server_interface.log("Python UDx - Adding 2 ints!")
        while(True):
            first_int = block_reader.getInt(0)
            second_int = block_reader.getInt(1)
            block_writer.setInt(first_int + second_int)
            <span class="code-input">server_interface.log("Values: first_int is {} second_int is {}".format(first_int, second_int))</span>
            block_writer.next()
            if not block_reader.next():
                break

log() 函数在日志文件中生成条目,如下所示:

$ tail /home/dbadmin/py_db/v_py_db_node0001_catalog/UDxLogs/UDxFencedProcesses.log
 07:52:12.862 [Python-v_py_db_node0001-7524:0x206c-40575]  0x7f70eee2f780 PythonExecContext::processBlock
 07:52:12.862 [Python-v_py_db_node0001-7524:0x206c-40575]  0x7f70eee2f780 [UserMessage] add2ints - Python UDx - Adding 2 ints!
 07:52:12.862 [Python-v_py_db_node0001-7524:0x206c-40575]  0x7f70eee2f780 [UserMessage] add2ints - Values: first_int is 100 second_int is 100

有关查看 Vertica 日志文件的详细信息,请参阅监控日志文件

将消息写入 UDX_EVENTS 表(仅限 C++)

在 C++ API 中,除了写入日志之外,您还可以将消息写入 UDX_EVENTS 系统表。写入系统表之后,您可以将来自所有节点的事件收集至一个位置中。

可以使用 ServerInterface.logEvent() 函数将消息写入此表。该函数将提取一个实参和一个映射。映射作为 Flex VMap 写入表的 RAW 列。以下示例显示 Parquet 导出器如何创建和记录此映射。

// Log exported parquet file details to v_monitor.udx_events
std::map<std::string, std::string> details;
details["file"] = escapedPath;
details["created"] = create_timestamp_;
details["closed"] = close_timestamp_;
details["rows"] = std::to_string(num_rows_in_file);
details["row_groups"] = std::to_string(num_row_groups_in_file);
details["size_mb"] = std::to_string((double)outputStream->Tell()/(1024*1024));
srvInterface.logEvent(details);

您可以从 VMap 中选择单个字段,如下例所示。

=> SELECT __RAW__['file'] FROM UDX_EVENTS;
                                   __RAW__
-----------------------------------------------------------------------------
 /tmp/export_tmpzLkrKq3a/450c4213-v_vmart_node0001-139770732459776-0.parquet
 /tmp/export_tmpzLkrKq3a/9df1c797-v_vmart_node0001-139770860660480-0.parquet
(2 rows)

或者,您可以定义一个视图,以便像列一样更轻松地直接查询字段。有关示例,请参阅 监控导出