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:
attacker committed 2026-07-11 15:15:47 +08:00
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" },
],
};