Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion include/triton/common/logging.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright 2018-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -27,8 +27,10 @@

#include <array>
#include <cerrno>
#include <cstdint>
#include <cstring>
#include <fstream>
#include <functional>
#include <mutex>
#include <sstream>
#include <string>
Expand Down Expand Up @@ -140,6 +142,30 @@ class Logger {
return std::string();
}

// Delivers each enabled log record as structured fields to an embedding host
// (e.g. Dynamo), bypassing Triton's default stderr/file sink entirely.
//
// The callback is invoked on the producing thread, outside the output mutex.
// It must be lightweight, thread-safe, and must never throw.
typedef std::function<void(
Level level, bool is_verbose, const char* file, int line,
uint64_t timestamp_us, const char* message)>
LogCallbackFn;

// Registers the log callback, or clears it when passed an empty function.
// While set, log records are delivered only to the callback and the default
// stdout/stderr/file sink is bypassed.
//
// Access to the callback is not thread-safe and this class enforces no
// set-once policy, so it must be set before any thread that logs is started.
// In the Triton server, TRITONSERVER_ServerNew sets it during server
// initialization.
void SetLogCallback(LogCallbackFn callback)
{
callback_ = std::move(callback);
}
const LogCallbackFn& LogCallback() const { return callback_; }
Comment thread
pskiran1 marked this conversation as resolved.

// Log a message.
void Log(const std::string& msg, const Logger::Level level);

Expand All @@ -156,6 +182,7 @@ class Logger {
std::mutex mutex_;
std::string filename_;
std::ofstream file_stream_;
LogCallbackFn callback_;
};

extern Logger gLogger_;
Expand All @@ -179,6 +206,14 @@ class LogMessage {

~LogMessage();

// Marks this record as verbose so a structured callback can distinguish
// LOG_VERBOSE from plain INFO. Has no effect on the default sink.
LogMessage& SetVerbose()
{
is_verbose_ = true;
return *this;
}

std::stringstream& stream() { return message_; }

private:
Expand All @@ -204,6 +239,7 @@ class LogMessage {
std::stringstream message_;
const char* heading_;
bool escape_log_messages_;
bool is_verbose_ = false;
};

#define LOG_ENABLE_INFO(E) \
Expand All @@ -219,6 +255,7 @@ class LogMessage {
static_cast<uint32_t>(std::max(0, (L))))
#define LOG_SET_OUT_FILE(FN) triton::common::gLogger_.SetLogFile((FN))
#define LOG_SET_FORMAT(F) triton::common::gLogger_.SetLogFormat((F))
#define LOG_SET_CALLBACK(CB) triton::common::gLogger_.SetLogCallback((CB))

#define LOG_VERBOSE_LEVEL triton::common::gLogger_.VerboseLevel()
#define LOG_FORMAT triton::common::gLogger_.LogFormat()
Expand Down Expand Up @@ -265,6 +302,7 @@ class LogMessage {
if (LOG_VERBOSE_IS_ON(L)) \
triton::common::LogMessage( \
(char*)(FN), LN, triton::common::Logger::Level::kINFO) \
.SetVerbose() \
Comment thread
yinggeh marked this conversation as resolved.
.stream()

// Macros that use current filename and line number.
Expand All @@ -286,6 +324,7 @@ class LogMessage {
triton::common::LogMessage( \
__FILE__, __LINE__, triton::common::Logger::Level::kINFO, nullptr, \
false) \
.SetVerbose() \
.stream() \
<< TABLE.PrintTable(); \
} while (false)
Expand All @@ -312,6 +351,7 @@ class LogMessage {
triton::common::LogMessage( \
__FILE__, __LINE__, triton::common::Logger::Level::kINFO, HEADING, \
false) \
.SetVerbose() \
.stream() \
<< PB_MESSAGE.DebugString(); \
} while (false)
Expand Down
34 changes: 33 additions & 1 deletion src/logging.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright 2018-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -38,6 +38,10 @@

namespace triton { namespace common {

namespace {
constexpr uint64_t kMicrosecondsPerSecond = 1000000ULL;
} // namespace

Logger gLogger_;

Logger::Logger()
Expand Down Expand Up @@ -142,6 +146,34 @@ LogMessage::LogPreamble(std::stringstream& stream)

LogMessage::~LogMessage()
{
// If a structured callback is registered, send the raw Triton log record to
// it and skip the default sink. This allows the host to route Triton logs
// through its own logging pipeline as a single, consistent stream.
// The callback receives the unformatted message and structured metadata, and
// is responsible for any formatting or escaping. Invoke it outside the logger
// output mutex so a slow callback does not block all logging. It must never
// throw.
const Logger::LogCallbackFn& callback = gLogger_.LogCallback();
if (callback) {
uint64_t timestamp_us =
static_cast<uint64_t>(timestamp_.tv_sec) * kMicrosecondsPerSecond +
static_cast<uint64_t>(timestamp_.tv_usec);
Comment thread
pskiran1 marked this conversation as resolved.
const std::string message = message_.str();
const std::string raw_message =
(heading_ != nullptr) ? (std::string(heading_) + "\n" + message)
: message;
try {
callback(
level_, is_verbose_, path_.c_str(), line_, timestamp_us,
raw_message.c_str());
}
catch (...) {
// Logging must not fail or terminate the server.
}
return;
}

// Default sink: format the log record and write it to the configured output.
std::stringstream log_record;
LogPreamble(log_record);
std::string escaped_message =
Expand Down
3 changes: 2 additions & 1 deletion src/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2023-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# Copyright 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -39,5 +39,6 @@ FetchContent_MakeAvailable(googletest)

if (TRITON_COMMON_ENABLE_JSON)
Comment thread
yinggeh marked this conversation as resolved.
add_subdirectory(triton_json triton_json)
add_subdirectory(logging logging)
endif()
Comment thread
pskiran1 marked this conversation as resolved.

48 changes: 48 additions & 0 deletions src/test/logging/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

cmake_minimum_required (VERSION 3.31.8)

add_executable(triton-logging-test logging_test.cc)

target_link_libraries(
triton-logging-test
PRIVATE
triton-common-logging
GTest::gtest
GTest::gtest_main
)

set_target_properties(
triton-logging-test
PROPERTIES
OUTPUT_NAME logging_test
)

install(
TARGETS triton-logging-test
RUNTIME DESTINATION bin
)
Loading
Loading