Stream live server logs over SSE

This commit is contained in:
npc0-hue
2026-08-03 22:28:54 +08:00
parent 5d4fca14f9
commit 7eac1926dd
48 changed files with 1526 additions and 263 deletions
+21 -1
View File
@@ -745,6 +745,11 @@ func (svc *CoreService) QueueLogBackfillForSession(sessionID string, request dom
_ = svc.recordAuditEvent(user.ID, "logs.backfill.denied", "server-instance", instance.ID, domain.AuditResultDenied, "log backfill denied: plugin capability is not declared")
return domain.Job{}, ErrForbidden
}
source, err := declaredFileLogSource(plugin, request.SourceKey)
if err != nil {
_ = svc.recordAuditEvent(user.ID, "logs.backfill.denied", "server-instance", instance.ID, domain.AuditResultDenied, "log backfill denied: log source is not declared")
return domain.Job{}, err
}
if err := svc.requireCompleteRuntimeBindings(user.ID, instance.ID, "logs.backfill.denied"); err != nil {
return domain.Job{}, err
}
@@ -753,10 +758,11 @@ func (svc *CoreService) QueueLogBackfillForSession(sessionID string, request dom
ServerInstanceID: instance.ID,
RunEndpointID: instance.RunEndpointID,
Capability: domain.JobCapabilityLogsBackfill,
TargetKey: "logs/" + request.SourceKey,
TargetKey: "logs/" + source.Key,
InputRef: request.CheckpointRef,
IdempotencyKey: request.IdempotencyKey,
Progress: domain.JobProgress{Percent: 0, Message: "historical log backfill queued"},
ExecutionInput: domain.JobExecutionInput{LogSource: &source},
})
if err != nil {
_ = svc.recordAuditEvent(user.ID, "logs.backfill.denied", "server-instance", instance.ID, domain.AuditResultDenied, "log backfill denied: endpoint unsupported or offline")
@@ -768,6 +774,20 @@ func (svc *CoreService) QueueLogBackfillForSession(sessionID string, request dom
return domain.CopyJob(job), nil
}
func declaredFileLogSource(plugin domain.GamePlugin, sourceKey string) (domain.RuntimeLogSource, error) {
for _, source := range plugin.RuntimeProfiles.LogSources {
if source.Key != sourceKey {
continue
}
if source.Kind != "file.tail" || strings.TrimSpace(source.TargetKey) == "" || strings.TrimSpace(source.StreamKey) == "" {
return domain.RuntimeLogSource{}, validationError("log source must be a file.tail source with target and stream keys")
}
copy := source
return copy, nil
}
return domain.RuntimeLogSource{}, validationError("log source is not declared by plugin")
}
func (svc *CoreService) validateDistributionPluginPermission(actorID string, plugin domain.GamePlugin, serverInstanceID string, permission string, deniedAction string) error {
if plugin.Status != domain.GamePluginStatusInstalled {
_ = svc.recordAuditEvent(actorID, deniedAction, "server-instance", serverInstanceID, domain.AuditResultDenied, "distribution operation denied: plugin is not installed")