You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2022/08/30 15:24:36 UTC
[camel-k] 01/01: feat(cli): Add tail and tail-lines flags to the log command
This is an automated email from the ASF dual-hosted git repository.
nfilotto pushed a commit to branch 3004/log-tail
in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 80bd2d7f664b765d1bb337820d804a6652c0410b
Author: Nicolas Filotto <nf...@talend.com>
AuthorDate: Tue Aug 30 17:24:10 2022 +0200
feat(cli): Add tail and tail-lines flags to the log command
---
e2e/namespace/install/cli/log_test.go | 8 ++++++++
pkg/cmd/debug.go | 2 +-
pkg/cmd/log.go | 13 ++++++++++++-
pkg/cmd/run.go | 2 +-
pkg/util/kubernetes/log/annotation_scraper.go | 6 ++++--
pkg/util/kubernetes/log/pod_scraper.go | 5 ++++-
pkg/util/kubernetes/log/util.go | 8 ++++----
7 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/e2e/namespace/install/cli/log_test.go b/e2e/namespace/install/cli/log_test.go
index 5b696ac68..5b25479e7 100644
--- a/e2e/namespace/install/cli/log_test.go
+++ b/e2e/namespace/install/cli/log_test.go
@@ -48,6 +48,14 @@ func TestKamelCLILog(t *testing.T) {
logsCLI := GetOutputStringAsync(Kamel("log", "yaml", "-n", ns))
Eventually(logsCLI).Should(ContainSubstring("Monitoring pod " + podName))
Eventually(logsCLI).Should(ContainSubstring(logs))
+
+ logsCLI := GetOutputStringAsync(Kamel("log", "yaml", "-n", ns, "-f"))
+ Eventually(logsCLI).Should(ContainSubstring("Monitoring pod " + podName))
+ Eventually(logsCLI).Should(ContainSubstring(logs))
+
+ logsCLI := GetOutputStringAsync(Kamel("log", "yaml", "-n", ns, "-l", 5))
+ Eventually(logsCLI).Should(ContainSubstring("Monitoring pod " + podName))
+ Eventually(logsCLI).Should(ContainSubstring(logs))
})
})
}
diff --git a/pkg/cmd/debug.go b/pkg/cmd/debug.go
index 2913bacae..7d5a1de8f 100644
--- a/pkg/cmd/debug.go
+++ b/pkg/cmd/debug.go
@@ -123,7 +123,7 @@ func (o *debugCmdOptions) run(cmd *cobra.Command, args []string) error {
selector := fmt.Sprintf("camel.apache.org/debug=true,camel.apache.org/integration=%s", name)
go func() {
- err = k8slog.PrintUsingSelector(o.Context, cmd, cmdClient, o.Namespace, "integration", selector, cmd.OutOrStdout())
+ err = k8slog.PrintUsingSelector(o.Context, cmd, cmdClient, o.Namespace, "integration", selector, nil, cmd.OutOrStdout())
if err != nil {
fmt.Fprintln(cmd.ErrOrStderr(), err.Error())
}
diff --git a/pkg/cmd/log.go b/pkg/cmd/log.go
index 9a9efcbf9..b668091fa 100644
--- a/pkg/cmd/log.go
+++ b/pkg/cmd/log.go
@@ -46,6 +46,9 @@ func newCmdLog(rootCmdOptions *RootCmdOptions) (*cobra.Command, *logCmdOptions)
RunE: options.run,
}
+ cmd.Flags().BoolP("tail", "f", false, "To show the end of the logs")
+ cmd.Flags().Int64P("tail-lines", "l", 10, "The number of lines from the end of the logs to show")
+
// completion support
configureKnownCompletions(&cmd)
@@ -54,6 +57,8 @@ func newCmdLog(rootCmdOptions *RootCmdOptions) (*cobra.Command, *logCmdOptions)
type logCmdOptions struct {
*RootCmdOptions
+ Tail bool `mapstructure:"tail"`
+ TailLines int64 `mapstructure:"tail-lines"`
}
func (o *logCmdOptions) validate(_ *cobra.Command, args []string) error {
@@ -129,7 +134,13 @@ func (o *logCmdOptions) run(cmd *cobra.Command, args []string) error {
// Found the running integration so step over to scraping its pod log
//
fmt.Fprintln(cmd.OutOrStdout(), "Integration '"+integrationID+"' is now running. Showing log ...")
- if err := k8slog.Print(o.Context, cmd, c, &integration, cmd.OutOrStdout()); err != nil {
+ var tailLines *int64
+ if cmd.Flags().Lookup("tail-lines").Changed {
+ tailLines = &o.TailLines
+ } else if o.Tail {
+ tailLines = &[]int64{10}[0]
+ }
+ if err := k8slog.Print(o.Context, cmd, c, &integration, tailLines, cmd.OutOrStdout()); err != nil {
return false, err
}
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index b1e23aa6e..ac4174ff4 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -378,7 +378,7 @@ func (o *runCmdOptions) run(cmd *cobra.Command, args []string) error {
}
}
if o.Logs || o.Dev {
- err = k8slog.Print(o.Context, cmd, c, integration, cmd.OutOrStdout())
+ err = k8slog.Print(o.Context, cmd, c, integration, nil, cmd.OutOrStdout())
if err != nil {
return err
}
diff --git a/pkg/util/kubernetes/log/annotation_scraper.go b/pkg/util/kubernetes/log/annotation_scraper.go
index c3cde929d..4c687ad60 100644
--- a/pkg/util/kubernetes/log/annotation_scraper.go
+++ b/pkg/util/kubernetes/log/annotation_scraper.go
@@ -44,16 +44,18 @@ type SelectorScraper struct {
podScrapers sync.Map
counter uint64
L klog.Logger
+ tailLines *int64
}
// NewSelectorScraper creates a new SelectorScraper.
-func NewSelectorScraper(client kubernetes.Interface, namespace string, defaultContainerName string, labelSelector string) *SelectorScraper {
+func NewSelectorScraper(client kubernetes.Interface, namespace string, defaultContainerName string, labelSelector string, tailLines *int64) *SelectorScraper {
return &SelectorScraper{
client: client,
namespace: namespace,
defaultContainerName: defaultContainerName,
labelSelector: labelSelector,
L: klog.WithName("scraper").WithName("label").WithValues("selector", labelSelector),
+ tailLines: tailLines,
}
}
@@ -130,7 +132,7 @@ func (s *SelectorScraper) synchronize(ctx context.Context, out *bufio.Writer) er
}
func (s *SelectorScraper) addPodScraper(ctx context.Context, podName string, out *bufio.Writer) {
- podScraper := NewPodScraper(s.client, s.namespace, podName, s.defaultContainerName)
+ podScraper := NewPodScraper(s.client, s.namespace, podName, s.defaultContainerName, s.tailLines)
podCtx, podCancel := context.WithCancel(ctx)
id := atomic.AddUint64(&s.counter, 1)
prefix := "[" + strconv.FormatUint(id, 10) + "] "
diff --git a/pkg/util/kubernetes/log/pod_scraper.go b/pkg/util/kubernetes/log/pod_scraper.go
index 494e0501f..a9fb24a89 100644
--- a/pkg/util/kubernetes/log/pod_scraper.go
+++ b/pkg/util/kubernetes/log/pod_scraper.go
@@ -48,16 +48,18 @@ type PodScraper struct {
defaultContainerName string
client kubernetes.Interface
L klog.Logger
+ tailLines *int64
}
// NewPodScraper creates a new pod scraper.
-func NewPodScraper(c kubernetes.Interface, namespace string, podName string, defaultContainerName string) *PodScraper {
+func NewPodScraper(c kubernetes.Interface, namespace string, podName string, defaultContainerName string, tailLines *int64) *PodScraper {
return &PodScraper{
namespace: namespace,
podName: podName,
defaultContainerName: defaultContainerName,
client: c,
L: klog.WithName("scraper").WithName("pod").WithValues("name", podName),
+ tailLines: tailLines,
}
}
@@ -83,6 +85,7 @@ func (s *PodScraper) doScrape(ctx context.Context, out *bufio.Writer, clientClos
}
logOptions := corev1.PodLogOptions{
Follow: true,
+ TailLines: s.tailLines,
Container: containerName,
}
byteReader, err := s.client.CoreV1().Pods(s.namespace).GetLogs(s.podName, &logOptions).Stream(ctx)
diff --git a/pkg/util/kubernetes/log/util.go b/pkg/util/kubernetes/log/util.go
index 26bd2c158..8dbc08530 100644
--- a/pkg/util/kubernetes/log/util.go
+++ b/pkg/util/kubernetes/log/util.go
@@ -30,13 +30,13 @@ import (
)
// Print prints integrations logs to the stdout.
-func Print(ctx context.Context, cmd *cobra.Command, client kubernetes.Interface, integration *v1.Integration, out io.Writer) error {
- return PrintUsingSelector(ctx, cmd, client, integration.Namespace, integration.Name, v1.IntegrationLabel+"="+integration.Name, out)
+func Print(ctx context.Context, cmd *cobra.Command, client kubernetes.Interface, integration *v1.Integration, tailLines *int64, out io.Writer) error {
+ return PrintUsingSelector(ctx, cmd, client, integration.Namespace, integration.Name, v1.IntegrationLabel+"="+integration.Name, tailLines, out)
}
// PrintUsingSelector prints pod logs using a selector.
-func PrintUsingSelector(ctx context.Context, cmd *cobra.Command, client kubernetes.Interface, namespace, defaultContainerName, selector string, out io.Writer) error {
- scraper := NewSelectorScraper(client, namespace, defaultContainerName, selector)
+func PrintUsingSelector(ctx context.Context, cmd *cobra.Command, client kubernetes.Interface, namespace, defaultContainerName, selector string, tailLines *int64, out io.Writer) error {
+ scraper := NewSelectorScraper(client, namespace, defaultContainerName, selector, tailLines)
reader := scraper.Start(ctx)
if _, err := io.Copy(out, ioutil.NopCloser(reader)); err != nil {