greenhat 0.1.4 → 0.3.1
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/README.md +2 -7
- data/lib/greenhat/accessors/disk.rb +58 -2
- data/lib/greenhat/accessors/gitlab.rb +75 -0
- data/lib/greenhat/accessors/memory.rb +10 -10
- data/lib/greenhat/accessors/process.rb +10 -1
- data/lib/greenhat/cli.rb +128 -57
- data/lib/greenhat/color.rb +27 -0
- data/lib/greenhat/logbot.rb +9 -9
- data/lib/greenhat/settings.rb +51 -3
- data/lib/greenhat/shell/args.rb +146 -0
- data/lib/greenhat/shell/cat.rb +25 -73
- data/lib/greenhat/shell/color_string.rb +43 -0
- data/lib/greenhat/shell/disk.rb +30 -42
- data/lib/greenhat/shell/faststats.rb +80 -61
- data/lib/greenhat/shell/filter_help.rb +143 -0
- data/lib/greenhat/shell/gitlab.rb +61 -2
- data/lib/greenhat/shell/help.rb +98 -15
- data/lib/greenhat/shell/list.rb +46 -0
- data/lib/greenhat/shell/log.rb +78 -203
- data/lib/greenhat/shell/page.rb +39 -0
- data/lib/greenhat/shell/process.rb +57 -2
- data/lib/greenhat/shell/report.rb +70 -60
- data/lib/greenhat/shell/shell_helper.rb +601 -0
- data/lib/greenhat/shell.rb +27 -13
- data/lib/greenhat/thing/file_types.rb +76 -8
- data/lib/greenhat/thing/formatters/json_shellwords.rb +0 -3
- data/lib/greenhat/thing/formatters/nginx.rb +44 -0
- data/lib/greenhat/thing/formatters/syslog.rb +39 -0
- data/lib/greenhat/thing/helpers.rb +4 -4
- data/lib/greenhat/thing/kind.rb +9 -2
- data/lib/greenhat/thing/spinner.rb +3 -3
- data/lib/greenhat/thing.rb +3 -3
- data/lib/greenhat/tty/columns.rb +44 -0
- data/lib/greenhat/version.rb +1 -1
- data/lib/greenhat.rb +15 -14
- metadata +30 -20
- data/lib/greenhat/shell/helper.rb +0 -514
@@ -3,16 +3,75 @@ module GreenHat
|
|
3
3
|
module Shell
|
4
4
|
# Logs
|
5
5
|
module Gitlab
|
6
|
+
def self.ls
|
7
|
+
help
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.help
|
11
|
+
puts "\u2500".pastel(:cyan) * 20
|
12
|
+
puts "#{'GitLab'.pastel(:yellow)} - Tanuki power"
|
13
|
+
puts "\u2500".pastel(:cyan) * 20
|
14
|
+
|
15
|
+
puts 'Command Summary'.pastel(:blue)
|
16
|
+
|
17
|
+
puts ' services'.pastel(:green)
|
18
|
+
puts ' Show services status and version'
|
19
|
+
puts
|
20
|
+
|
21
|
+
puts ' status'.pastel(:green)
|
22
|
+
puts ' Show gitlab-ctl status'
|
23
|
+
puts
|
24
|
+
|
25
|
+
puts ' architecture'.pastel(:green)
|
26
|
+
puts ' Show node responsibility. E.g. Webservice, Gitaly, and etc'
|
27
|
+
puts
|
28
|
+
|
29
|
+
puts ' version'.pastel(:green)
|
30
|
+
puts ' Show GitLab software version'
|
31
|
+
puts
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.architecture
|
35
|
+
results = Archive.all.map { |x| GitLab.identify_node(x) }
|
36
|
+
|
37
|
+
GitLab.node_types.each do |entry|
|
38
|
+
list = results.select { |x| (x.services & entry.pattern).any? }.map(&:host).join(', ')
|
39
|
+
next if list.blank?
|
40
|
+
|
41
|
+
puts entry.name.pastel(:bright_green)
|
42
|
+
puts list
|
43
|
+
puts
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
6
47
|
def self.version
|
7
48
|
Thing.where(type: 'gitlab/version-manifest.json').each do |file|
|
8
49
|
next unless file.data
|
9
50
|
|
10
51
|
puts file.friendly_name
|
11
|
-
puts Semantic::Version.new(file.data.build_version).to_s.
|
52
|
+
puts Semantic::Version.new(file.data.build_version).to_s.pastel(:yellow)
|
12
53
|
puts
|
13
54
|
end
|
14
55
|
end
|
15
56
|
|
57
|
+
# Print service info / shared report method
|
58
|
+
def self.services(raw = {})
|
59
|
+
_files, flags, _args = Args.parse(raw, [:truncate])
|
60
|
+
|
61
|
+
results = {}
|
62
|
+
|
63
|
+
Archive.all.each do |archive|
|
64
|
+
result = GitLab.services(archive)
|
65
|
+
next unless result
|
66
|
+
|
67
|
+
# Generated Output
|
68
|
+
results[archive.friendly_name.pastel(:blue)] = result
|
69
|
+
end
|
70
|
+
|
71
|
+
# Print
|
72
|
+
ShellHelper.show(results, flags)
|
73
|
+
end
|
74
|
+
|
16
75
|
def self.status
|
17
76
|
Thing.where(type: 'gitlab_status').each do |file|
|
18
77
|
next unless file.data
|
@@ -27,7 +86,7 @@ module GreenHat
|
|
27
86
|
|
28
87
|
[
|
29
88
|
"#{service.status}:",
|
30
|
-
service.name.ljust(pad).
|
89
|
+
service.name.ljust(pad).pastel(color),
|
31
90
|
"#{service.pid_uptime};".ljust(pad)
|
32
91
|
|
33
92
|
]
|
data/lib/greenhat/shell/help.rb
CHANGED
@@ -1,15 +1,98 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
1
|
+
module GreenHat
|
2
|
+
# Root Level Shell / Splitting Help into its own file
|
3
|
+
module Shell
|
4
|
+
# rubocop:disable Layout/LineLength
|
5
|
+
def self.help
|
6
|
+
puts 'Quickstart'.pastel(:blue)
|
7
|
+
puts " Commands are organized by submodule: #{'log'.pastel(:blue)}, #{'cat'.pastel(:blue)}, #{'faststats'.pastel(:blue)}"
|
8
|
+
puts " Use #{'help'.pastel(:bright_blue)} for available commands in each module"
|
9
|
+
puts
|
10
|
+
|
11
|
+
puts ' Example Commands'
|
12
|
+
puts ' log filter sidekiq/current'.pastel(:yellow)
|
13
|
+
puts ' disk free'.pastel(:yellow)
|
14
|
+
puts
|
15
|
+
|
16
|
+
puts 'Top Level Commands'.pastel(:blue)
|
17
|
+
puts ' report'.pastel(:green)
|
18
|
+
puts ' Show summary report of SOS Report. OS, CPU, Memory, Disk, and etc'
|
19
|
+
puts ' --raw, no pagination'
|
20
|
+
puts ' --archive=<redis/archive>, filter by archive name'
|
21
|
+
puts
|
22
|
+
|
23
|
+
puts ' ps,df,netstat,free,uptime,uname'.pastel(:green)
|
24
|
+
puts ' Show common files from archives / Emulate terminal commands'
|
25
|
+
puts
|
26
|
+
|
27
|
+
puts ' Noisy Output'.pastel(:green)
|
28
|
+
puts " Use #{'quiet'.pastel(:blue)} or to #{'debug'.pastel(:blue)} to toggle greenhat logging"
|
29
|
+
puts
|
30
|
+
|
31
|
+
cli_shortcuts
|
32
|
+
|
33
|
+
puts "See #{'about'.pastel(:bright_blue)} for more details about GreenHat"
|
34
|
+
end
|
35
|
+
# rubocop:enable Layout/LineLength
|
36
|
+
|
37
|
+
def self.cli_shortcuts
|
38
|
+
puts "\u2500".pastel(:cyan) * 25
|
39
|
+
puts 'Nav / Keyboard Shortcuts'.pastel(:blue)
|
40
|
+
puts "\u2500".pastel(:cyan) * 25
|
41
|
+
puts <<~BLOCK
|
42
|
+
| Hotkey | Description |
|
43
|
+
| ------------------- | ----------------------- |
|
44
|
+
| Ctrl + U | Clear Input |
|
45
|
+
| Ctrl + A | Go to beginning |
|
46
|
+
| Ctrl + E | Go to End |
|
47
|
+
| Ctrl + Left/Right | Move left/right by word |
|
48
|
+
| Ctrl + D, Ctrl + Z | Exit |
|
49
|
+
| Ctrl + C, Shift Tab | Up one module |
|
50
|
+
BLOCK
|
51
|
+
puts
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.about
|
55
|
+
puts "\u2500".pastel(:cyan) * 20
|
56
|
+
puts "About GreenHat #{GreenHat::VERSION}".pastel(:yellow)
|
57
|
+
puts "\u2500".pastel(:cyan) * 20
|
58
|
+
|
59
|
+
puts 'TLDR; Put in SOS reports, run commands, and find stuffs'.pastel(:green)
|
60
|
+
puts
|
61
|
+
|
62
|
+
puts <<~BLOCK
|
63
|
+
General overview (OS, Memory, Disk, GitLab)
|
64
|
+
#{'report'.pastel(:bright_cyan)}
|
65
|
+
|
66
|
+
Log Searching
|
67
|
+
#{'log filter sidekiq/current --job_status=done --sort=duration_s,db_duration_s --slice=duration_s,db_duration_s --reverse'.pastel(:bright_cyan)}
|
68
|
+
|
69
|
+
Read File(s) across SOS archives
|
70
|
+
#{'cat uptime'.pastel(:bright_cyan)} or #{'cat mount etc/fstab'.pastel(:bright_cyan)}
|
71
|
+
|
72
|
+
BLOCK
|
73
|
+
|
74
|
+
puts 'What it does / How it works'.pastel(:blue)
|
75
|
+
puts
|
76
|
+
puts <<~BLOCK
|
77
|
+
GreenHat is a support utility to enhance troubleshooting with GitLabSOS Reports and log files. Make it easy to find stuff
|
78
|
+
|
79
|
+
Supplied input files are staged, unpacked, identified, and normalized.
|
80
|
+
This enables other utilities to automatically find and present data. (Faststats, report, and etc)
|
81
|
+
|
82
|
+
BLOCK
|
83
|
+
|
84
|
+
puts 'Commands and Submodules'.pastel(:blue)
|
85
|
+
puts
|
86
|
+
puts <<~BLOCK
|
87
|
+
Greenhat is broken down into different "modules". Each module has its own commands. For example: log, cat, and faststats.
|
88
|
+
You can "cd" into or execute commands directly against with their names.
|
89
|
+
|
90
|
+
- Direct: #{'log filter sidekiq/current'.pastel(:cyan)}
|
91
|
+
- Or within: First #{'log'.pastel(:cyan)}, then #{'filter sidekiq/current'.pastel(:cyan)}
|
92
|
+
|
93
|
+
You can find the list of commands and submodules of each with #{'help'.pastel(:yellow)}
|
94
|
+
|
95
|
+
BLOCK
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module GreenHat
|
2
|
+
module ShellHelper
|
3
|
+
# Helper to handle listing of files
|
4
|
+
module List
|
5
|
+
# List Files Helpers
|
6
|
+
def self.list(raw = [], files)
|
7
|
+
filter, flags, _args = Args.parse(raw)
|
8
|
+
|
9
|
+
# Sort
|
10
|
+
files.sort_by!(&:name)
|
11
|
+
|
12
|
+
# Simplified vs Full. Full file name/path / or just file kinds
|
13
|
+
all = flags.key?(:all) || flags.key?(:a)
|
14
|
+
|
15
|
+
# Short & Uniq
|
16
|
+
files.uniq!(&:name) unless all
|
17
|
+
|
18
|
+
# Filter / Pattern
|
19
|
+
files.select! { |f| filter.any? { |x| f.name.include? x } } unless filter.empty?
|
20
|
+
|
21
|
+
# Print
|
22
|
+
files.each do |log|
|
23
|
+
if all
|
24
|
+
puts "- #{log.friendly_name}"
|
25
|
+
else
|
26
|
+
puts "- #{log.name.pastel(:yellow)}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Unified Help
|
32
|
+
def self.help
|
33
|
+
puts ' ls'.pastel(:green)
|
34
|
+
puts ' List available files'
|
35
|
+
puts ' Options'.pastel(:cyan)
|
36
|
+
puts ' -a, --all, show full file name/path including source'
|
37
|
+
puts ' <string> filter available'
|
38
|
+
puts ' Examples'.pastel(:cyan)
|
39
|
+
puts ' ls -a rails'
|
40
|
+
puts ' ls sys'
|
41
|
+
puts
|
42
|
+
end
|
43
|
+
# ----
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/greenhat/shell/log.rb
CHANGED
@@ -2,275 +2,146 @@ module GreenHat
|
|
2
2
|
# CLI Helper
|
3
3
|
module Shell
|
4
4
|
# Logs
|
5
|
-
# rubocop:disable Metrics/ModuleLength
|
6
5
|
module Log
|
7
6
|
def self.help
|
8
|
-
puts "\u2500".
|
9
|
-
puts "#{'Logs'.
|
10
|
-
puts "\u2500".
|
7
|
+
puts "\u2500".pastel(:cyan) * 20
|
8
|
+
puts "#{'Logs'.pastel(:yellow)} find stuff"
|
9
|
+
puts "\u2500".pastel(:cyan) * 20
|
11
10
|
|
12
|
-
puts 'Command Summary'.
|
13
|
-
puts '
|
14
|
-
puts
|
15
|
-
puts '
|
16
|
-
puts ' Key/Field Filtering'
|
17
|
-
puts ' search'.colorize(:green)
|
18
|
-
puts ' General text by entry searching'
|
19
|
-
puts ' ls'.colorize(:green)
|
20
|
-
puts ' List available files'
|
11
|
+
puts 'Command Summary'.pastel(:blue)
|
12
|
+
puts ' filter'.pastel(:green)
|
13
|
+
puts " Primary way for log searching within greenhat. See #{'filter_help'.pastel(:blue)}"
|
14
|
+
puts ' Time, round, slice/except, and/or, stats, uniq, sort'
|
21
15
|
puts
|
22
16
|
|
23
|
-
|
24
|
-
|
17
|
+
puts ' show'.pastel(:green)
|
18
|
+
puts ' Just print selected logs'
|
25
19
|
puts
|
26
|
-
search_help
|
27
|
-
end
|
28
|
-
|
29
|
-
# List Files Helpers
|
30
|
-
def self.list(args = [])
|
31
|
-
all = false
|
32
|
-
all = true if args.include?('-a') || args.include?('--all')
|
33
20
|
|
34
|
-
|
21
|
+
puts ' search'.pastel(:green)
|
22
|
+
puts " General full text by file searching. See #{'search_help'.pastel(:blue)}"
|
23
|
+
puts
|
35
24
|
|
36
|
-
|
37
|
-
files.sort_by!(&:name)
|
25
|
+
puts ShellHelper::List.help
|
38
26
|
|
39
|
-
#
|
40
|
-
|
27
|
+
puts "See #{'examples'.pastel(:bright_blue)} for query examples"
|
28
|
+
end
|
41
29
|
|
42
|
-
|
43
|
-
|
44
|
-
if all
|
45
|
-
puts "- #{log.friendly_name}"
|
46
|
-
else
|
47
|
-
puts "- #{log.name.colorize(:yellow)}"
|
48
|
-
end
|
49
|
-
end
|
30
|
+
def self.filter_help
|
31
|
+
ShellHelper::Filter.help
|
50
32
|
end
|
51
33
|
|
52
34
|
def self.ls(args = [])
|
53
|
-
list(args)
|
35
|
+
ShellHelper::List.list(args, ShellHelper::Log.list)
|
54
36
|
end
|
55
37
|
|
56
|
-
def self.show(
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
# Convert to Things
|
61
|
-
logs = ShellHelper.find_things(log_list)
|
38
|
+
def self.show(raw = {})
|
39
|
+
# Extract Args
|
40
|
+
files_list, flags, _args = Args.parse(raw)
|
62
41
|
|
63
|
-
|
42
|
+
# Collect Files
|
43
|
+
files = ShellHelper.files(files_list, Thing.all, flags)
|
64
44
|
|
65
|
-
ShellHelper.show
|
45
|
+
ShellHelper.show files.map(&:data).flatten
|
66
46
|
end
|
67
47
|
|
68
48
|
# ========================================================================
|
69
|
-
# Filter
|
49
|
+
# Filter (See Filter Help)
|
70
50
|
# ========================================================================
|
71
|
-
# Supported Params
|
72
|
-
# --or (Filter OR instead of AND)
|
73
|
-
# --total Total Count Entries Only
|
74
|
-
# --project=thingy --exclude_this!=asdf *
|
75
|
-
# --slice: only grab specific fields --slice=path (slice multiple with comma)
|
76
|
-
# --slice=time,path (E.g. log filter --path='mirror/pull' --slice=path,time )
|
77
|
-
# --except: Exclude specific fields (except multiple with comma)
|
78
|
-
# Example: log filter --path='mirror/pull' --except=params
|
79
51
|
def self.default(raw_list)
|
80
52
|
filter(raw_list)
|
81
53
|
end
|
82
54
|
|
83
|
-
def self.filter(
|
55
|
+
def self.filter(raw)
|
84
56
|
# Print Helper
|
85
|
-
if
|
57
|
+
if raw == ['help']
|
86
58
|
filter_help
|
87
59
|
return true
|
88
60
|
end
|
89
61
|
|
90
|
-
#
|
91
|
-
|
62
|
+
# Argument Parsing
|
63
|
+
files, flags, args = Args.parse(raw)
|
92
64
|
|
93
65
|
# Prepare Log List
|
94
|
-
|
66
|
+
files = ShellHelper.prepare_list(files, ShellHelper::Log.list, flags)
|
95
67
|
|
96
|
-
|
97
|
-
filter_type = args.or ? :any? : :all?
|
68
|
+
results = ShellHelper.filter_start(files, flags, args)
|
98
69
|
|
99
|
-
|
100
|
-
|
101
|
-
# Skipo and Print Total if set
|
102
|
-
if args.total
|
70
|
+
# Skip and Print Total if set
|
71
|
+
if flags[:total]
|
103
72
|
ShellHelper.total_count(results)
|
104
73
|
return true
|
105
74
|
end
|
106
75
|
|
107
76
|
# Check Search Results
|
108
77
|
if results.instance_of?(Hash) && results.values.flatten.empty?
|
109
|
-
puts 'No results'.
|
78
|
+
puts 'No results'.pastel(:red)
|
110
79
|
else
|
111
80
|
# This causes the key 'colorized' output to also be included
|
112
|
-
ShellHelper.show(results.to_a.compact.flatten,
|
81
|
+
ShellHelper.show(results.to_a.compact.flatten, flags)
|
113
82
|
end
|
114
83
|
|
115
84
|
# log filter --path='cloud/gitlab-automation' --path='/pull' --all
|
116
|
-
# cloud/gitlab-automation
|
117
85
|
# log filter --project=thingy --other_filter=asdf *
|
118
86
|
rescue StandardError => e
|
119
|
-
|
120
|
-
|
87
|
+
LogBot.fatal('Filter', message: e.message)
|
88
|
+
ap e.backtrace
|
121
89
|
end
|
122
90
|
# ========================================================================
|
123
91
|
|
124
|
-
# rubocop:disable
|
125
|
-
|
126
|
-
|
127
|
-
puts '
|
128
|
-
puts
|
129
|
-
|
130
|
-
puts 'Options'.colorize(:blue)
|
131
|
-
puts '--raw'.colorize(:green)
|
132
|
-
puts ' Do not use less/paging'
|
133
|
-
puts
|
134
|
-
|
135
|
-
puts '--round'.colorize(:green)
|
136
|
-
puts ' Attempt to round all integers. Default: 2.'
|
137
|
-
puts ' E.g. --round, --round=3, --round=0'
|
138
|
-
puts
|
139
|
-
|
140
|
-
puts '--json'.colorize(:green)
|
141
|
-
puts ' Print output back into JSON'
|
142
|
-
puts
|
143
|
-
|
144
|
-
puts '--or'.colorize(:green)
|
145
|
-
puts ' Filters will use OR instead of AND'
|
146
|
-
puts
|
147
|
-
|
148
|
-
puts '--total'.colorize(:green)
|
149
|
-
puts ' Print only total count of matching entries'
|
150
|
-
puts
|
151
|
-
|
152
|
-
puts '--slice'.colorize(:green)
|
153
|
-
puts ' Extract specific fields from entries (slice multiple with comma)'
|
154
|
-
puts ' Ex: --slice=path or --slice=path,params'
|
155
|
-
puts
|
156
|
-
|
157
|
-
puts '--except'.colorize(:green)
|
158
|
-
puts ' Exclude specific fields (except multiple with comma)'
|
159
|
-
puts ' Ex: --except=params --except=params,path'
|
160
|
-
puts
|
161
|
-
|
162
|
-
puts '--stats'.colorize(:green)
|
163
|
-
puts ' Order/Count occurrances by field'
|
164
|
-
puts ' Ex: --stats=params --except=params,path'
|
165
|
-
puts
|
166
|
-
|
167
|
-
puts '--uniq'.colorize(:green)
|
168
|
-
puts ' Show unique values only'
|
169
|
-
puts ' Ex: --uniq=params --uniq=params,path'
|
170
|
-
puts
|
171
|
-
|
172
|
-
puts '--pluck'.colorize(:green)
|
173
|
-
puts ' Extract values from entries'
|
174
|
-
puts ' Ex: --pluck=params --pluck=params,path'
|
175
|
-
puts
|
176
|
-
|
177
|
-
puts '--archive'.colorize(:green)
|
178
|
-
puts ' Limit to specific archvie name (inclusive). Matching SOS tar.gz name'
|
179
|
-
puts ' Ex: --archive=dev-gitlab_20210622154626, --archive=202106,202107'
|
180
|
-
puts
|
181
|
-
|
182
|
-
puts '--sort'.colorize(:green)
|
183
|
-
puts ' Sort by multiple fields'
|
184
|
-
puts ' Ex: --sort=duration_s,db_duration_s'
|
185
|
-
puts
|
186
|
-
|
187
|
-
puts '--reverse'.colorize(:green)
|
188
|
-
puts ' Reverse all results'
|
189
|
-
puts ' Ex: --reverse'
|
190
|
-
puts
|
191
|
-
|
192
|
-
puts '--combine'.colorize(:green)
|
193
|
-
puts ' Omit archive identifier dividers. Useful with sort or time filters'
|
194
|
-
puts ' Ex: --combine'
|
195
|
-
puts
|
196
|
-
|
197
|
-
puts '--start'.colorize(:green)
|
198
|
-
puts ' Show events after specified time. Filtered by the `time` field'
|
199
|
-
puts ' Use with `--end` for between selections'
|
200
|
-
puts ' Ex: log filter --start="2021-06-22 14:44 UTC" --end="2021-06-22 14:45 UTC"'
|
92
|
+
# rubocop:disable Layout/LineLength
|
93
|
+
# TODO: Add a lot more examples
|
94
|
+
def self.examples
|
95
|
+
puts 'Find `done` job for sidekiq, sort by duration, only duration, and show longest first'.pastel(:bright_green)
|
96
|
+
puts 'log filter sidekiq/current --job_status=done --sort=duration_s,db_duration_s --slice=duration_s,db_duration_s --reverse'
|
201
97
|
puts
|
202
98
|
|
203
|
-
puts '
|
204
|
-
puts '
|
205
|
-
puts ' Use with `--start` for between selections'
|
206
|
-
puts ' Ex: log filter --end="2021-06-22"'
|
99
|
+
puts 'Find 500s only show exceptions'.pastel(:bright_green)
|
100
|
+
puts 'log filter --status=500 --slice=exception.message gitlab-rails/production_json.log'
|
207
101
|
puts
|
208
102
|
|
209
|
-
puts '
|
210
|
-
puts '
|
211
|
-
puts ' Search in key for value'
|
212
|
-
puts ' Example: --path=mirror/pull'
|
103
|
+
puts 'Show unique sidekiq queue namespaces. Exclude Specifics'.pastel(:bright_green)
|
104
|
+
puts 'filter sidekiq/current --slice=queue_namespace --uniq=queue_namespace --queue_namespace!=jira_connect --queue_namespace!=hashed_storage'
|
213
105
|
puts
|
214
106
|
|
215
|
-
puts '
|
216
|
-
puts '
|
217
|
-
puts " Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.colorize(:yellow)}` for log names"
|
107
|
+
puts 'Show user,ip from API logs where `meta.user` field is present '.pastel(:bright_green)
|
108
|
+
puts 'gitlab-rails/api_json.log --slice=meta.user,meta.remote_ip --exists=meta.user'
|
218
109
|
puts
|
219
110
|
|
220
|
-
puts '
|
221
|
-
puts
|
222
|
-
puts 'log filter --class=BuildFinishedWorker sidekiq/current --slice=time,message'
|
223
|
-
puts 'log filter gitlab-rails/api_json.log --slice=ua --uniq=ua --ua=gitlab-runner'
|
224
|
-
|
111
|
+
puts 'Count/% occurences for both user and remote ip fields'.pastel(:bright_green)
|
112
|
+
puts 'gitlab-rails/api_json.log --stats=meta.user,meta.remote_ip --exists=meta.user'
|
225
113
|
puts
|
226
114
|
end
|
227
|
-
# rubocop:enable Metrics/MethodLength
|
228
115
|
|
229
|
-
# rubocop:disable Layout/LineLength
|
230
|
-
# TODO: Add a lot more examples
|
231
|
-
def self.filter_examples
|
232
|
-
puts 'log filter sidekiq/current --sort=db_duration_s --job_status=done --sort=duration_s,db_duration_s --slice=duration_s,db_duration_s --reverse'
|
233
|
-
end
|
234
116
|
# rubocop:enable Layout/LineLength
|
235
|
-
|
236
117
|
# ========================================================================
|
237
118
|
# Search (Full Text / String Search)
|
238
119
|
# ========================================================================
|
239
|
-
|
240
|
-
# --text='asdf'
|
241
|
-
# --text!='asdf'
|
242
|
-
# --regex='' # TODO?
|
243
|
-
# --slice=time,path (E.g. log filter --path='mirror/pull' --slice=path,time )
|
244
|
-
# --except: Exclude specific fields (except multiple with comma)
|
245
|
-
|
246
|
-
# --total Total Count Entries Only
|
247
|
-
def self.search(initial_param)
|
120
|
+
def self.search(raw)
|
248
121
|
# Extract Args
|
249
|
-
|
122
|
+
files_list, flags, args = Args.parse(raw)
|
250
123
|
|
251
124
|
# Prepare Log List
|
252
|
-
|
253
|
-
|
254
|
-
# AND / OR Filtering
|
255
|
-
filter_type = args.or ? :any? : :all?
|
125
|
+
files = ShellHelper.prepare_list(files_list)
|
256
126
|
|
257
|
-
results = ShellHelper.search_start(
|
127
|
+
results = ShellHelper.search_start(files, flags, args)
|
258
128
|
|
259
|
-
#
|
260
|
-
if
|
129
|
+
# Skip and Print Total if set
|
130
|
+
if flags[:total]
|
261
131
|
ShellHelper.total_count(results)
|
262
132
|
return true
|
263
133
|
end
|
264
134
|
|
265
135
|
# Check Search Results
|
266
136
|
if results.values.flatten.empty?
|
267
|
-
puts 'No results'.
|
137
|
+
puts 'No results'.pastel(:red)
|
268
138
|
else
|
269
139
|
# This causes the key 'colorized' output to also be included
|
270
|
-
ShellHelper.show(results.to_a.compact.flatten,
|
140
|
+
ShellHelper.show(results.to_a.compact.flatten, flags)
|
271
141
|
end
|
272
142
|
rescue StandardError => e
|
273
|
-
LogBot.fatal('
|
143
|
+
LogBot.fatal('Search', message: e.message)
|
144
|
+
ap e.backtrace
|
274
145
|
end
|
275
146
|
# ========================================================================
|
276
147
|
|
@@ -282,43 +153,48 @@ module GreenHat
|
|
282
153
|
|
283
154
|
# rubocop:disable Metrics/MethodLength
|
284
155
|
def self.search_help
|
285
|
-
puts "\u2500".
|
286
|
-
puts 'Log Search'.
|
287
|
-
puts "\u2500".
|
156
|
+
puts "\u2500".pastel(:cyan) * 20
|
157
|
+
puts 'Log Search'.pastel(:yellow)
|
158
|
+
puts "\u2500".pastel(:cyan) * 20
|
288
159
|
|
289
160
|
puts 'Search will do a full line include or exclude text search'
|
290
161
|
|
291
|
-
puts 'Options'.
|
292
|
-
puts '--text'.
|
162
|
+
puts 'Options'.pastel(:blue)
|
163
|
+
puts '--text'.pastel(:green)
|
293
164
|
puts ' Primary parameter for searching. Include or ! to exclude'
|
294
165
|
puts ' Ex: --text=BuildHooksWorker --text!=start sidekiq/current'
|
295
166
|
puts
|
296
167
|
|
297
|
-
puts '--total'.
|
168
|
+
puts '--total'.pastel(:green)
|
298
169
|
puts ' Print only total count of matching entries'
|
299
170
|
puts
|
300
171
|
|
301
|
-
puts '--slice'.
|
172
|
+
puts '--slice'.pastel(:green)
|
302
173
|
puts ' Extract specific fields from entries (slice multiple with comma)'
|
303
174
|
puts ' Ex: --slice=path or --slice=path,params'
|
304
175
|
puts
|
305
176
|
|
306
|
-
puts '--except'.
|
177
|
+
puts '--except'.pastel(:green)
|
307
178
|
puts ' Exclude specific fields (except multiple with comma)'
|
308
179
|
puts ' Ex: --except=params --except=params,path'
|
309
180
|
puts
|
310
181
|
|
311
|
-
puts '--archive'.
|
312
|
-
puts ' Limit to specific
|
182
|
+
puts '--archive'.pastel(:green)
|
183
|
+
puts ' Limit to specific archive name (inclusive). Matching SOS tar.gz name'
|
313
184
|
puts ' Ex: --archive=dev-gitlab_20210622154626, --archive=202106,202107'
|
314
185
|
puts
|
315
186
|
|
316
|
-
puts '
|
187
|
+
puts '--limit'.pastel(:green)
|
188
|
+
puts ' Limit total number of results. Default to half total screen size'
|
189
|
+
puts ' Ex: --limit; --limit=10'
|
190
|
+
puts
|
191
|
+
|
192
|
+
puts 'Search specific logs'.pastel(:blue)
|
317
193
|
puts ' Any non dash parameters will be the log list to search from'
|
318
|
-
puts " Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.
|
194
|
+
puts " Ex: log filter --path=api sidekiq/current (hint: use `#{'ls'.pastel(:yellow)}` for log names)"
|
319
195
|
puts
|
320
196
|
|
321
|
-
puts 'Example Queries'.
|
197
|
+
puts 'Example Queries'.pastel(:blue)
|
322
198
|
puts 'log search --text=BuildHooksWorker --text!=start sidekiq/current --total'
|
323
199
|
puts 'log search --text=BuildHooksWorker --text!=start --slice=enqueued_at sidekiq/current'
|
324
200
|
puts
|
@@ -327,7 +203,6 @@ module GreenHat
|
|
327
203
|
|
328
204
|
# ------------------------------------------------------------------------
|
329
205
|
end
|
330
|
-
# rubocop:enable Metrics/ModuleLength
|
331
206
|
end
|
332
207
|
end
|
333
208
|
|