* Copyright (c) Huawei Technologies Co., Ltd. 2025-2026. All rights reserved.
* MindIE is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "pylog.h"
#include <Python.h>
#include <frameobject.h>
#include "system_log.h"
using namespace mindie_llm;
namespace FOUNDATION {
PyDoc_STRVAR(LogModuleDoc, "C++ logging bindings based on system_log.");
static void LogLineForPyObject(LogComponent comp, LogSeverity level, LogType type, const char* msg) {
auto& mgr = LogManager::GetInstance();
if (!mgr.IsPrintLog(comp, level)) {
return;
}
const char* filename = "";
size_t lineNum = 0;
PyGILState_STATE gil = PyGILState_Ensure();
PyFrameObject* frame = PyEval_GetFrame();
PyFrameObject* caller = frame ? PyFrame_GetBack(frame) : nullptr;
PyCodeObject* code = caller ? PyFrame_GetCode(caller) : nullptr;
if (code) {
PyObject* pyFile = code->co_filename;
if (pyFile) filename = PyUnicode_AsUTF8(pyFile);
lineNum = static_cast<size_t>(PyFrame_GetLineNumber(caller));
}
Py_XDECREF(code);
Py_XDECREF(caller);
PyGILState_Release(gil);
LogLine line(comp, level, filename, lineNum);
line.SetType(type) << msg;
}
static PyObject* PyLog(PyObject*, PyObject* args, LogSeverity level) {
const char* msg;
const char* compStr;
const char* typeStr = "general";
if (!PyArg_ParseTuple(args, "ss|s", &msg, &compStr, &typeStr)) {
return nullptr;
}
LogComponent comp;
if (!String2Component(compStr, comp)) {
PyErr_Format(PyExc_ValueError, "invalid component: '%s'", compStr);
return nullptr;
}
LogType type;
if (!String2LogType(typeStr, type)) {
PyErr_Format(PyExc_ValueError, "invalid log type: '%s'", typeStr);
return nullptr;
}
LogLineForPyObject(comp, level, type, msg);
Py_RETURN_NONE;
}
static PyObject* PyDebug(PyObject* s, PyObject* a) { return PyLog(s, a, LogSeverity::DEBUG); }
static PyObject* PyInfo(PyObject* s, PyObject* a) { return PyLog(s, a, LogSeverity::INFO); }
static PyObject* PyWarn(PyObject* s, PyObject* a) { return PyLog(s, a, LogSeverity::WARN); }
static PyObject* PyError(PyObject* s, PyObject* a) { return PyLog(s, a, LogSeverity::ERROR); }
static PyObject* PyCritical(PyObject* s, PyObject* a) { return PyLog(s, a, LogSeverity::CRITICAL); }
static PyObject* PyAudit(PyObject* s, PyObject* a) { return PyLog(s, a, LogSeverity::AUDIT); }
static PyObject* PySetLogLevel(PyObject*, PyObject* arg) {
if (!PyUnicode_Check(arg)) {
PyErr_SetString(PyExc_TypeError, "set_log_level(level: str), e.g. 'debug', 'llm:info;llmmodels:warn'");
return nullptr;
}
const char* levelStr = PyUnicode_AsUTF8(arg);
if (levelStr == nullptr) {
return nullptr;
}
const std::string level(levelStr);
LogManager::GetInstance().LoadByComponentByString<LogSeverity>(
level, GetAllLogSeverity(),
[](const std::string& s) {
LogSeverity lvl;
if (!String2LogSeverity(s, lvl)) {
return LogSeverity::INFO;
}
return lvl;
},
[](ComponentConfig& c, LogSeverity v) { c.minLevel = v; });
Py_RETURN_NONE;
}
static PyMethodDef LogMethods[] = {{"debug", PyDebug, METH_VARARGS, "debug(msg, comp, 'general')"},
{"info", PyInfo, METH_VARARGS, "info(msg, comp, 'general')"},
{"warn", PyWarn, METH_VARARGS, "warn(msg, comp, 'general')"},
{"error", PyError, METH_VARARGS, "error(msg, comp, 'general')"},
{"critical", PyCritical, METH_VARARGS, "critical(msg, comp, 'general')"},
{"audit", PyAudit, METH_VARARGS, "audit(msg, comp, 'general')"},
{"set_log_level", PySetLogLevel, METH_O, "set_log_level(level: str)"},
{nullptr, nullptr, 0, nullptr}};
static PyModuleDef g_LogModule = {
PyModuleDef_HEAD_INIT,
"foundation.log",
LogModuleDoc,
-1,
LogMethods,
nullptr,
nullptr,
nullptr,
nullptr
};
PyObject* GetLogModule() { return PyModule_Create(&g_LogModule); }
}