diff --git a/cmd/common.go b/cmd/common.go index 24bdebd0d..fdbeb910f 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -111,7 +111,7 @@ func dumpLogsIfNeeded(ctx context.Context, kubernetesProvider *kubernetes.Provid } dotDir := misc.GetDotFolderPath() filePath := path.Join(dotDir, fmt.Sprintf("%s_logs_%s.zip", misc.Program, time.Now().Format("2006_01_02__15_04_05"))) - if err := fsUtils.DumpLogs(ctx, kubernetesProvider, filePath); err != nil { + if err := fsUtils.DumpLogs(ctx, kubernetesProvider, filePath, config.Config.Logs.Grep); err != nil { log.Error().Err(err).Msg("Failed to dump logs.") } } diff --git a/cmd/logs.go b/cmd/logs.go index 42e63cf05..7f741c077 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -30,7 +30,7 @@ var logsCmd = &cobra.Command{ log.Debug().Str("logs-path", config.Config.Logs.FilePath()).Msg("Using this logs path...") - if dumpLogsErr := fsUtils.DumpLogs(ctx, kubernetesProvider, config.Config.Logs.FilePath()); dumpLogsErr != nil { + if dumpLogsErr := fsUtils.DumpLogs(ctx, kubernetesProvider, config.Config.Logs.FilePath(), config.Config.Logs.Grep); dumpLogsErr != nil { log.Error().Err(dumpLogsErr).Msg("Failed to dump logs.") } @@ -47,4 +47,5 @@ func init() { } logsCmd.Flags().StringP(configStructs.FileLogsName, "f", defaultLogsConfig.FileStr, fmt.Sprintf("Path for zip file (default current <pwd>\\%s_logs.zip)", misc.Program)) + logsCmd.Flags().StringP(configStructs.GrepLogsName, "g", defaultLogsConfig.Grep, "Regexp to do grepping on the logs") } diff --git a/config/configStructs/logsConfig.go b/config/configStructs/logsConfig.go index 1979fc487..3cbe6fde9 100644 --- a/config/configStructs/logsConfig.go +++ b/config/configStructs/logsConfig.go @@ -10,10 +10,12 @@ import ( const ( FileLogsName = "file" + GrepLogsName = "grep" ) type LogsConfig struct { FileStr string `yaml:"file" json:"file"` + Grep string `yaml:"grep" json:"grep"` } func (config *LogsConfig) Validate() error { diff --git a/go.mod b/go.mod index d263f483e..f39f292df 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/rs/zerolog v1.28.0 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 + github.com/tanqiangyes/grep-go v0.0.0-20220515134556-b36bff9c3d8e helm.sh/helm/v3 v3.12.0 k8s.io/api v0.28.3 k8s.io/apimachinery v0.28.3 diff --git a/go.sum b/go.sum index dbb31696d..d53b5c186 100644 --- a/go.sum +++ b/go.sum @@ -618,6 +618,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tanqiangyes/grep-go v0.0.0-20220515134556-b36bff9c3d8e h1:+qDZ81UqxfZsWK6Vq9wET3AsdQxHGbViYOqkNxZ9FnU= +github.com/tanqiangyes/grep-go v0.0.0-20220515134556-b36bff9c3d8e/go.mod h1:ANZlXE3vfRYCYnkojePl2hJODYmOeCVD+XahuhDdTbI= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= diff --git a/kubernetes/provider.go b/kubernetes/provider.go index 1c47d34ef..2a44e3c13 100644 --- a/kubernetes/provider.go +++ b/kubernetes/provider.go @@ -1,6 +1,7 @@ package kubernetes import ( + "bufio" "bytes" "context" "fmt" @@ -8,12 +9,14 @@ import ( "net/url" "path/filepath" "regexp" + "strings" "github.com/kubeshark/kubeshark/config" "github.com/kubeshark/kubeshark/misc" "github.com/kubeshark/kubeshark/semver" "github.com/kubeshark/kubeshark/utils" "github.com/rs/zerolog/log" + "github.com/tanqiangyes/grep-go/reader" core "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -142,7 +145,7 @@ func (provider *Provider) ListPodsByAppLabel(ctx context.Context, namespaces str return pods.Items, err } -func (provider *Provider) GetPodLogs(ctx context.Context, namespace string, podName string, containerName string) (string, error) { +func (provider *Provider) GetPodLogs(ctx context.Context, namespace string, podName string, containerName string, grep string) (string, error) { podLogOpts := core.PodLogOptions{Container: containerName} req := provider.clientSet.CoreV1().Pods(namespace).GetLogs(podName, &podLogOpts) podLogs, err := req.Stream(ctx) @@ -154,8 +157,26 @@ func (provider *Provider) GetPodLogs(ctx context.Context, namespace string, podN if _, err = io.Copy(buf, podLogs); err != nil { return "", fmt.Errorf("error copy information from podLogs to buf, ns: %s, pod: %s, %w", namespace, podName, err) } - str := buf.String() - return str, nil + + if grep != "" { + finder, err := reader.NewFinder(grep, true, true) + if err != nil { + panic(err) + } + + read, err := reader.NewStdReader(bufio.NewReader(buf), []reader.Finder{finder}) + if err != nil { + panic(err) + } + read.Run() + result := read.Result()[0] + + log.Info().Str("namespace", namespace).Str("pod", podName).Str("container", containerName).Int("lines", len(result.Lines)).Str("grep", grep).Send() + return strings.Join(result.MatchString, "\n"), nil + } else { + log.Info().Str("namespace", namespace).Str("pod", podName).Str("container", containerName).Send() + return buf.String(), nil + } } func (provider *Provider) GetNamespaceEvents(ctx context.Context, namespace string) (string, error) { diff --git a/misc/fsUtils/kubesharkLogsUtils.go b/misc/fsUtils/kubesharkLogsUtils.go index 1f1035009..5277e824f 100644 --- a/misc/fsUtils/kubesharkLogsUtils.go +++ b/misc/fsUtils/kubesharkLogsUtils.go @@ -13,7 +13,7 @@ import ( "github.com/rs/zerolog/log" ) -func DumpLogs(ctx context.Context, provider *kubernetes.Provider, filePath string) error { +func DumpLogs(ctx context.Context, provider *kubernetes.Provider, filePath string, grep string) error { podExactRegex := regexp.MustCompile("^" + kubernetes.SELF_RESOURCES_PREFIX) pods, err := provider.ListAllPodsMatchingRegex(ctx, podExactRegex, []string{config.Config.Tap.Release.Namespace}) if err != nil { @@ -34,7 +34,7 @@ func DumpLogs(ctx context.Context, provider *kubernetes.Provider, filePath strin for _, pod := range pods { for _, container := range pod.Spec.Containers { - logs, err := provider.GetPodLogs(ctx, pod.Namespace, pod.Name, container.Name) + logs, err := provider.GetPodLogs(ctx, pod.Namespace, pod.Name, container.Name, grep) if err != nil { log.Error().Err(err).Msg("Failed to get logs!") continue