feat: Konfigurierbarer Log-Level über LOG_LEVEL-Umgebungsvariable (debug/info/warn/error) hinzugefügt
This commit is contained in:
@@ -126,7 +126,9 @@ func (d *Daemon) syncBirthdaysToCal(ctx context.Context, httpClient webdav.HTTPC
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slog.DebugContext(ctx, "queried existing calendar events", "user", user, "count", len(events))
|
||||
bevs := generateBirthdayEvents(birthdays)
|
||||
slog.DebugContext(ctx, "generated birthday events", "user", user, "count", len(bevs))
|
||||
bevsInSync := make([]int, 0)
|
||||
driftedEvents := make([]string, 0)
|
||||
for _, ev := range events {
|
||||
@@ -145,6 +147,7 @@ func (d *Daemon) syncBirthdaysToCal(ctx context.Context, httpClient webdav.HTTPC
|
||||
}
|
||||
counterDelete, counterAdded := 0, 0
|
||||
for _, v := range driftedEvents {
|
||||
slog.DebugContext(ctx, "removing drifted calendar event", "user", user, "path", v)
|
||||
if err := cl.RemoveAll(ctx, v); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -154,6 +157,7 @@ func (d *Daemon) syncBirthdaysToCal(ctx context.Context, httpClient webdav.HTTPC
|
||||
if slices.Contains(bevsInSync, i) {
|
||||
continue
|
||||
}
|
||||
slog.DebugContext(ctx, "adding calendar event", "user", user, "summary", v.Summary, "start", v.DateTimeStart)
|
||||
p, ic := v.generateICAL(calendarPath, d.notificationEnabled, d.notificationTrigger)
|
||||
_, err := cl.PutCalendarObject(ctx, p, ic)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
@@ -66,6 +67,7 @@ func (d *Daemon) getBirthdays(ctx context.Context, httpClient webdav.HTTPClient,
|
||||
YearKnown: yyyy != 0,
|
||||
Type: ContactTypeBirthday,
|
||||
})
|
||||
slog.DebugContext(ctx, "found birthday contact", "user", user, "name", nn[0].GivenName+" "+nn[0].FamilyName, "date", bdayprop)
|
||||
}
|
||||
{
|
||||
annivprop := v.Card.Value("ANNIVERSARY")
|
||||
@@ -81,9 +83,11 @@ func (d *Daemon) getBirthdays(ctx context.Context, httpClient webdav.HTTPClient,
|
||||
YearKnown: yyyy != 0,
|
||||
Type: ContactTypeAnniversary,
|
||||
})
|
||||
slog.DebugContext(ctx, "found anniversary contact", "user", user, "name", nn[0].GivenName+" "+nn[0].FamilyName, "date", annivprop)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
slog.DebugContext(ctx, "collected contacts with dates", "user", user, "count", len(contacts))
|
||||
return contacts, nil
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ func (d *Daemon) getUserPass(ctx context.Context, username string) (string, erro
|
||||
oldIDs = append(oldIDs, p.ID)
|
||||
}
|
||||
}
|
||||
if len(oldIDs) > 0 {
|
||||
slog.DebugContext(ctx, "removing old app passwords", "user", username, "count", len(oldIDs))
|
||||
}
|
||||
if err := d.mailcowClient.DeleteAppPasswords(ctx, oldIDs); err != nil {
|
||||
return "", fmt.Errorf("error deleting app passwords: %w", err)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,29 @@ type Daemon struct {
|
||||
health *healthState
|
||||
}
|
||||
|
||||
// initLogLevel liest die Umgebungsvariable LOG_LEVEL und konfiguriert den
|
||||
// globalen slog-Logger entsprechend. Gültige Werte: debug, info, warn, error.
|
||||
// Standard: info.
|
||||
func initLogLevel() {
|
||||
var level slog.Level
|
||||
switch strings.ToLower(os.Getenv("LOG_LEVEL")) {
|
||||
case "debug":
|
||||
level = slog.LevelDebug
|
||||
case "warn":
|
||||
level = slog.LevelWarn
|
||||
case "error":
|
||||
level = slog.LevelError
|
||||
default:
|
||||
level = slog.LevelInfo
|
||||
}
|
||||
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
|
||||
Level: level,
|
||||
})))
|
||||
}
|
||||
|
||||
func main() {
|
||||
initLogLevel()
|
||||
|
||||
if len(os.Args) > 1 {
|
||||
switch os.Args[1] {
|
||||
case "cleanup":
|
||||
@@ -68,6 +90,7 @@ func main() {
|
||||
|
||||
func run() error {
|
||||
slog.Info("starting mcbdd", "version", version, "commit", commit, "date", date)
|
||||
slog.Debug("log level configured", "LOG_LEVEL", os.Getenv("LOG_LEVEL"))
|
||||
|
||||
// Signal-Handling für Graceful Shutdown (SIGTERM, SIGINT).
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
@@ -181,6 +204,7 @@ func (d *Daemon) daemonRun() error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching mailboxes: %w", err)
|
||||
}
|
||||
slog.Debug("fetched mailboxes", "count", len(mb))
|
||||
eg := sync.WaitGroup{}
|
||||
for _, m := range mb {
|
||||
eg.Go(func() {
|
||||
@@ -204,8 +228,10 @@ func (d *Daemon) daemonRun() error {
|
||||
|
||||
func (d *Daemon) processUser(ctx context.Context, m mailcow.Mailbox) error {
|
||||
if !m.IsActive() {
|
||||
slog.DebugContext(ctx, "skipping inactive mailbox", "user", m.Username)
|
||||
return nil
|
||||
}
|
||||
slog.DebugContext(ctx, "processing user", "user", m.Username)
|
||||
pass, err := d.getUserPass(ctx, m.Username)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting userpass: %w", err)
|
||||
|
||||
@@ -23,6 +23,7 @@ func (d *Daemon) loadState() error {
|
||||
if err := d.loadFromDisk(&d.userTokens); err != nil {
|
||||
return fmt.Errorf("cant load state v%d: %w", stateVer.Version, err)
|
||||
}
|
||||
slog.Debug("loaded state", "version", stateVer.Version, "users", len(d.userTokens))
|
||||
d.stateUnsaved = true
|
||||
case 1:
|
||||
state := struct {
|
||||
|
||||
@@ -28,6 +28,7 @@ services:
|
||||
# - NOTIFICATION_ENABLED=true
|
||||
# - NOTIFICATION_TIME=08:00
|
||||
# - SYNC_INTERVAL=15m
|
||||
# - LOG_LEVEL=info
|
||||
volumes:
|
||||
- birthdaydaemon:/data
|
||||
|
||||
@@ -63,8 +64,7 @@ docker compose pull birthdaydaemon && docker compose up -d --no-deps birthdaydae
|
||||
| `NOTIFICATION_ENABLED` | Nein | `false` | Aktiviert Kalender-Benachrichtigungen (VALARM) für Geburtstags-Events (`true`/`false`) |
|
||||
| `NOTIFICATION_TIME` | Nein | `08:00` | Uhrzeit der Benachrichtigung im Format `HH:MM` (nur wirksam wenn `NOTIFICATION_ENABLED=true`) |
|
||||
| `STATEFILE` | Nein | `state.json` (im Container: `/data/state.json`) | Pfad zur Zustandsdatei, in der App-Passwörter und der aktuelle Kalendername gespeichert werden |
|
||||
| `SYNC_INTERVAL` | Nein | `15m` | Intervall zwischen den Synchronisationsläufen im Go-Duration-Format (z. B. `10m`, `30m`, `1h`). Mindestwert: `1m`. |
|
||||
|
||||
| `SYNC_INTERVAL` | Nein | `15m` | Intervall zwischen den Synchronisationsläufen im Go-Duration-Format (z. B. `10m`, `30m`, `1h`). Mindestwert: `1m`. || `LOG_LEVEL` | Nein | `info` | Log-Verbosity: `debug`, `info`, `warn` oder `error`. Im `debug`-Modus werden einzelne Kalendereinträge (hinzugefügt/entfernt) und Kontaktdetails geloggt. |
|
||||
## API-Key erstellen
|
||||
|
||||
Den API-Key findet man im Admin-Panel unter Konfiguration → Zugang → Administratordetails bearbeiten → API → Lese-/Schreibzugriff.
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
## Container startet, aber keine Kalender werden erstellt
|
||||
|
||||
1. Logs prüfen: `docker compose logs -f birthdaydaemon`
|
||||
2. Sicherstellen, dass der API-Key **Lese- und Schreibzugriff** hat (nicht nur Lesezugriff).
|
||||
3. Prüfen, ob die Mailbox aktiv ist – inaktive Mailboxen werden übersprungen.
|
||||
2. Für detaillierte Ausgaben `LOG_LEVEL=debug` als Umgebungsvariable setzen – damit werden einzelne Kontakte und Kalendereinträge sichtbar.
|
||||
3. Sicherstellen, dass der API-Key **Lese- und Schreibzugriff** hat (nicht nur Lesezugriff).
|
||||
4. Prüfen, ob die Mailbox aktiv ist – inaktive Mailboxen werden übersprungen.
|
||||
|
||||
## Verbindungsfehler / Timeout
|
||||
|
||||
|
||||
Reference in New Issue
Block a user