Skip to content

Commit 23f65b4

Browse files
authored
improve service logs (#2)
1 parent fd3ce7a commit 23f65b4

File tree

6 files changed

+69
-14
lines changed

6 files changed

+69
-14
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,5 @@ yarn.lock
5959

6060
# Added by goreleaser init:
6161
dist/
62+
63+
gcx.dev.yaml

app.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sdmanager
22

33
import (
4+
"context"
45
"fmt"
56
"strings"
67

@@ -9,6 +10,10 @@ import (
910

1011
// Создание новой модели приложения
1112
func NewApplication(o AppOptions) AppModel {
13+
if o.ctx == nil {
14+
o.ctx = context.Background()
15+
}
16+
1217
return AppModel{
1318
Mode: ModeMainMenu,
1419
MenuModel: NewMenuModel(),
@@ -86,7 +91,7 @@ func (m AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
8691

8792
case ModeServiceInput:
8893
// Обновляем модель ввода имени сервиса
89-
serviceModel, cmd, err := UpdateServiceInput(msg, m.ServiceInputModel)
94+
serviceModel, cmd, err := UpdateServiceInput(m.options.ctx, msg, m.ServiceInputModel)
9095
m.ServiceInputModel = serviceModel
9196

9297
// Обрабатываем ошибку

app_options.go

+9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package sdmanager
22

3+
import "context"
4+
35
type AppOptions struct {
46
serviceName string
7+
ctx context.Context
58
}
69

710
type AppOption func(*AppOptions)
@@ -11,3 +14,9 @@ func WithServiceName(serviceName string) AppOption {
1114
o.serviceName = serviceName
1215
}
1316
}
17+
18+
func WithContext(ctx context.Context) AppOption {
19+
return func(o *AppOptions) {
20+
o.ctx = ctx
21+
}
22+
}

cmd/sdmanager/main.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package main
22

33
import (
4+
"context"
45
"fmt"
56
"os"
7+
"os/signal"
8+
"syscall"
69

710
"github.com/sxwebdev/sdmanager"
811
)
@@ -20,7 +23,10 @@ func PrintVersion() {
2023
}
2124

2225
func main() {
23-
err := sdmanager.RunSystemdManager()
26+
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL)
27+
defer cancel()
28+
29+
err := sdmanager.RunSystemdManager(sdmanager.WithContext(ctx))
2430
if err != nil {
2531
fmt.Printf("Error: %s\n", err)
2632
os.Exit(1)

service.go

+42-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package sdmanager
22

33
import (
4+
"bufio"
45
"bytes"
6+
"context"
7+
"encoding/json"
58
"errors"
69
"fmt"
710
"os"
@@ -303,20 +306,49 @@ func RestartService(serviceName string) (string, error) {
303306
}
304307

305308
// Выполнение просмотра логов
306-
func ViewServiceLogs(serviceName string) (string, error) {
307-
cmd := exec.Command("journalctl", "-n", "50", "-u", serviceName)
308-
output, err := cmd.CombinedOutput()
309-
outputStr := strings.TrimSpace(string(output))
309+
func ViewServiceLogs(ctx context.Context, serviceName string) error {
310+
cmd := exec.CommandContext(ctx, "journalctl", "-n", "50", "-u", serviceName, "--output=json", "--no-pager")
310311

312+
stdout, err := cmd.StdoutPipe()
311313
if err != nil {
312-
// Если сервис не найден, это не критическая ошибка
313-
if strings.Contains(outputStr, "No journal files") {
314-
return "Логи для сервиса не найдены", nil
315-
}
316-
return "", fmt.Errorf("ошибка при получении логов: %w", err)
314+
return fmt.Errorf("stdout pipe: %w", err)
317315
}
318316

319-
return outputStr, nil
317+
if err := cmd.Start(); err != nil {
318+
return fmt.Errorf("ошибка запуска: %w", err)
319+
}
320+
321+
done := make(chan struct{})
322+
go func() {
323+
scanner := bufio.NewScanner(stdout)
324+
325+
for scanner.Scan() {
326+
jsonLine := scanner.Text()
327+
328+
var entry map[string]interface{}
329+
if err := json.Unmarshal([]byte(jsonLine), &entry); err != nil {
330+
fmt.Fprintf(os.Stderr, "ошибка парсинга JSON: %v\n", err)
331+
continue
332+
}
333+
334+
if message, ok := entry["MESSAGE"].(string); ok {
335+
fmt.Println(message)
336+
}
337+
}
338+
339+
if err := scanner.Err(); err != nil {
340+
fmt.Fprintf(os.Stderr, "ошибка чтения вывода: %v\n", err)
341+
}
342+
343+
close(done)
344+
}()
345+
346+
select {
347+
case <-done:
348+
return cmd.Wait()
349+
case <-ctx.Done():
350+
return cmd.Process.Kill()
351+
}
320352
}
321353

322354
// Полностью установить сервис (создать файл, reload, enable, start)

service_input.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sdmanager
22

33
import (
4+
"context"
45
"strings"
56

67
"github.com/charmbracelet/bubbles/textinput"
@@ -40,7 +41,7 @@ func NewServiceInputModel(action string) ServiceInputModel {
4041
}
4142

4243
// Обработка событий при вводе имени сервиса
43-
func UpdateServiceInput(msg tea.Msg, model ServiceInputModel) (ServiceInputModel, tea.Cmd, error) {
44+
func UpdateServiceInput(ctx context.Context, msg tea.Msg, model ServiceInputModel) (ServiceInputModel, tea.Cmd, error) {
4445
switch msg := msg.(type) {
4546
case tea.KeyMsg:
4647
switch msg.Type {
@@ -75,7 +76,7 @@ func UpdateServiceInput(msg tea.Msg, model ServiceInputModel) (ServiceInputModel
7576
case ActionRestart:
7677
result, err = RestartService(serviceName)
7778
case ActionViewLog:
78-
result, err = ViewServiceLogs(serviceName)
79+
err = ViewServiceLogs(ctx, serviceName)
7980
}
8081

8182
if err != nil {

0 commit comments

Comments
 (0)