Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
29b0e4a8
Commit
29b0e4a8
authored
Mar 13, 2026
by
Peter
Browse files
feat(ops): allow hiding alert events
parent
af9c4a7d
Changes
8
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/ops_settings.go
View file @
29b0e4a8
...
@@ -372,6 +372,7 @@ func defaultOpsAdvancedSettings() *OpsAdvancedSettings {
...
@@ -372,6 +372,7 @@ func defaultOpsAdvancedSettings() *OpsAdvancedSettings {
IgnoreContextCanceled
:
true
,
// Default to true - client disconnects are not errors
IgnoreContextCanceled
:
true
,
// Default to true - client disconnects are not errors
IgnoreNoAvailableAccounts
:
false
,
// Default to false - this is a real routing issue
IgnoreNoAvailableAccounts
:
false
,
// Default to false - this is a real routing issue
DisplayOpenAITokenStats
:
false
,
DisplayOpenAITokenStats
:
false
,
DisplayAlertEvents
:
true
,
AutoRefreshEnabled
:
false
,
AutoRefreshEnabled
:
false
,
AutoRefreshIntervalSec
:
30
,
AutoRefreshIntervalSec
:
30
,
}
}
...
@@ -439,7 +440,7 @@ func (s *OpsService) GetOpsAdvancedSettings(ctx context.Context) (*OpsAdvancedSe
...
@@ -439,7 +440,7 @@ func (s *OpsService) GetOpsAdvancedSettings(ctx context.Context) (*OpsAdvancedSe
return
nil
,
err
return
nil
,
err
}
}
cfg
:=
&
OpsAdvancedSettings
{}
cfg
:=
default
OpsAdvancedSettings
()
if
err
:=
json
.
Unmarshal
([]
byte
(
raw
),
cfg
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
raw
),
cfg
);
err
!=
nil
{
return
defaultCfg
,
nil
return
defaultCfg
,
nil
}
}
...
...
backend/internal/service/ops_settings_advanced_test.go
View file @
29b0e4a8
...
@@ -2,6 +2,7 @@ package service
...
@@ -2,6 +2,7 @@ package service
import
(
import
(
"context"
"context"
"encoding/json"
"testing"
"testing"
)
)
...
@@ -16,6 +17,9 @@ func TestGetOpsAdvancedSettings_DefaultHidesOpenAITokenStats(t *testing.T) {
...
@@ -16,6 +17,9 @@ func TestGetOpsAdvancedSettings_DefaultHidesOpenAITokenStats(t *testing.T) {
if
cfg
.
DisplayOpenAITokenStats
{
if
cfg
.
DisplayOpenAITokenStats
{
t
.
Fatalf
(
"DisplayOpenAITokenStats = true, want false by default"
)
t
.
Fatalf
(
"DisplayOpenAITokenStats = true, want false by default"
)
}
}
if
!
cfg
.
DisplayAlertEvents
{
t
.
Fatalf
(
"DisplayAlertEvents = false, want true by default"
)
}
if
repo
.
setCalls
!=
1
{
if
repo
.
setCalls
!=
1
{
t
.
Fatalf
(
"expected defaults to be persisted once, got %d"
,
repo
.
setCalls
)
t
.
Fatalf
(
"expected defaults to be persisted once, got %d"
,
repo
.
setCalls
)
}
}
...
@@ -27,6 +31,7 @@ func TestUpdateOpsAdvancedSettings_PersistsOpenAITokenStatsVisibility(t *testing
...
@@ -27,6 +31,7 @@ func TestUpdateOpsAdvancedSettings_PersistsOpenAITokenStatsVisibility(t *testing
cfg
:=
defaultOpsAdvancedSettings
()
cfg
:=
defaultOpsAdvancedSettings
()
cfg
.
DisplayOpenAITokenStats
=
true
cfg
.
DisplayOpenAITokenStats
=
true
cfg
.
DisplayAlertEvents
=
false
updated
,
err
:=
svc
.
UpdateOpsAdvancedSettings
(
context
.
Background
(),
cfg
)
updated
,
err
:=
svc
.
UpdateOpsAdvancedSettings
(
context
.
Background
(),
cfg
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -35,6 +40,9 @@ func TestUpdateOpsAdvancedSettings_PersistsOpenAITokenStatsVisibility(t *testing
...
@@ -35,6 +40,9 @@ func TestUpdateOpsAdvancedSettings_PersistsOpenAITokenStatsVisibility(t *testing
if
!
updated
.
DisplayOpenAITokenStats
{
if
!
updated
.
DisplayOpenAITokenStats
{
t
.
Fatalf
(
"DisplayOpenAITokenStats = false, want true"
)
t
.
Fatalf
(
"DisplayOpenAITokenStats = false, want true"
)
}
}
if
updated
.
DisplayAlertEvents
{
t
.
Fatalf
(
"DisplayAlertEvents = true, want false"
)
}
reloaded
,
err
:=
svc
.
GetOpsAdvancedSettings
(
context
.
Background
())
reloaded
,
err
:=
svc
.
GetOpsAdvancedSettings
(
context
.
Background
())
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -43,4 +51,47 @@ func TestUpdateOpsAdvancedSettings_PersistsOpenAITokenStatsVisibility(t *testing
...
@@ -43,4 +51,47 @@ func TestUpdateOpsAdvancedSettings_PersistsOpenAITokenStatsVisibility(t *testing
if
!
reloaded
.
DisplayOpenAITokenStats
{
if
!
reloaded
.
DisplayOpenAITokenStats
{
t
.
Fatalf
(
"reloaded DisplayOpenAITokenStats = false, want true"
)
t
.
Fatalf
(
"reloaded DisplayOpenAITokenStats = false, want true"
)
}
}
if
reloaded
.
DisplayAlertEvents
{
t
.
Fatalf
(
"reloaded DisplayAlertEvents = true, want false"
)
}
}
func
TestGetOpsAdvancedSettings_BackfillsNewDisplayFlagsFromDefaults
(
t
*
testing
.
T
)
{
repo
:=
newRuntimeSettingRepoStub
()
svc
:=
&
OpsService
{
settingRepo
:
repo
}
legacyCfg
:=
map
[
string
]
any
{
"data_retention"
:
map
[
string
]
any
{
"cleanup_enabled"
:
false
,
"cleanup_schedule"
:
"0 2 * * *"
,
"error_log_retention_days"
:
30
,
"minute_metrics_retention_days"
:
30
,
"hourly_metrics_retention_days"
:
30
,
},
"aggregation"
:
map
[
string
]
any
{
"aggregation_enabled"
:
false
,
},
"ignore_count_tokens_errors"
:
true
,
"ignore_context_canceled"
:
true
,
"ignore_no_available_accounts"
:
false
,
"ignore_invalid_api_key_errors"
:
false
,
"auto_refresh_enabled"
:
false
,
"auto_refresh_interval_seconds"
:
30
,
}
raw
,
err
:=
json
.
Marshal
(
legacyCfg
)
if
err
!=
nil
{
t
.
Fatalf
(
"marshal legacy config: %v"
,
err
)
}
repo
.
values
[
SettingKeyOpsAdvancedSettings
]
=
string
(
raw
)
cfg
,
err
:=
svc
.
GetOpsAdvancedSettings
(
context
.
Background
())
if
err
!=
nil
{
t
.
Fatalf
(
"GetOpsAdvancedSettings() error = %v"
,
err
)
}
if
cfg
.
DisplayOpenAITokenStats
{
t
.
Fatalf
(
"DisplayOpenAITokenStats = true, want false default backfill"
)
}
if
!
cfg
.
DisplayAlertEvents
{
t
.
Fatalf
(
"DisplayAlertEvents = false, want true default backfill"
)
}
}
}
backend/internal/service/ops_settings_models.go
View file @
29b0e4a8
...
@@ -99,6 +99,7 @@ type OpsAdvancedSettings struct {
...
@@ -99,6 +99,7 @@ type OpsAdvancedSettings struct {
IgnoreNoAvailableAccounts
bool
`json:"ignore_no_available_accounts"`
IgnoreNoAvailableAccounts
bool
`json:"ignore_no_available_accounts"`
IgnoreInvalidApiKeyErrors
bool
`json:"ignore_invalid_api_key_errors"`
IgnoreInvalidApiKeyErrors
bool
`json:"ignore_invalid_api_key_errors"`
DisplayOpenAITokenStats
bool
`json:"display_openai_token_stats"`
DisplayOpenAITokenStats
bool
`json:"display_openai_token_stats"`
DisplayAlertEvents
bool
`json:"display_alert_events"`
AutoRefreshEnabled
bool
`json:"auto_refresh_enabled"`
AutoRefreshEnabled
bool
`json:"auto_refresh_enabled"`
AutoRefreshIntervalSec
int
`json:"auto_refresh_interval_seconds"`
AutoRefreshIntervalSec
int
`json:"auto_refresh_interval_seconds"`
}
}
...
...
frontend/src/api/admin/ops.ts
View file @
29b0e4a8
...
@@ -842,6 +842,7 @@ export interface OpsAdvancedSettings {
...
@@ -842,6 +842,7 @@ export interface OpsAdvancedSettings {
ignore_no_available_accounts
:
boolean
ignore_no_available_accounts
:
boolean
ignore_invalid_api_key_errors
:
boolean
ignore_invalid_api_key_errors
:
boolean
display_openai_token_stats
:
boolean
display_openai_token_stats
:
boolean
display_alert_events
:
boolean
auto_refresh_enabled
:
boolean
auto_refresh_enabled
:
boolean
auto_refresh_interval_seconds
:
number
auto_refresh_interval_seconds
:
number
}
}
...
...
frontend/src/i18n/locales/en.ts
View file @
29b0e4a8
...
@@ -3652,6 +3652,8 @@ export default {
...
@@ -3652,6 +3652,8 @@ export default {
refreshInterval30s
:
'
30 seconds
'
,
refreshInterval30s
:
'
30 seconds
'
,
refreshInterval60s
:
'
60 seconds
'
,
refreshInterval60s
:
'
60 seconds
'
,
dashboardCards
:
'
Dashboard Cards
'
,
dashboardCards
:
'
Dashboard Cards
'
,
displayAlertEvents
:
'
Display alert events
'
,
displayAlertEventsHint
:
'
Show or hide the recent alert events card on the ops dashboard. Enabled by default.
'
,
displayOpenAITokenStats
:
'
Display OpenAI token request stats
'
,
displayOpenAITokenStats
:
'
Display OpenAI token request stats
'
,
displayOpenAITokenStatsHint
:
'
Show or hide the OpenAI token request stats card on the ops dashboard. Hidden by default.
'
,
displayOpenAITokenStatsHint
:
'
Show or hide the OpenAI token request stats card on the ops dashboard. Hidden by default.
'
,
autoRefreshCountdown
:
'
Auto refresh: {seconds}s
'
,
autoRefreshCountdown
:
'
Auto refresh: {seconds}s
'
,
...
...
frontend/src/i18n/locales/zh.ts
View file @
29b0e4a8
...
@@ -3826,6 +3826,8 @@ export default {
...
@@ -3826,6 +3826,8 @@ export default {
refreshInterval30s
:
'
30 秒
'
,
refreshInterval30s
:
'
30 秒
'
,
refreshInterval60s
:
'
60 秒
'
,
refreshInterval60s
:
'
60 秒
'
,
dashboardCards
:
'
仪表盘卡片
'
,
dashboardCards
:
'
仪表盘卡片
'
,
displayAlertEvents
:
'
展示告警事件
'
,
displayAlertEventsHint
:
'
控制运维监控仪表盘中告警事件卡片是否显示,默认开启。
'
,
displayOpenAITokenStats
:
'
展示 OpenAI Token 请求统计
'
,
displayOpenAITokenStats
:
'
展示 OpenAI Token 请求统计
'
,
displayOpenAITokenStatsHint
:
'
控制运维监控仪表盘中 OpenAI Token 请求统计卡片是否显示,默认关闭。
'
,
displayOpenAITokenStatsHint
:
'
控制运维监控仪表盘中 OpenAI Token 请求统计卡片是否显示,默认关闭。
'
,
autoRefreshCountdown
:
'
自动刷新:{seconds}s
'
,
autoRefreshCountdown
:
'
自动刷新:{seconds}s
'
,
...
...
frontend/src/views/admin/ops/OpsDashboard.vue
View file @
29b0e4a8
...
@@ -94,7 +94,7 @@
...
@@ -94,7 +94,7 @@
</div>
</div>
<!-- Alert Events -->
<!-- Alert Events -->
<OpsAlertEventsCard
v-if=
"opsEnabled && !(loading && !hasLoadedOnce)"
/>
<OpsAlertEventsCard
v-if=
"opsEnabled &&
showAlertEvents &&
!(loading && !hasLoadedOnce)"
/>
<!-- System Logs -->
<!-- System Logs -->
<OpsSystemLogTable
<OpsSystemLogTable
...
@@ -381,6 +381,7 @@ const showSettingsDialog = ref(false)
...
@@ -381,6 +381,7 @@ const showSettingsDialog = ref(false)
const
showAlertRulesCard
=
ref
(
false
)
const
showAlertRulesCard
=
ref
(
false
)
// Auto refresh settings
// Auto refresh settings
const
showAlertEvents
=
ref
(
true
)
const
showOpenAITokenStats
=
ref
(
false
)
const
showOpenAITokenStats
=
ref
(
false
)
const
autoRefreshEnabled
=
ref
(
false
)
const
autoRefreshEnabled
=
ref
(
false
)
const
autoRefreshIntervalMs
=
ref
(
30000
)
// default 30 seconds
const
autoRefreshIntervalMs
=
ref
(
30000
)
// default 30 seconds
...
@@ -413,12 +414,14 @@ const { pause: pauseCountdown, resume: resumeCountdown } = useIntervalFn(
...
@@ -413,12 +414,14 @@ const { pause: pauseCountdown, resume: resumeCountdown } = useIntervalFn(
async
function
loadDashboardAdvancedSettings
()
{
async
function
loadDashboardAdvancedSettings
()
{
try
{
try
{
const
settings
=
await
opsAPI
.
getAdvancedSettings
()
const
settings
=
await
opsAPI
.
getAdvancedSettings
()
showAlertEvents
.
value
=
settings
.
display_alert_events
showOpenAITokenStats
.
value
=
settings
.
display_openai_token_stats
showOpenAITokenStats
.
value
=
settings
.
display_openai_token_stats
autoRefreshEnabled
.
value
=
settings
.
auto_refresh_enabled
autoRefreshEnabled
.
value
=
settings
.
auto_refresh_enabled
autoRefreshIntervalMs
.
value
=
settings
.
auto_refresh_interval_seconds
*
1000
autoRefreshIntervalMs
.
value
=
settings
.
auto_refresh_interval_seconds
*
1000
autoRefreshCountdown
.
value
=
settings
.
auto_refresh_interval_seconds
autoRefreshCountdown
.
value
=
settings
.
auto_refresh_interval_seconds
}
catch
(
err
)
{
}
catch
(
err
)
{
console
.
error
(
'
[OpsDashboard] Failed to load dashboard advanced settings
'
,
err
)
console
.
error
(
'
[OpsDashboard] Failed to load dashboard advanced settings
'
,
err
)
showAlertEvents
.
value
=
true
showOpenAITokenStats
.
value
=
false
showOpenAITokenStats
.
value
=
false
autoRefreshEnabled
.
value
=
false
autoRefreshEnabled
.
value
=
false
autoRefreshIntervalMs
.
value
=
30000
autoRefreshIntervalMs
.
value
=
30000
...
...
frontend/src/views/admin/ops/components/OpsSettingsDialog.vue
View file @
29b0e4a8
...
@@ -548,6 +548,16 @@ async function saveAllSettings() {
...
@@ -548,6 +548,16 @@ async function saveAllSettings() {
<div
class=
"space-y-3"
>
<div
class=
"space-y-3"
>
<h5
class=
"text-xs font-semibold text-gray-700 dark:text-gray-300"
>
{{
t
(
'
admin.ops.settings.dashboardCards
'
)
}}
</h5>
<h5
class=
"text-xs font-semibold text-gray-700 dark:text-gray-300"
>
{{
t
(
'
admin.ops.settings.dashboardCards
'
)
}}
</h5>
<div
class=
"flex items-center justify-between"
>
<div>
<label
class=
"text-sm font-medium text-gray-700 dark:text-gray-300"
>
{{
t
(
'
admin.ops.settings.displayAlertEvents
'
)
}}
</label>
<p
class=
"mt-1 text-xs text-gray-500"
>
{{
t
(
'
admin.ops.settings.displayAlertEventsHint
'
)
}}
</p>
</div>
<Toggle
v-model=
"advancedSettings.display_alert_events"
/>
</div>
<div
class=
"flex items-center justify-between"
>
<div
class=
"flex items-center justify-between"
>
<div>
<div>
<label
class=
"text-sm font-medium text-gray-700 dark:text-gray-300"
>
{{
t
(
'
admin.ops.settings.displayOpenAITokenStats
'
)
}}
</label>
<label
class=
"text-sm font-medium text-gray-700 dark:text-gray-300"
>
{{
t
(
'
admin.ops.settings.displayOpenAITokenStats
'
)
}}
</label>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment