garm/cmd/garm-cli/cmd/log.go
Gabriel Adrian Samfira 0faeee703d Make the debug-log command more useful
The debug-log command now supports log level filtering and attribute
filtering. The log level filtering will only be able to set the minimum
log level as low as the server is configured to stream. If the server has
its log level set as INFO, then setting the log level in the CLI to DEBUG
will have no effect.

But anything above what the server sends, is within the control of the client
to filter. This is all done client side.

Attribute filters are useful if you need to watch the logs for a particular
worker, entity, etc.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
2025-08-27 13:21:56 +00:00

75 lines
2.3 KiB
Go

// Copyright 2025 Cloudbase Solutions SRL
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package cmd
import (
"context"
"os/signal"
"strings"
"github.com/spf13/cobra"
garmWs "github.com/cloudbase/garm-provider-common/util/websocket"
"github.com/cloudbase/garm/cmd/garm-cli/common"
)
var (
eventsFilters string
logLevel string
filters []string
enableColor bool
)
var logCmd = &cobra.Command{
Use: "debug-log",
SilenceUsage: true,
Short: "Stream garm log",
Long: `Stream all garm logging to the terminal.`,
RunE: func(_ *cobra.Command, _ []string) error {
ctx, stop := signal.NotifyContext(context.Background(), signals...)
defer stop()
// Parse filters into map
attributeFilters := make(map[string]string)
for _, filter := range filters {
parts := strings.SplitN(filter, "=", 2)
if len(parts) == 2 {
attributeFilters[parts[0]] = parts[1]
}
}
// Create log formatter with filters
logFormatter := common.NewLogFormatter(logLevel, attributeFilters, enableColor)
reader, err := garmWs.NewReader(ctx, mgr.BaseURL, "/api/v1/ws/logs", mgr.Token, logFormatter.FormatWebsocketMessage)
if err != nil {
return err
}
if err := reader.Start(); err != nil {
return err
}
<-reader.Done()
return nil
},
}
func init() {
logCmd.Flags().StringVar(&logLevel, "log-level", "", "Minimum log level to display (DEBUG, INFO, WARN, ERROR)")
logCmd.Flags().StringArrayVar(&filters, "filter", []string{}, "Filter logs by attribute (format: key=value) or message content (msg=text). You can specify this option multiple times. The filter will return true for any of the attributes you set.")
logCmd.Flags().BoolVar(&enableColor, "enable-color", true, "Enable color logging (auto-detects terminal support)")
rootCmd.AddCommand(logCmd)
}