mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
133 lines
3.6 KiB
Go
133 lines
3.6 KiB
Go
package machine
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/psviderski/uncloud/internal/cli"
|
|
"github.com/psviderski/uncloud/internal/cli/logs"
|
|
"github.com/psviderski/uncloud/internal/journal"
|
|
"github.com/psviderski/uncloud/pkg/api"
|
|
"github.com/psviderski/uncloud/pkg/client"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func NewLogsCommand() *cobra.Command {
|
|
var options logs.Options
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "logs [SERVICE...]",
|
|
Aliases: []string{"log"},
|
|
Short: "View systemd service logs.",
|
|
Long: `View logs from the specified systemd service(s) across all machines in the cluster.
|
|
Use -m to restrict to specific machines.
|
|
|
|
Supported services:
|
|
uncloud the Uncloud daemon
|
|
docker the Docker daemon
|
|
uncloud-corrosion the Corrosion distributed state store
|
|
|
|
If no services are specified, streams logs from the uncloud service.`,
|
|
Example: ` # View recent logs for the uncloud service.
|
|
uc machine logs
|
|
uc machine logs uncloud
|
|
|
|
# Stream logs in real-time (follow mode).
|
|
uc machine logs -f uncloud
|
|
|
|
# View logs from multiple services.
|
|
uc machine logs uncloud docker uncloud-corrosion
|
|
|
|
# Show last 20 lines per machine (default is 100).
|
|
uc machine logs -n 20 docker
|
|
|
|
# Show all logs without line limit.
|
|
uc machine logs -n all docker
|
|
|
|
# View logs from a specific time range.
|
|
uc machine logs --since 3h --until 1h30m docker
|
|
|
|
# View logs only from specific machines.
|
|
uc machine logs -m machine1,machine2 uncloud uncloud-corrosion`,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
uncli := cmd.Context().Value("cli").(*cli.CLI)
|
|
return runLogs(cmd.Context(), uncli, args, options)
|
|
},
|
|
}
|
|
|
|
cmd.Flags().AddFlagSet(logs.Flags(&options))
|
|
return cmd
|
|
}
|
|
|
|
func runLogs(ctx context.Context, uncli *cli.CLI, units []string, opts logs.Options) error {
|
|
if len(units) == 0 {
|
|
units = []string{journal.UnitUncloud}
|
|
}
|
|
|
|
for _, unit := range units {
|
|
if !journal.ValidUnit(unit) {
|
|
return fmt.Errorf("invalid systemd service '%s'", unit)
|
|
}
|
|
}
|
|
|
|
tail, err := logs.Tail(opts.Tail)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c, err := uncli.ConnectCluster(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("connect to cluster: %w", err)
|
|
}
|
|
defer c.Close()
|
|
|
|
logsOpts := api.ServiceLogsOptions{
|
|
Follow: opts.Follow,
|
|
Tail: tail,
|
|
Since: opts.Since,
|
|
Until: opts.Until,
|
|
Machines: cli.ExpandCommaSeparatedValues(opts.Machines),
|
|
}
|
|
|
|
// Resolve machine records for the formatter's column width computation.
|
|
machines, err := c.ListMachines(ctx, &api.MachineFilter{
|
|
NamesOrIDs: logsOpts.Machines,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("list machines: %w", err)
|
|
}
|
|
machineNames := make([]string, 0, len(machines))
|
|
for _, m := range machines {
|
|
machineNames = append(machineNames, m.Machine.Name)
|
|
}
|
|
|
|
// Collect one log stream per unit. MachineLogs merges across machines internally.
|
|
unitStreams := make([]<-chan api.ServiceLogEntry, 0, len(units))
|
|
for _, unit := range units {
|
|
ch, err := c.MachineLogs(ctx, unit, logsOpts)
|
|
if err != nil {
|
|
return fmt.Errorf("stream logs for systemd service '%s': %w", unit, err)
|
|
}
|
|
unitStreams = append(unitStreams, ch)
|
|
}
|
|
|
|
var stream <-chan api.ServiceLogEntry
|
|
if len(unitStreams) == 1 {
|
|
stream = unitStreams[0]
|
|
} else {
|
|
// Each MachineLogs stream already runs its own inner merger with stall detection,
|
|
// so the outer merger across units skips it to avoid duplicate warnings.
|
|
merger := client.NewLogMerger(unitStreams, client.LogMergerOptions{})
|
|
stream = merger.Stream()
|
|
}
|
|
|
|
formatter := logs.NewFormatter(machineNames, units, opts.UTC)
|
|
|
|
// Print merged logs.
|
|
for entry := range stream {
|
|
formatter.PrintEntry(entry)
|
|
}
|
|
|
|
return nil
|
|
}
|