kubetailrb 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +20 -11
- data/kubetailrb.png +0 -0
- data/lib/kubetailrb/cmd/help.rb +2 -0
- data/lib/kubetailrb/cmd/k8s.rb +35 -26
- data/lib/kubetailrb/formatter/json_formatter.rb +25 -4
- data/lib/kubetailrb/k8s_opts.rb +18 -5
- data/lib/kubetailrb/painter.rb +4 -0
- data/lib/kubetailrb/reader/k8s_pod_reader.rb +2 -2
- data/lib/kubetailrb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0916dd6a8baf85b2f7b4771e9d0623fdbe1ff22ca0ea4111cc54ba1fcfab7fd4'
|
4
|
+
data.tar.gz: 051cc8d7bae42f86ce12b2ac43a567674d187170c73f5079aee14f66cb91a44b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35a876c94e0a0c812e92d9e1828996c186a7e9179ada8222265ee30925cb20d91ea67f0047661df4c87eb0508b26752ee50de37ef5078740288bb6cb75c38214
|
7
|
+
data.tar.gz: 776f10f0896164550dee36bdae375852b8e374aef9d304c5ddde313202c809fa59ffcf46dbc5a7252464425b695cc62f1536895874c0c4ceeed242d8c41a6763
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -5,16 +5,6 @@
|
|
5
5
|
|
6
6
|
> Tail your Kubernetes pod logs at the same time.
|
7
7
|
|
8
|
-
> [!NOTE]
|
9
|
-
> This project is a pet project I used to learn the [Ruby programming language](https://www.ruby-lang.org/en/).
|
10
|
-
> So you might find lots of my [personal notes](./journey_log.md) in the codebase.
|
11
|
-
>
|
12
|
-
> If you want to have something that works, please look at the following
|
13
|
-
> projects that were used as inspirations instead:
|
14
|
-
>
|
15
|
-
> - https://github.com/stern/stern
|
16
|
-
> - https://github.com/johanhaleby/kubetail
|
17
|
-
|
18
8
|

|
19
9
|
|
20
10
|
## Installation
|
@@ -51,7 +41,17 @@ kubetailrb 'clock-json' -n sandbox -f
|
|
51
41
|
kubetailrb '^clock(?!-json)' -n sandbox -f
|
52
42
|
|
53
43
|
# you can also filter the containers using regex on the container names
|
54
|
-
kubetailrb 'clock' -n sandbox -f -c '
|
44
|
+
kubetailrb 'clock' -n sandbox -f -c 'my-container'
|
45
|
+
|
46
|
+
# you can exclude access logs
|
47
|
+
kubetailrb 'clock' -n sandbox -f --excludes access-logs
|
48
|
+
# or Datadog logs
|
49
|
+
kubetailrb 'clock' -n sandbox -f --excludes dd-logs
|
50
|
+
# or both
|
51
|
+
kubetailrb 'clock' -n sandbox -f --excludes access-logs,dd-logs
|
52
|
+
|
53
|
+
# you can include your MDCs by adding your MDC names separated by a comma
|
54
|
+
kubetailrb 'clock' -n sandbox -f --mdcs thread.name,service.version
|
55
55
|
```
|
56
56
|
|
57
57
|
## Development
|
@@ -94,6 +94,15 @@ Then execute the script:
|
|
94
94
|
|
95
95
|
Bug reports and pull requests are welcome on GitHub at https://github.com/l-lin/kubetailrb.
|
96
96
|
|
97
|
+
## Note
|
98
|
+
|
99
|
+
This project is a pet project I used to learn the [Ruby programming language](https://www.ruby-lang.org/en/).
|
100
|
+
So you might find lots of my [personal notes](./journey_log.md) in the codebase.
|
101
|
+
|
102
|
+
If you want to have something that is more complete, please look at
|
103
|
+
[stern](https://github.com/stern/stern) project that was used as inspirations
|
104
|
+
instead.
|
105
|
+
|
97
106
|
## License
|
98
107
|
|
99
108
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/kubetailrb.png
CHANGED
Binary file
|
data/lib/kubetailrb/cmd/help.rb
CHANGED
@@ -23,6 +23,8 @@ module Kubetailrb
|
|
23
23
|
--display-names Display pod and container names.
|
24
24
|
-n, --namespace Kubernetes namespace to use.
|
25
25
|
-c, --container Container name when multiple containers in pod. Default to '.'.
|
26
|
+
-e, --excludes Exclude types of log, separated by a comma. Supporting only 'access-logs' and 'dd-logs'.
|
27
|
+
-m, --mdcs Include MDCs if present in the JSON log, separated by a comma. E.g. 'account.id,thread.name'.
|
26
28
|
HELP
|
27
29
|
end
|
28
30
|
|
data/lib/kubetailrb/cmd/k8s.rb
CHANGED
@@ -17,7 +17,9 @@ module Kubetailrb
|
|
17
17
|
DISPLAY_NAMES_FLAG = '--display-names'
|
18
18
|
|
19
19
|
CONTAINER_FLAGS = %w[-c --container].freeze
|
20
|
-
|
20
|
+
EXCLUDES_FLAGS = %w[-e --excludes].freeze
|
21
|
+
|
22
|
+
MDCS_FLAGS = %w[-m --mdcs].freeze
|
21
23
|
|
22
24
|
attr_reader :reader
|
23
25
|
|
@@ -44,7 +46,8 @@ module Kubetailrb
|
|
44
46
|
follow: parse_follow(*args),
|
45
47
|
raw: parse_raw(*args),
|
46
48
|
display_names: parse_display_names(*args),
|
47
|
-
|
49
|
+
excludes: parse_excludes(*args),
|
50
|
+
mdcs: parse_mdcs(*args)
|
48
51
|
)
|
49
52
|
)
|
50
53
|
end
|
@@ -65,7 +68,7 @@ module Kubetailrb
|
|
65
68
|
#
|
66
69
|
# will return 'sandbox'.
|
67
70
|
#
|
68
|
-
# Will raise `
|
71
|
+
# Will raise `ArgumentError` if the value is not provided:
|
69
72
|
#
|
70
73
|
# kubetailrb some-pod -n
|
71
74
|
#
|
@@ -74,7 +77,7 @@ module Kubetailrb
|
|
74
77
|
|
75
78
|
index = args.find_index { |arg| NAMESPACE_FLAGS.include?(arg) }.to_i
|
76
79
|
|
77
|
-
raise
|
80
|
+
raise ArgumentError, "Missing #{NAMESPACE_FLAGS} value." if args[index + 1].nil?
|
78
81
|
|
79
82
|
args[index + 1]
|
80
83
|
end
|
@@ -86,11 +89,11 @@ module Kubetailrb
|
|
86
89
|
#
|
87
90
|
# will return 3.
|
88
91
|
#
|
89
|
-
# Will raise `
|
92
|
+
# Will raise `ArgumentError` if the value is not provided:
|
90
93
|
#
|
91
94
|
# kubetailrb some-pod --tail
|
92
95
|
#
|
93
|
-
# Will raise `
|
96
|
+
# Will raise `ArgumentError` if the provided value is not a
|
94
97
|
# number:
|
95
98
|
#
|
96
99
|
# kubetailrb some-pod --tail some-string
|
@@ -100,11 +103,11 @@ module Kubetailrb
|
|
100
103
|
|
101
104
|
index = args.find_index { |arg| arg == TAIL_FLAG }.to_i
|
102
105
|
|
103
|
-
raise
|
106
|
+
raise ArgumentError, "Missing #{TAIL_FLAG} value." if args[index + 1].nil?
|
104
107
|
|
105
108
|
last_nb_lines = args[index + 1].to_i
|
106
109
|
|
107
|
-
raise
|
110
|
+
raise ArgumentError, "Invalid #{TAIL_FLAG} value: #{args[index + 1]}." if last_nb_lines.zero?
|
108
111
|
|
109
112
|
last_nb_lines
|
110
113
|
end
|
@@ -122,7 +125,7 @@ module Kubetailrb
|
|
122
125
|
|
123
126
|
index = args.find_index { |arg| CONTAINER_FLAGS.include?(arg) }.to_i
|
124
127
|
|
125
|
-
raise
|
128
|
+
raise ArgumentError, "Missing #{CONTAINER_FLAGS} value." if args[index + 1].nil?
|
126
129
|
|
127
130
|
args[index + 1]
|
128
131
|
end
|
@@ -138,35 +141,41 @@ module Kubetailrb
|
|
138
141
|
#
|
139
142
|
# will return [access-logs, dd-logs].
|
140
143
|
#
|
141
|
-
# Will raise `
|
144
|
+
# Will raise `ArgumentError` if the value is not provided:
|
142
145
|
#
|
143
146
|
# kubetailrb some-pod --exclude
|
144
147
|
#
|
145
|
-
def
|
146
|
-
return [] unless args.any? { |arg|
|
148
|
+
def parse_excludes(*args)
|
149
|
+
return [] unless args.any? { |arg| EXCLUDES_FLAGS.include?(arg) }
|
147
150
|
|
148
|
-
index = args.find_index { |arg|
|
151
|
+
index = args.find_index { |arg| EXCLUDES_FLAGS.include?(arg) }.to_i
|
149
152
|
|
150
|
-
raise
|
153
|
+
raise ArgumentError, "Missing #{EXCLUDES_FLAGS} value." if args[index + 1].nil?
|
151
154
|
|
152
155
|
args[index + 1].split(',')
|
153
156
|
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
class MissingNbLinesValueError < RuntimeError
|
158
|
-
end
|
159
157
|
|
160
|
-
|
161
|
-
|
158
|
+
#
|
159
|
+
# Parse MDCs to include from arguments provided in the CLI, e.g.
|
160
|
+
#
|
161
|
+
# kubetailrb some-pod --mdc account.id,process.thread.name
|
162
|
+
#
|
163
|
+
# will return [account.id, thread.name].
|
164
|
+
#
|
165
|
+
# Will raise `ArgumentError` if the value is not provided:
|
166
|
+
#
|
167
|
+
# kubetailrb some-pod --mdc
|
168
|
+
#
|
169
|
+
def parse_mdcs(*args)
|
170
|
+
return [] unless args.any? { |arg| MDCS_FLAGS.include?(arg) }
|
162
171
|
|
163
|
-
|
164
|
-
end
|
172
|
+
index = args.find_index { |arg| MDCS_FLAGS.include?(arg) }.to_i
|
165
173
|
|
166
|
-
|
167
|
-
end
|
174
|
+
raise ArgumentError, "Missing #{MDCS_FLAGS} value." if args[index + 1].nil?
|
168
175
|
|
169
|
-
|
176
|
+
args[index + 1].split(',')
|
177
|
+
end
|
178
|
+
end
|
170
179
|
end
|
171
180
|
end
|
172
181
|
end
|
@@ -1,12 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'kubetailrb/painter'
|
4
|
+
require 'kubetailrb/validated'
|
4
5
|
|
5
6
|
module Kubetailrb
|
6
7
|
module Formatter
|
7
8
|
# Format JSON to human readable.
|
8
9
|
class JsonFormatter
|
9
10
|
include Painter
|
11
|
+
include Validated
|
12
|
+
|
13
|
+
def initialize(mdcs = [])
|
14
|
+
@mdcs = mdcs
|
15
|
+
|
16
|
+
validate
|
17
|
+
end
|
10
18
|
|
11
19
|
def format(log)
|
12
20
|
json = JSON.parse(log)
|
@@ -20,16 +28,20 @@ module Kubetailrb
|
|
20
28
|
|
21
29
|
private
|
22
30
|
|
31
|
+
def validate
|
32
|
+
raise_if_nil @mdcs, 'MDCs not set.'
|
33
|
+
end
|
34
|
+
|
23
35
|
def access_log?(json)
|
24
36
|
json.include?('http.response.status_code') || json.include?('http_status')
|
25
37
|
end
|
26
38
|
|
27
39
|
def format_access_log(json)
|
28
|
-
"#{json["@timestamp"]}#{
|
40
|
+
"#{json["@timestamp"]}#{format_http_status_code json}#{http_method json} #{url_path json}"
|
29
41
|
end
|
30
42
|
|
31
43
|
def format_application_log(json)
|
32
|
-
"#{json["@timestamp"]}#{
|
44
|
+
"#{json["@timestamp"]}#{format_log_level json}#{format_mdcs json}#{json["message"]}#{format_stack_trace json}"
|
33
45
|
end
|
34
46
|
|
35
47
|
def format_stack_trace(json)
|
@@ -40,7 +52,7 @@ module Kubetailrb
|
|
40
52
|
"\n#{stack_trace}"
|
41
53
|
end
|
42
54
|
|
43
|
-
def
|
55
|
+
def format_http_status_code(json)
|
44
56
|
code = json['http.response.status_code'] || json['http_status']
|
45
57
|
|
46
58
|
return " #{highlight_blue(" I ")} [#{code}] " if code >= 200 && code < 400
|
@@ -50,7 +62,7 @@ module Kubetailrb
|
|
50
62
|
" #{code} "
|
51
63
|
end
|
52
64
|
|
53
|
-
def
|
65
|
+
def format_log_level(json)
|
54
66
|
level = json['log.level'] || json.dig('log', 'level')
|
55
67
|
return ' ' if level.nil? || level.strip.empty?
|
56
68
|
return " #{highlight_blue(" I ")} " if level == 'INFO'
|
@@ -67,6 +79,15 @@ module Kubetailrb
|
|
67
79
|
def url_path(json)
|
68
80
|
json['url.path'] || json['http_path']
|
69
81
|
end
|
82
|
+
|
83
|
+
def format_mdcs(json)
|
84
|
+
result = ''
|
85
|
+
@mdcs.each do |mdc|
|
86
|
+
value = json[mdc] || json.dig(*mdc.split('.'))
|
87
|
+
result += "#{cyan("#{mdc}=#{value}")} " unless value.nil?
|
88
|
+
end
|
89
|
+
result.to_s
|
90
|
+
end
|
70
91
|
end
|
71
92
|
end
|
72
93
|
end
|
data/lib/kubetailrb/k8s_opts.rb
CHANGED
@@ -7,15 +7,27 @@ module Kubetailrb
|
|
7
7
|
class K8sOpts
|
8
8
|
include Validated
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
DEFAULT_NAMESPACE = 'default'
|
11
|
+
DEFAULT_NB_LINES = 10
|
12
|
+
|
13
|
+
attr_reader :namespace, :last_nb_lines, :excludes, :mdcs
|
14
|
+
|
15
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
16
|
+
namespace: DEFAULT_NAMESPACE,
|
17
|
+
last_nb_lines: DEFAULT_NB_LINES,
|
18
|
+
follow: false,
|
19
|
+
raw: false,
|
20
|
+
display_names: false,
|
21
|
+
excludes: [],
|
22
|
+
mdcs: []
|
23
|
+
)
|
13
24
|
@namespace = namespace
|
14
25
|
@last_nb_lines = last_nb_lines
|
15
26
|
@follow = follow
|
16
27
|
@raw = raw
|
17
28
|
@display_names = display_names
|
18
|
-
@
|
29
|
+
@excludes = excludes
|
30
|
+
@mdcs = mdcs
|
19
31
|
|
20
32
|
validate
|
21
33
|
end
|
@@ -40,7 +52,8 @@ module Kubetailrb
|
|
40
52
|
validate_boolean @follow, "Invalid follow: #{@follow}."
|
41
53
|
validate_boolean @raw, "Invalid raw: #{@raw}."
|
42
54
|
validate_boolean @display_names, "Invalid display names: #{@display_names}."
|
43
|
-
raise_if_nil @
|
55
|
+
raise_if_nil @excludes, 'Excludes not set.'
|
56
|
+
raise_if_nil @mdcs, 'MDCs not set.'
|
44
57
|
end
|
45
58
|
end
|
46
59
|
end
|
data/lib/kubetailrb/painter.rb
CHANGED
@@ -23,7 +23,7 @@ module Kubetailrb
|
|
23
23
|
@pod_name = pod_name
|
24
24
|
@container_name = container_name
|
25
25
|
@formatter = create_formatter(opts, pod_name, container_name)
|
26
|
-
@filter = Kubetailrb::Filter::LogFilter.create(opts.
|
26
|
+
@filter = Kubetailrb::Filter::LogFilter.create(opts.excludes)
|
27
27
|
@opts = opts
|
28
28
|
end
|
29
29
|
|
@@ -95,7 +95,7 @@ module Kubetailrb
|
|
95
95
|
formatter = if opts.raw?
|
96
96
|
Kubetailrb::Formatter::NoOpFormatter.new
|
97
97
|
else
|
98
|
-
Kubetailrb::Formatter::JsonFormatter.new
|
98
|
+
Kubetailrb::Formatter::JsonFormatter.new(opts.mdcs)
|
99
99
|
end
|
100
100
|
|
101
101
|
if opts.display_names?
|
data/lib/kubetailrb/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kubetailrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Louis Lin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kubeclient
|