核心库新增公共helpers与LogHelper
This commit is contained in:
80
src/Library/LogHelper.php
Normal file
80
src/Library/LogHelper.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Dhd\Micro\Core\Library;
|
||||
|
||||
use Hyperf\Context\ApplicationContext;
|
||||
use Hyperf\Logger\LoggerFactory;
|
||||
use Hyperf\Rpc\Context as RpcContext;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* 统一日志静态入口,支持 trace_id 注入与多通道.
|
||||
*/
|
||||
class LogHelper
|
||||
{
|
||||
public static function error(string $message, array $context = []): void
|
||||
{
|
||||
self::log('error', $message, $context, 'error');
|
||||
}
|
||||
|
||||
public static function warning(string $message, array $context = []): void
|
||||
{
|
||||
self::log('warning', $message, $context);
|
||||
}
|
||||
|
||||
public static function info(string $message, array $context = []): void
|
||||
{
|
||||
self::log('info', $message, $context);
|
||||
}
|
||||
|
||||
public static function debug(string $message, array $context = []): void
|
||||
{
|
||||
self::log('debug', $message, $context);
|
||||
}
|
||||
|
||||
public static function business(string $message, array $context = []): void
|
||||
{
|
||||
self::log('info', $message, $context, 'business');
|
||||
}
|
||||
|
||||
public static function sql(string $sql, array $bindings = [], float $time = 0): void
|
||||
{
|
||||
$message = sprintf('SQL: %s | Bindings: %s | Time: %.2fms', $sql, json_encode($bindings), $time);
|
||||
self::log('debug', $message, [], 'sql');
|
||||
}
|
||||
|
||||
protected static function log(string $level, string $message, array $context = [], string $channel = 'default'): void
|
||||
{
|
||||
$logger = self::getLogger($channel);
|
||||
$enrichedContext = array_merge($context, self::getTraceContext());
|
||||
$logger->log($level, $message, $enrichedContext);
|
||||
}
|
||||
|
||||
protected static function getLogger(string $channel = 'default'): LoggerInterface
|
||||
{
|
||||
$container = ApplicationContext::getContainer();
|
||||
$loggerFactory = $container->get(LoggerFactory::class);
|
||||
return $loggerFactory->get($channel);
|
||||
}
|
||||
|
||||
protected static function getTraceContext(): array
|
||||
{
|
||||
$context = [];
|
||||
|
||||
try {
|
||||
$container = ApplicationContext::getContainer();
|
||||
$rpcContext = $container->get(RpcContext::class);
|
||||
|
||||
$traceId = $rpcContext->get('trace_id');
|
||||
if ($traceId) {
|
||||
$context['trace_id'] = $traceId;
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
// 上下文不可用时静默降级
|
||||
}
|
||||
|
||||
return $context;
|
||||
}
|
||||
}
|
||||
157
src/helpers.php
Normal file
157
src/helpers.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Hyperf\Context\ApplicationContext;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Logger\LoggerFactory;
|
||||
use function Hyperf\Config\config;
|
||||
|
||||
if (! function_exists('getNacosConfig')) {
|
||||
/**
|
||||
* 获取nacos配置.
|
||||
*/
|
||||
function getNacosConfig(string $key, $default = null)
|
||||
{
|
||||
return config('nacos_config.' . $key, $default);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('get_file_domain')) {
|
||||
/**
|
||||
* 获取文件中心域名.
|
||||
*/
|
||||
function get_file_domain()
|
||||
{
|
||||
return getNacosConfig('file_domain', '');
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('c_get')) {
|
||||
function c_get($name)
|
||||
{
|
||||
return ApplicationContext::getContainer()->get($name);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('f_log')) {
|
||||
/**
|
||||
* 程序日志.
|
||||
*/
|
||||
function f_log(string $msg, mixed $data)
|
||||
{
|
||||
$fatory = ApplicationContext::getContainer()->get(LoggerFactory::class);
|
||||
$logger = $fatory->get('log', 'default');
|
||||
$content = [
|
||||
'msg' => $msg,
|
||||
'data' => $data,
|
||||
];
|
||||
$logger->info(json_encode($content, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('f_debug')) {
|
||||
/**
|
||||
* debug日志.
|
||||
*/
|
||||
function f_debug($msg)
|
||||
{
|
||||
$logger = ApplicationContext::getContainer()->get(StdoutLoggerInterface::class);
|
||||
$logger->info((is_array($msg) || is_object($msg)) ? json_encode($msg, JSON_UNESCAPED_UNICODE) : $msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('add_file_domain')) {
|
||||
/**
|
||||
* 为内容中的图片路径添加文件域名.
|
||||
*/
|
||||
function add_file_domain($content, $simple = false, $fileDomain = null)
|
||||
{
|
||||
if (empty($content)) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$fileDomain = $fileDomain ?? get_file_domain() . '/';
|
||||
if ($simple) {
|
||||
if (is_string($content) && preg_match('#^(?:https?:)?//#i', $content)) {
|
||||
return $content;
|
||||
}
|
||||
return $fileDomain . ltrim($content, '/');
|
||||
}
|
||||
|
||||
$content = preg_replace_callback('/<img([^>]*src\s*=\s*["\'])([^"\']*)(["\'][^>]*)>/i', function ($matches) use ($fileDomain) {
|
||||
$prefix = $matches[1];
|
||||
$src = $matches[2];
|
||||
$suffix = $matches[3];
|
||||
|
||||
if ($src === '' || preg_match('#^(?:https?:)?//#i', $src) || str_starts_with($src, 'data:')) {
|
||||
return $matches[0];
|
||||
}
|
||||
$newSrc = rtrim($fileDomain, '/') . '/' . ltrim($src, '/');
|
||||
return '<img' . $prefix . $newSrc . $suffix . '>';
|
||||
}, $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('remove_file_domain')) {
|
||||
/**
|
||||
* 移除内容中图片的文件域名.
|
||||
*/
|
||||
function remove_file_domain($content, $fileDomain = null)
|
||||
{
|
||||
if (empty($content)) {
|
||||
return $content;
|
||||
}
|
||||
$fileDomain = $fileDomain ?? get_file_domain();
|
||||
$fileDomain = $fileDomain ? rtrim($fileDomain, '/') : '';
|
||||
if ($fileDomain === '') {
|
||||
return $content;
|
||||
}
|
||||
$pattern = '#' . preg_quote($fileDomain, '#') . '/+#';
|
||||
return preg_replace($pattern, '', $content);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('copy_file_safely')) {
|
||||
/**
|
||||
* 复制文件到指定路径,若目标目录不存在则递归创建.
|
||||
*/
|
||||
function copy_file_safely($sourceFile, $destinationFile)
|
||||
{
|
||||
$safeLog = function ($msg, $data) {
|
||||
try {
|
||||
f_log($msg, $data);
|
||||
} catch (Throwable $e) {
|
||||
// 忽略日志错误
|
||||
}
|
||||
};
|
||||
|
||||
if (! file_exists($sourceFile)) {
|
||||
$safeLog('源文件不存在', $sourceFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
$destinationDir = dirname($destinationFile);
|
||||
if (! is_dir($destinationDir)) {
|
||||
if (! mkdir($destinationDir, 0755, true)) {
|
||||
$safeLog('无法创建目标目录', $destinationDir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_writable($destinationDir)) {
|
||||
$safeLog('目标目录不可写', $destinationDir);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (copy($sourceFile, $destinationFile)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$error = error_get_last();
|
||||
$safeLog('文件复制失败', $error['message'] ?? '未知错误');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user