refactor(i18n): U22 日志中心组件 i18n 治理 — QuickQueryBar/types-v3/TimeRangePicker/LogRBAC 中文键清零
- QuickQueryBar.tsx: 23 处中文键 → monitor.logCenter.quickQuery.* 语义键
- types-v3.ts: 15 处中文键 → monitor.logCenter.quickQuery.* 语义键 (含 QUICK_TEMPLATES 3 引擎)
- TimeRangePicker.tsx: 13 处中文键 → monitor.timeRangePicker.* 语义键 + 修复 3 个复制粘贴 bug 键
(i18n.t('开启后折叠行仅显示前 500 字预览') 应为 '选择时间范围'/'绝对时间'/'自定义时间范围')
(i18n.t(' > 另存为 <ChevronDown className=') 应为 '相对时间')
- LogRBAC.tsx: 10 处中文键/硬编码 → monitor.logRbac.* 语义键 + 插值键 (scopeCount/deleteConfirm)
- zh/en 新增 68 键对齐 (7038→7098), tsc -b=0, npm build✓ (17.41s), ESLint=0/0/0, 17/17 测试通过
This commit is contained in:
1 parent
fba5fc46b6
commit
a8f6fd190b
6 files changed
+205
-81
No files matched your search
@@ -22,7 +22,7 @@ import i18n from '@/i18n';
|
||||
|
||||
const ROLE_LABEL: Record<string, string> = {
|
||||
viewer: i18n.t('pipeline.viewer'),
|
||||
analyst: i18n.t('分析者'),
|
||||
analyst: i18n.t('monitor.logRbac.analyst'),
|
||||
};
|
||||
|
||||
const ENGINE_LABEL: Record<string, string> = {
|
||||
@@ -108,7 +108,7 @@ export default function LogRBAC() {
|
||||
|
||||
const handleCreate = async () => {
|
||||
if (!newName.trim() || !newCode.trim() || !newPattern.trim()) {
|
||||
toast.error(i18n.t('请填写名称、标识与正则')); return;
|
||||
toast.error(i18n.t('monitor.logRbac.fillRequired')); return;
|
||||
}
|
||||
setSaving(true);
|
||||
try {
|
||||
@@ -147,8 +147,8 @@ export default function LogRBAC() {
|
||||
|
||||
const handleDelete = async (role: LogScopeRole) => {
|
||||
const ok = await _confirm({
|
||||
title: i18n.t('删除权限'),
|
||||
description: `确定删除「${role.name}」?将影响 ${matchCount[role.id]?.length || 0} 个示例范围`,
|
||||
title: i18n.t('monitor.logRbac.deletePermission'),
|
||||
description: i18n.t('monitor.logRbac.deleteConfirm', { name: role.name, count: matchCount[role.id]?.length || 0 }),
|
||||
variant: 'destructive',
|
||||
});
|
||||
if (!ok) return;
|
||||
@@ -165,7 +165,7 @@ export default function LogRBAC() {
|
||||
};
|
||||
|
||||
const handleAssign = async () => {
|
||||
if (!selectedUserId || !assignRoleId) { toast.error(i18n.t('请选择用户和权限')); return; }
|
||||
if (!selectedUserId || !assignRoleId) { toast.error(i18n.t('monitor.logRbac.selectUserAndPermission')); return; }
|
||||
setAssignLoading(true);
|
||||
try {
|
||||
await logRbacApi.assignRole(Number(selectedUserId), {
|
||||
@@ -189,8 +189,8 @@ export default function LogRBAC() {
|
||||
|
||||
const selectedUser = users.find((u) => String(u.id) === selectedUserId);
|
||||
const pageTabs = [
|
||||
{ id: 'roles', label: i18n.t('权限策略'), badge: roles.length || undefined },
|
||||
{ id: 'users', label: i18n.t('用户授权') },
|
||||
{ id: 'roles', label: i18n.t('monitor.logRbac.permissionPolicy'), badge: roles.length || undefined },
|
||||
{ id: 'users', label: i18n.t('monitor.logRbac.userAssignment') },
|
||||
{ id: 'preview', label: i18n.t('pipeline.matchPreview') },
|
||||
];
|
||||
|
||||
@@ -206,7 +206,7 @@ export default function LogRBAC() {
|
||||
onTabChange={setActiveTab}
|
||||
actions={(
|
||||
<Button className="dg-btn-primary" onClick={() => setCreateOpen(true)}>
|
||||
<Plus className="w-4 h-4 mr-1" />新建权限
|
||||
<Plus className="w-4 h-4 mr-1" />{i18n.t('monitor.logRbac.createPermission')}
|
||||
</Button>
|
||||
)}
|
||||
contentClassName="space-y-4"
|
||||
@@ -215,8 +215,8 @@ export default function LogRBAC() {
|
||||
roles.length === 0 ? (
|
||||
<PageEmpty
|
||||
icon={<Shield className="h-10 w-10" />}
|
||||
title={i18n.t('暂无日志权限策略')}
|
||||
description={i18n.t('创建策略并分配给用户后,将按正则限制可查询的索引与 Label 范围')}
|
||||
title={i18n.t('monitor.logRbac.noPolicies')}
|
||||
description={i18n.t('monitor.logRbac.noPoliciesDesc')}
|
||||
action={<Button onClick={() => setCreateOpen(true)}><Plus className="h-4 w-4 mr-1" /> {i18n.t('monitor.logrbactsx.s6058845c')} </Button>}
|
||||
/>
|
||||
) : (
|
||||
@@ -243,7 +243,7 @@ export default function LogRBAC() {
|
||||
className="text-[10px] cursor-pointer border-[var(--dg-border)]"
|
||||
onClick={() => { setActiveTab('preview'); setPreviewRoleId(role.id); }}
|
||||
>
|
||||
{matchCount[role.id]?.length || 0} 个范围
|
||||
{i18n.t('monitor.logRbac.scopeCount', { count: matchCount[role.id]?.length || 0 })}
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-[var(--dg-text-muted)] mt-1 font-mono truncate">
|
||||
@@ -259,7 +259,7 @@ export default function LogRBAC() {
|
||||
<SelectTrigger className="h-7 w-20 text-xs"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="viewer"> {i18n.t('pipeline.viewer')} </SelectItem>
|
||||
<SelectItem value="analyst"> {i18n.t('分析者')} </SelectItem>
|
||||
<SelectItem value="analyst"> {i18n.t('monitor.logRbac.analyst')} </SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Button size="icon" variant="ghost" className="h-7 w-7" onClick={() => handleUpdate(role.id)}><Check className="w-3.5 h-3.5" /></Button>
|
||||
@@ -285,7 +285,7 @@ export default function LogRBAC() {
|
||||
<Card className="dg-card">
|
||||
<CardContent className="p-4 space-y-4">
|
||||
<p className="text-xs text-[var(--dg-text-muted)]">
|
||||
用户未分配任何策略时不拦截(向后兼容);分配后仅允许命中策略的查询。
|
||||
{i18n.t('monitor.logRbac.userPolicyHint')}
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-3 items-end">
|
||||
<div className="space-y-1 flex-1 min-w-[200px]">
|
||||
@@ -302,7 +302,7 @@ export default function LogRBAC() {
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-1 w-48">
|
||||
<Label className="text-xs"> {i18n.t('权限策略')} </Label>
|
||||
<Label className="text-xs"> {i18n.t('monitor.logRbac.permissionPolicy')} </Label>
|
||||
<Select value={assignRoleId} onValueChange={setAssignRoleId}>
|
||||
<SelectTrigger className="h-8 text-sm dg-input"><SelectValue placeholder={i18n.t('kubernetes.hpa.selectPolicy')} /></SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -314,7 +314,7 @@ export default function LogRBAC() {
|
||||
</div>
|
||||
<Button className="h-8" onClick={handleAssign} disabled={assignLoading || !selectedUserId || !assignRoleId}>
|
||||
{assignLoading ? <Loader2 className="w-3.5 h-3.5 mr-1 animate-spin" /> : <UserPlus className="w-3.5 h-3.5 mr-1" />}
|
||||
分配
|
||||
{i18n.t('monitor.logRbac.assign')}
|
||||
</Button>
|
||||
</div>
|
||||
{selectedUser ? (
|
||||
@@ -351,7 +351,7 @@ export default function LogRBAC() {
|
||||
<CardContent className="p-4 space-y-3">
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
<Button variant={previewRoleId === null ? 'secondary' : 'ghost'} size="sm" onClick={() => setPreviewRoleId(null)}>
|
||||
全部 ({SAMPLE_SCOPES.length})
|
||||
{i18n.t('monitor.logRbac.all')} ({SAMPLE_SCOPES.length})
|
||||
</Button>
|
||||
{roles.map((r) => (
|
||||
<Button
|
||||
|
||||
@@ -4,36 +4,36 @@ import i18n from '@/i18n';
|
||||
|
||||
const ALL_TEMPLATES: Record<'loki' | 'elasticsearch', { label: string; query: string }[]> = {
|
||||
loki: [
|
||||
{ label: i18n.t('Nginx 错误'), query: '{job="nginx"} |= "error"' },
|
||||
{ label: i18n.t('JSON 过滤'), query: '{namespace="prod"} | json | level="warn"' },
|
||||
{ label: i18n.t('超时搜索'), query: '{app="api"} |= "timeout"' },
|
||||
{ label: i18n.t('级别统计'), query: 'sum by(level) (count_over_time({job="app"}[5m]))' },
|
||||
{ label: i18n.t('正则多级别'), query: '{container="frontend"} |~ "ERROR|WARN|FATAL"' },
|
||||
{ label: i18n.t('慢请求>1s'), query: '{job="api"} | json | response_time > 1000' },
|
||||
{ label: i18n.t('错误率统计'), query: 'sum by(level) (count_over_time({app="cex-admin-api"} |= "error" [5m]))' },
|
||||
{ label: i18n.t('追踪ID查询'), query: '{app="cex-admin-api"} |= "trace_id" | json' },
|
||||
{ label: i18n.t('错误率统计'), query: 'sum by(service_name) (count_over_time({namespace="astralx"}[5m]))' },
|
||||
{ label: i18n.t('高延迟筛选'), query: '{app="cex-admin-api"} | json | response_time > 500' },
|
||||
{ label: i18n.t('异常堆栈'), query: '{app="cex-admin-api"} |= "Exception"' },
|
||||
{ label: i18n.t('monitor.logTrend'), query: 'sum(count_over_time({app="cex-admin-api"}[1h]))' },
|
||||
{ label: i18n.t('正则提取'), query: '{app="cex-admin-api"} | regexp "(?P<method>[A-Za-z0-9_]+) (?P<path>[^ ]+)"' },
|
||||
{ label: i18n.t('格式输出'), query: '{app="cex-admin-api"} | json | line_format "{{.level}} {{.message}}"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.nginxError'), query: '{job="nginx"} |= "error"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.jsonFilter'), query: '{namespace="prod"} | json | level="warn"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.timeoutSearch'), query: '{app="api"} |= "timeout"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.levelStats'), query: 'sum by(level) (count_over_time({job="app"}[5m]))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.regexMultiLevel'), query: '{container="frontend"} |~ "ERROR|WARN|FATAL"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.slowRequest1s'), query: '{job="api"} | json | response_time > 1000' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.errorRateStats'), query: 'sum by(level) (count_over_time({app="cex-admin-api"} |= "error" [5m]))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.traceIdQuery'), query: '{app="cex-admin-api"} |= "trace_id" | json' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.errorRateStats'), query: 'sum by(service_name) (count_over_time({namespace="astralx"}[5m]))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.highLatencyFilter'), query: '{app="cex-admin-api"} | json | response_time > 500' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.exceptionStack'), query: '{app="cex-admin-api"} |= "Exception"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.errorRateStats'), query: 'sum(count_over_time({app="cex-admin-api"}[1h]))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.regexExtract'), query: '{app="cex-admin-api"} | regexp "(?P<method>[A-Za-z0-9_]+) (?P<path>[^ ]+)"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.formatOutput'), query: '{app="cex-admin-api"} | json | line_format "{{.level}} {{.message}}"' },
|
||||
],
|
||||
elasticsearch: [
|
||||
{ label: 'API 5xx', query: 'status:500 AND path:"/api/*"' },
|
||||
{ label: i18n.t('错误超时'), query: '(level:error OR log.level:error) AND message:*timeout*' },
|
||||
{ label: i18n.t('排除调试'), query: 'host.name:server-* AND NOT level:debug' },
|
||||
{ label: i18n.t('慢请求'), query: 'response_time:>1000 AND method:POST' },
|
||||
{ label: i18n.t('严重错误'), query: '@timestamp:[now-1h TO now] AND (level:critical OR log.level:critical)' },
|
||||
{ label: i18n.t('严重错误'), query: 'service:nginx AND (level:(error OR fatal) OR log.level:(error OR fatal))' },
|
||||
{ label: i18n.t('组合查询'), query: 'app:cex-admin-api AND (level:(error OR warn) OR log.level:(error OR warn))' },
|
||||
{ label: i18n.t('模糊匹配'), query: 'message:*timeout* AND app:cex-admin-api' },
|
||||
{ label: i18n.t('范围查询'), query: 'response_time:[1000 TO *] AND method:POST' },
|
||||
{ label: i18n.t('排除路径'), query: 'app:cex-admin-api AND NOT path:/health' },
|
||||
{ label: i18n.t('时间过滤'), query: '@timestamp:[now-1h TO now] AND level:error' },
|
||||
{ label: i18n.t('IP段过滤'), query: 'client_ip:172.36.* AND app:cex-admin-api' },
|
||||
{ label: i18n.t('多级别筛选'), query: 'app:cex-admin-api AND (level:(error OR warn OR info) OR log.level:(error OR warn OR info))' },
|
||||
{ label: i18n.t('嵌套字段'), query: 'labels.orgId:10001 AND app:cex-admin-api' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.esErrorTimeout'), query: '(level:error OR log.level:error) AND message:*timeout*' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.excludeDebug'), query: 'host.name:server-* AND NOT level:debug' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.slowRequest'), query: 'response_time:>1000 AND method:POST' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.criticalError'), query: '@timestamp:[now-1h TO now] AND (level:critical OR log.level:critical)' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.criticalError'), query: 'service:nginx AND (level:(error OR fatal) OR log.level:(error OR fatal))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.combinedQuery'), query: 'app:cex-admin-api AND (level:(error OR warn) OR log.level:(error OR warn))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.fuzzyMatch'), query: 'message:*timeout* AND app:cex-admin-api' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.rangeQuery'), query: 'response_time:[1000 TO *] AND method:POST' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.excludePath'), query: 'app:cex-admin-api AND NOT path:/health' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.timeFilter'), query: '@timestamp:[now-1h TO now] AND level:error' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.ipSegmentFilter'), query: 'client_ip:172.36.* AND app:cex-admin-api' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.multiLevelFilter'), query: 'app:cex-admin-api AND (level:(error OR warn OR info) OR log.level:(error OR warn OR info))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.nestedField'), query: 'labels.orgId:10001 AND app:cex-admin-api' },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -46,7 +46,7 @@ export function QuickQueryBar({ engine, onSelect }: { engine: 'loki' | 'elastics
|
||||
<div>
|
||||
<button onClick={() => setOpen(!open)} className="flex items-center gap-1 text-[11px] px-2 py-1 rounded transition-colors" style={{ color: 'var(--dg-blue)', background: open ? 'var(--dg-bg-tertiary)' : 'transparent' }}>
|
||||
<span className="w-1.5 h-1.5 rounded-full" style={{ background: 'var(--dg-blue)' }} />
|
||||
{labels[engine]} 快捷查询模板
|
||||
{labels[engine]} {i18n.t('monitor.logCenter.quickQuery.quickTemplates')}
|
||||
<ChevronDown className="h-3 w-3" style={{ transform: open ? 'rotate(0deg)' : 'rotate(-90deg)', transition: 'transform 0.2s' }} />
|
||||
</button>
|
||||
{open && (
|
||||
|
||||
@@ -6,27 +6,27 @@ import i18n from '@/i18n';
|
||||
|
||||
// 相对时间预设:最近N... 每次点击时计算 start = now - N // Logan.Li
|
||||
const RELATIVE_PRESETS = [
|
||||
{ label: i18n.t('最近1分钟'), value: '1m' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.range1min'), value: '1m' },
|
||||
{ label: i18n.t('monitor.logPanel.last5min'), value: '5m' },
|
||||
{ label: i18n.t('最近15分钟'), value: '15m' },
|
||||
{ label: i18n.t('最近1小时'), value: '1h' },
|
||||
{ label: i18n.t('最近4小时'), value: '4h' },
|
||||
{ label: i18n.t('最近1天'), value: '24h' },
|
||||
{ label: i18n.t('最近1周'), value: '7d' },
|
||||
{ label: i18n.t('最近30天'), value: '30d' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.range15min'), value: '15m' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.range1hour'), value: '1h' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.range4hours'), value: '4h' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.range1day'), value: '24h' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.range1week'), value: '7d' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.range30days'), value: '30d' },
|
||||
];
|
||||
|
||||
// 绝对时间预设:固定的自然日/周/月/季/年 // Logan.Li
|
||||
const ABSOLUTE_PRESETS = [
|
||||
{ label: i18n.t('audit.terminal.presetToday'), value: 'today' },
|
||||
{ label: i18n.t('common.yesterday'), value: 'yesterday' },
|
||||
{ label: i18n.t('前天'), value: 'day_before_yesterday' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.dayBeforeYesterday'), value: 'day_before_yesterday' },
|
||||
{ label: i18n.t('common.thisWeek'), value: 'this_week' },
|
||||
{ label: i18n.t('common.lastWeek'), value: 'last_week' },
|
||||
{ label: i18n.t('cloud.thisMonth'), value: 'this_month' },
|
||||
{ label: i18n.t('common.lastMonth'), value: 'last_month' },
|
||||
{ label: i18n.t('本季度'), value: 'this_quarter' },
|
||||
{ label: i18n.t('本年度'), value: 'this_year' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.thisQuarter'), value: 'this_quarter' },
|
||||
{ label: i18n.t('monitor.timeRangePicker.thisYear'), value: 'this_year' },
|
||||
];
|
||||
|
||||
function getPresetRange(value: string): { start: Date; end: Date; label: string } {
|
||||
@@ -136,7 +136,7 @@ export function TimeRangePicker({ value, onChange }: Props) {
|
||||
{/* 头部 */}
|
||||
<div className="flex items-center gap-2 mb-3 pb-3" style={{ borderBottom: '1px solid var(--dg-border)' }}>
|
||||
<Calendar className="h-4 w-4" style={{ color: 'var(--dg-blue)' }} />
|
||||
<span className="text-sm font-medium" style={{ color: 'var(--dg-text-primary)' }}> {i18n.t('开启后折叠行仅显示前 500 字预览')} </span>
|
||||
<span className="text-sm font-medium" style={{ color: 'var(--dg-text-primary)' }}> {i18n.t('monitor.timeRangePicker.selectTimeRange')} </span>
|
||||
<button
|
||||
onClick={openCustom}
|
||||
className="text-xs ml-2 px-2 py-0.5 rounded transition-colors"
|
||||
@@ -152,7 +152,7 @@ export function TimeRangePicker({ value, onChange }: Props) {
|
||||
{mode === 'preset' ? (
|
||||
<>
|
||||
{/* 相对时间 — 最近... */}
|
||||
<p className="text-[10px] mb-2 font-medium uppercase tracking-wide" style={{ color: '#22c55e' }}> {i18n.t(' /> 另存为 <ChevronDown className=')} </p>
|
||||
<p className="text-[10px] mb-2 font-medium uppercase tracking-wide" style={{ color: '#22c55e' }}> {i18n.t('monitor.timeRangePicker.relativeTime')} </p>
|
||||
<div className="grid grid-cols-4 gap-1.5 mb-3">
|
||||
{RELATIVE_PRESETS.map(p => (
|
||||
<button
|
||||
@@ -171,7 +171,7 @@ export function TimeRangePicker({ value, onChange }: Props) {
|
||||
</div>
|
||||
|
||||
{/* 绝对时间 — 固定日历范围 */}
|
||||
<p className="text-[10px] mb-2 font-medium uppercase tracking-wide" style={{ color: 'var(--dg-blue)' }}> {i18n.t('开启后折叠行仅显示前 500 字预览')} </p>
|
||||
<p className="text-[10px] mb-2 font-medium uppercase tracking-wide" style={{ color: 'var(--dg-blue)' }}> {i18n.t('monitor.timeRangePicker.absoluteTime')} </p>
|
||||
<div className="grid grid-cols-5 gap-1.5">
|
||||
{ABSOLUTE_PRESETS.map(p => (
|
||||
<button
|
||||
@@ -192,7 +192,7 @@ export function TimeRangePicker({ value, onChange }: Props) {
|
||||
) : (
|
||||
/* 自定义日历模式 */
|
||||
<div className="space-y-3">
|
||||
<p className="text-[10px] font-medium uppercase" style={{ color: 'var(--dg-blue)' }}> {i18n.t('开启后折叠行仅显示前 500 字预览')} </p>
|
||||
<p className="text-[10px] font-medium uppercase" style={{ color: 'var(--dg-blue)' }}> {i18n.t('monitor.timeRangePicker.customTimeRange')} </p>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="text-[10px] block mb-1" style={{ color: 'var(--dg-text-muted)' }}> {i18n.t('system.terminalStartTime')} </label>
|
||||
|
||||
@@ -134,7 +134,7 @@ export const ENGINE_META: Record<LogEngine, { name: string; color: string; query
|
||||
color: '#f97316',
|
||||
queryPlaceholder: 'keyword | SELECT * WHERE level = "info"',
|
||||
statPlaceholder: '* | SELECT level, COUNT(*) as cnt GROUP BY level',
|
||||
externalLink: i18n.t('SLS控制台'),
|
||||
externalLink: i18n.t('monitor.logCenter.quickQuery.slsConsole'),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -250,27 +250,27 @@ export const savedQueryStorage = {
|
||||
// 快捷查询模板 // Logan.Li
|
||||
export const QUICK_TEMPLATES: Record<LogEngine, { label: string; query: string }[]> = {
|
||||
loki: [
|
||||
{ label: i18n.t('Nginx 错误日志'), query: '{job="nginx"} |= "error"' },
|
||||
{ label: i18n.t('JSON 解析过滤'), query: '{namespace="prod"} | json | level="warn"' },
|
||||
{ label: i18n.t('超时搜索'), query: '{app="api"} |= "timeout"' },
|
||||
{ label: i18n.t('按级别统计'), query: 'sum by (level) (count_over_time({job="app"}[5m]))' },
|
||||
{ label: i18n.t('正则匹配多级别'), query: '{container="frontend"} |~ "ERROR|WARN|FATAL"' },
|
||||
{ label: i18n.t('慢请求 >1s'), query: '{job="api"} | json | response_time > 1000' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.nginxErrorLog'), query: '{job="nginx"} |= "error"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.jsonParseFilter'), query: '{namespace="prod"} | json | level="warn"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.timeoutSearch'), query: '{app="api"} |= "timeout"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.statsByLevel'), query: 'sum by (level) (count_over_time({job="app"}[5m]))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.regexMultiLevelMatch'), query: '{container="frontend"} |~ "ERROR|WARN|FATAL"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.slowRequestGt1s'), query: '{job="api"} | json | response_time > 1000' },
|
||||
],
|
||||
elasticsearch: [
|
||||
{ label: i18n.t('API 5xx 错误'), query: 'status:500 AND path:"/api/*"' },
|
||||
{ label: i18n.t('错误超时日志'), query: '(level:error OR log.level:error) AND message:*timeout*' },
|
||||
{ label: i18n.t('排除调试日志'), query: 'host.name:server-* AND NOT level:debug AND NOT log.level:debug' },
|
||||
{ label: i18n.t('慢请求检测'), query: 'response_time:>1000 AND method:POST' },
|
||||
{ label: i18n.t('最近1小时严重错误'), query: '@timestamp:[now-1h TO now] AND (level:critical OR log.level:critical)' },
|
||||
{ label: i18n.t('最近1小时严重错误'), query: 'service:nginx AND (level:(error OR fatal) OR log.level:(error OR fatal))' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.api5xxError'), query: 'status:500 AND path:"/api/*"' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.errorTimeoutLog'), query: '(level:error OR log.level:error) AND message:*timeout*' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.excludeDebugLog'), query: 'host.name:server-* AND NOT level:debug AND NOT log.level:debug' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.slowRequestDetect'), query: 'response_time:>1000 AND method:POST' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.lastHourCritical'), query: '@timestamp:[now-1h TO now] AND (level:critical OR log.level:critical)' },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.lastHourCritical'), query: 'service:nginx AND (level:(error OR fatal) OR log.level:(error OR fatal))' },
|
||||
],
|
||||
sls: [
|
||||
{ label: i18n.t('错误日志筛选'), query: "* | select * where level = 'error'" },
|
||||
{ label: i18n.t('按级别统计'), query: "* | select count(*) as cnt, level group by level" },
|
||||
{ label: i18n.t('时间聚合'), query: "* | select date_trunc('minute', __time__) as t, count(*) group by t order by t" },
|
||||
{ label: i18n.t('状态码分布'), query: "* | select method, count(*) as cnt, avg(response_time) group by method order by cnt desc" },
|
||||
{ label: i18n.t('慢请求分析'), query: "* | select * where response_time > 1000 order by response_time desc limit 100" },
|
||||
{ label: i18n.t('状态码分布'), query: "* | select status_code, count(*) as cnt, count(*) * 100.0 / sum(count(*)) over() as pct group by status_code" },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.errorLogFilter'), query: "* | select * where level = 'error'" },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.statsByLevel'), query: "* | select count(*) as cnt, level group by level" },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.timeAggregate'), query: "* | select date_trunc('minute', __time__) as t, count(*) group by t order by t" },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.statusCodeDist'), query: "* | select method, count(*) as cnt, avg(response_time) group by method order by cnt desc" },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.slowRequestAnalysis'), query: "* | select * where response_time > 1000 order by response_time desc limit 100" },
|
||||
{ label: i18n.t('monitor.logCenter.quickQuery.statusCodeDist'), query: "* | select status_code, count(*) as cnt, count(*) * 100.0 / sum(count(*)) over() as pct group by status_code" },
|
||||
],
|
||||
};
|
||||
@@ -3263,7 +3263,49 @@
|
||||
"alerts": "Log Alerts",
|
||||
"alertsDesc": "Log alert policies based on query conditions",
|
||||
"rbac": "Log Permissions",
|
||||
"rbacDesc": "Restrict query scope by ES index / Loki Label regex"
|
||||
"rbacDesc": "Restrict query scope by ES index / Loki Label regex",
|
||||
"quickQuery": {
|
||||
"quickTemplates": "Quick Query Templates",
|
||||
"slsConsole": "SLS Console",
|
||||
"nginxError": "Nginx Errors",
|
||||
"jsonFilter": "JSON Filter",
|
||||
"timeoutSearch": "Timeout Search",
|
||||
"levelStats": "Level Stats",
|
||||
"regexMultiLevel": "Regex Multi-Level",
|
||||
"slowRequest1s": "Slow Requests >1s",
|
||||
"errorRateStats": "Error Rate Stats",
|
||||
"traceIdQuery": "Trace ID Query",
|
||||
"highLatencyFilter": "High Latency Filter",
|
||||
"exceptionStack": "Exception Stack",
|
||||
"regexExtract": "Regex Extract",
|
||||
"formatOutput": "Format Output",
|
||||
"esErrorTimeout": "Error & Timeout",
|
||||
"excludeDebug": "Exclude Debug",
|
||||
"slowRequest": "Slow Requests",
|
||||
"criticalError": "Critical Errors",
|
||||
"combinedQuery": "Combined Query",
|
||||
"fuzzyMatch": "Fuzzy Match",
|
||||
"rangeQuery": "Range Query",
|
||||
"excludePath": "Exclude Paths",
|
||||
"timeFilter": "Time Filter",
|
||||
"ipSegmentFilter": "IP Segment Filter",
|
||||
"multiLevelFilter": "Multi-Level Filter",
|
||||
"nestedField": "Nested Field",
|
||||
"nginxErrorLog": "Nginx Error Logs",
|
||||
"jsonParseFilter": "JSON Parse Filter",
|
||||
"statsByLevel": "Stats by Level",
|
||||
"regexMultiLevelMatch": "Regex Multi-Level Match",
|
||||
"slowRequestGt1s": "Slow Requests >1s",
|
||||
"api5xxError": "API 5xx Errors",
|
||||
"errorTimeoutLog": "Error Timeout Logs",
|
||||
"excludeDebugLog": "Exclude Debug Logs",
|
||||
"slowRequestDetect": "Slow Request Detection",
|
||||
"lastHourCritical": "Last Hour Critical Errors",
|
||||
"errorLogFilter": "Error Log Filter",
|
||||
"timeAggregate": "Time Aggregation",
|
||||
"statusCodeDist": "Status Code Distribution",
|
||||
"slowRequestAnalysis": "Slow Request Analysis"
|
||||
}
|
||||
},
|
||||
"alertEvents": {
|
||||
"searchPlaceholder": "Search alert name or target...",
|
||||
@@ -4388,7 +4430,11 @@
|
||||
"thisMonth": "This month",
|
||||
"lastMonth": "Last month",
|
||||
"thisQuarter": "This quarter",
|
||||
"thisYear": "This year"
|
||||
"thisYear": "This year",
|
||||
"selectTimeRange": "Select Time Range",
|
||||
"relativeTime": "Relative Time",
|
||||
"absoluteTime": "Absolute Time",
|
||||
"customTimeRange": "Custom Time Range"
|
||||
},
|
||||
"channel": {
|
||||
"dingtalk": "DingTalk",
|
||||
@@ -4430,6 +4476,22 @@
|
||||
"perPage": "/page",
|
||||
"prevPage": "Prev",
|
||||
"nextPage": "Next"
|
||||
},
|
||||
"logRbac": {
|
||||
"analyst": "Analyst",
|
||||
"fillRequired": "Please fill in name, code and regex pattern",
|
||||
"deletePermission": "Delete Permission",
|
||||
"deleteConfirm": "Delete \"{{name}}\"? This will affect {{count}} sample scopes",
|
||||
"selectUserAndPermission": "Please select user and permission",
|
||||
"permissionPolicy": "Permission Policy",
|
||||
"userAssignment": "User Assignment",
|
||||
"createPermission": "New Permission",
|
||||
"noPolicies": "No log permission policies",
|
||||
"noPoliciesDesc": "After creating and assigning policies to users, queryable indices and labels will be restricted by regex patterns",
|
||||
"scopeCount": "{{count}} scopes",
|
||||
"userPolicyHint": "Users without any policy are not blocked (backward compatible); once assigned, only queries matching policies are allowed.",
|
||||
"assign": "Assign",
|
||||
"all": "All"
|
||||
}
|
||||
},
|
||||
"task": {
|
||||
|
||||
@@ -3263,7 +3263,49 @@
|
||||
"alerts": "日志告警",
|
||||
"alertsDesc": "基于查询条件的日志告警策略",
|
||||
"rbac": "日志权限",
|
||||
"rbacDesc": "按 ES 索引 / Loki Label 正则限制查询范围"
|
||||
"rbacDesc": "按 ES 索引 / Loki Label 正则限制查询范围",
|
||||
"quickQuery": {
|
||||
"quickTemplates": "快捷查询模板",
|
||||
"slsConsole": "SLS控制台",
|
||||
"nginxError": "Nginx 错误",
|
||||
"jsonFilter": "JSON 过滤",
|
||||
"timeoutSearch": "超时搜索",
|
||||
"levelStats": "级别统计",
|
||||
"regexMultiLevel": "正则多级别",
|
||||
"slowRequest1s": "慢请求>1s",
|
||||
"errorRateStats": "错误率统计",
|
||||
"traceIdQuery": "追踪ID查询",
|
||||
"highLatencyFilter": "高延迟筛选",
|
||||
"exceptionStack": "异常堆栈",
|
||||
"regexExtract": "正则提取",
|
||||
"formatOutput": "格式输出",
|
||||
"esErrorTimeout": "错误超时",
|
||||
"excludeDebug": "排除调试",
|
||||
"slowRequest": "慢请求",
|
||||
"criticalError": "严重错误",
|
||||
"combinedQuery": "组合查询",
|
||||
"fuzzyMatch": "模糊匹配",
|
||||
"rangeQuery": "范围查询",
|
||||
"excludePath": "排除路径",
|
||||
"timeFilter": "时间过滤",
|
||||
"ipSegmentFilter": "IP段过滤",
|
||||
"multiLevelFilter": "多级别筛选",
|
||||
"nestedField": "嵌套字段",
|
||||
"nginxErrorLog": "Nginx 错误日志",
|
||||
"jsonParseFilter": "JSON 解析过滤",
|
||||
"statsByLevel": "按级别统计",
|
||||
"regexMultiLevelMatch": "正则匹配多级别",
|
||||
"slowRequestGt1s": "慢请求 >1s",
|
||||
"api5xxError": "API 5xx 错误",
|
||||
"errorTimeoutLog": "错误超时日志",
|
||||
"excludeDebugLog": "排除调试日志",
|
||||
"slowRequestDetect": "慢请求检测",
|
||||
"lastHourCritical": "最近1小时严重错误",
|
||||
"errorLogFilter": "错误日志筛选",
|
||||
"timeAggregate": "时间聚合",
|
||||
"statusCodeDist": "状态码分布",
|
||||
"slowRequestAnalysis": "慢请求分析"
|
||||
}
|
||||
},
|
||||
"alertEvents": {
|
||||
"searchPlaceholder": "搜索告警名称或目标...",
|
||||
@@ -4388,7 +4430,11 @@
|
||||
"thisMonth": "本月",
|
||||
"lastMonth": "上月",
|
||||
"thisQuarter": "本季度",
|
||||
"thisYear": "本年度"
|
||||
"thisYear": "本年度",
|
||||
"selectTimeRange": "选择时间范围",
|
||||
"relativeTime": "相对时间",
|
||||
"absoluteTime": "绝对时间",
|
||||
"customTimeRange": "自定义时间范围"
|
||||
},
|
||||
"channel": {
|
||||
"dingtalk": "钉钉",
|
||||
@@ -4430,6 +4476,22 @@
|
||||
"perPage": "/页",
|
||||
"prevPage": "上一页",
|
||||
"nextPage": "下一页"
|
||||
},
|
||||
"logRbac": {
|
||||
"analyst": "分析者",
|
||||
"fillRequired": "请填写名称、标识与正则",
|
||||
"deletePermission": "删除权限",
|
||||
"deleteConfirm": "确定删除「{{name}}」?将影响 {{count}} 个示例范围",
|
||||
"selectUserAndPermission": "请选择用户和权限",
|
||||
"permissionPolicy": "权限策略",
|
||||
"userAssignment": "用户授权",
|
||||
"createPermission": "新建权限",
|
||||
"noPolicies": "暂无日志权限策略",
|
||||
"noPoliciesDesc": "创建策略并分配给用户后,将按正则限制可查询的索引与 Label 范围",
|
||||
"scopeCount": "{{count}} 个范围",
|
||||
"userPolicyHint": "用户未分配任何策略时不拦截(向后兼容);分配后仅允许命中策略的查询。",
|
||||
"assign": "分配",
|
||||
"all": "全部"
|
||||
}
|
||||
},
|
||||
"task": {
|
||||
|
||||
Reference in new issue
Block a user