sumologic-query 1.3.5 → 1.4.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/CHANGELOG.md +52 -0
- data/README.md +4 -4
- data/lib/sumologic/cli/commands/base_command.rb +12 -20
- data/lib/sumologic/cli/commands/{discover_sources_command.rb → discover_source_metadata_command.rb} +4 -4
- data/lib/sumologic/cli/commands/export_content_command.rb +18 -0
- data/lib/sumologic/cli/commands/get_content_command.rb +18 -0
- data/lib/sumologic/cli/commands/get_dashboard_command.rb +18 -0
- data/lib/sumologic/cli/commands/get_lookup_command.rb +18 -0
- data/lib/sumologic/cli/commands/get_monitor_command.rb +18 -0
- data/lib/sumologic/cli/commands/list_apps_command.rb +16 -0
- data/lib/sumologic/cli/commands/list_collectors_command.rb +1 -7
- data/lib/sumologic/cli/commands/list_dashboards_command.rb +18 -0
- data/lib/sumologic/cli/commands/list_fields_command.rb +27 -0
- data/lib/sumologic/cli/commands/list_folders_command.rb +55 -0
- data/lib/sumologic/cli/commands/list_health_events_command.rb +18 -0
- data/lib/sumologic/cli/commands/list_monitors_command.rb +23 -0
- data/lib/sumologic/cli/commands/list_sources_command.rb +2 -9
- data/lib/sumologic/cli/commands/search_command.rb +70 -18
- data/lib/sumologic/cli.rb +290 -12
- data/lib/sumologic/client.rb +207 -12
- data/lib/sumologic/configuration.rb +44 -9
- data/lib/sumologic/http/client.rb +76 -11
- data/lib/sumologic/http/connection_pool.rb +7 -5
- data/lib/sumologic/http/response_handler.rb +65 -1
- data/lib/sumologic/metadata/app.rb +34 -0
- data/lib/sumologic/metadata/content.rb +95 -0
- data/lib/sumologic/metadata/dashboard.rb +104 -0
- data/lib/sumologic/metadata/field.rb +49 -0
- data/lib/sumologic/metadata/folder.rb +89 -0
- data/lib/sumologic/metadata/health_event.rb +35 -0
- data/lib/sumologic/metadata/lookup_table.rb +34 -0
- data/lib/sumologic/metadata/models.rb +2 -80
- data/lib/sumologic/metadata/monitor.rb +113 -0
- data/lib/sumologic/metadata/source.rb +5 -7
- data/lib/sumologic/metadata/{dynamic_source_discovery.rb → source_metadata_discovery.rb} +7 -7
- data/lib/sumologic/version.rb +1 -1
- data/lib/sumologic.rb +23 -1
- metadata +23 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f62e0cd6d7ee0fbfd44b2720b0075e4f1776e086ef1ccbe39ad9e520f539f951
|
|
4
|
+
data.tar.gz: da262a85a0fa2d556c310876d011705edd4fc1b46db47c43d6f892adf71649ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz: '
|
|
6
|
+
metadata.gz: 458d97b1853c3626d85f84770faaf918ebbd2842718ffed416ead1736a8a075bc4061eb040e003a24227e8af6b7f6f125baf2b2aec5627f0398abd6b054fe880
|
|
7
|
+
data.tar.gz: '078544851f936431eea88d6b0783f39c58789072bbfa8fe17f5147c2a9aff9df8bc0b3f5e71c48e7d6793f8ad94a69a134bfabe5ab3d46689ff35613a13446f5'
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,58 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
6
6
|
|
|
7
7
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
8
8
|
and release notes are automatically generated from commit messages.
|
|
9
|
+
## [1.4.1](https://github.com/patrick204nqh/sumologic-query/compare/v1.4.0...v1.4.1) (2026-02-11)
|
|
10
|
+
|
|
11
|
+
### 🎉 New Features
|
|
12
|
+
|
|
13
|
+
- add "Open in Sumo Logic" URL to search output
|
|
14
|
+
- add command recipe and CLI command specs
|
|
15
|
+
|
|
16
|
+
### 🐛 Bug Fixes
|
|
17
|
+
|
|
18
|
+
- update source_code_uri metadata to use homepage
|
|
19
|
+
|
|
20
|
+
### 🔧 Refactoring
|
|
21
|
+
|
|
22
|
+
- resolve ADR-006, fix README links, extract command helpers
|
|
23
|
+
|
|
24
|
+
### 📚 Documentation
|
|
25
|
+
|
|
26
|
+
- consolidate query examples and document v1/v2 API split
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## [1.4.0](https://github.com/patrick204nqh/sumologic-query/compare/v1.3.5...v1.4.0) (2026-02-11)
|
|
31
|
+
|
|
32
|
+
### 🎉 New Features
|
|
33
|
+
|
|
34
|
+
- add comprehensive skills documentation for Sumo Logic CLI commands
|
|
35
|
+
- add export-content command with async job handling
|
|
36
|
+
- add get-content command for path-based content lookup
|
|
37
|
+
- add get-lookup and list-apps commands
|
|
38
|
+
- add list-health-events and list-fields commands
|
|
39
|
+
- migrate monitors to search API with status/query filters
|
|
40
|
+
- add support for retrieving monitors and dashboards in the CLI, refactor monitor collection logic for improved readability
|
|
41
|
+
- Enhance Sumo Logic CLI with monitors, folders, and dashboards commands
|
|
42
|
+
- implement aggregation queries and enhance error handling for rate limits
|
|
43
|
+
|
|
44
|
+
### 🐛 Bug Fixes
|
|
45
|
+
|
|
46
|
+
- migrate dashboards from v1 to v2 API
|
|
47
|
+
|
|
48
|
+
### 🔧 Refactoring
|
|
49
|
+
|
|
50
|
+
- clean design for AI agent readiness (v1.4.0)
|
|
51
|
+
|
|
52
|
+
### 📚 Documentation
|
|
53
|
+
|
|
54
|
+
- update naming conventions to match actual codebase
|
|
55
|
+
- reorganize into SDLC structure
|
|
56
|
+
- clarify discover-sources as search-based technique
|
|
57
|
+
- revise architecture overview with enhanced clarity on design philosophy, component structure, and key features
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
9
61
|
## [1.3.5](https://github.com/patrick204nqh/sumologic-query/compare/v1.3.4...v1.3.5) (2025-11-19)
|
|
10
62
|
|
|
11
63
|
### 🎉 New Features
|
data/README.md
CHANGED
|
@@ -78,7 +78,7 @@ sumo-query search -q "YOUR_QUERY" -f "START" -t "END" [OPTIONS]
|
|
|
78
78
|
sumo-query discover-sources [OPTIONS]
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
Discovers source names from log data using search aggregation (`* | count by _sourceName, _sourceCategory`). This is not an official Sumo Logic API — it complements `list-sources` by finding runtime sources (CloudWatch, ECS, Lambda streams) that use dynamic `_sourceName` values.
|
|
82
82
|
|
|
83
83
|
**Options:**
|
|
84
84
|
- `-f, --from` - Start time (default: `-24h`)
|
|
@@ -152,9 +152,9 @@ client.list_all_sources
|
|
|
152
152
|
## Documentation
|
|
153
153
|
|
|
154
154
|
- [Query Examples](examples/queries.md) - Query patterns and examples
|
|
155
|
-
- [Quick Reference](docs/tldr.md) - Command cheat sheet
|
|
156
|
-
- [Rate Limiting](docs/rate-limiting.md) - Performance tuning
|
|
157
|
-
- [Architecture](docs/
|
|
155
|
+
- [Quick Reference](docs/sdlc/7-maintain/tldr.md) - Command cheat sheet
|
|
156
|
+
- [Rate Limiting](docs/sdlc/4-develop/rate-limiting.md) - Performance tuning
|
|
157
|
+
- [Architecture](docs/sdlc/3-design/overview.md) - Design decisions
|
|
158
158
|
|
|
159
159
|
## Contributing
|
|
160
160
|
|
|
@@ -17,6 +17,18 @@ module Sumologic
|
|
|
17
17
|
|
|
18
18
|
private
|
|
19
19
|
|
|
20
|
+
def list_resource(label:, key:)
|
|
21
|
+
warn "Fetching #{label}..."
|
|
22
|
+
items = yield
|
|
23
|
+
output_json(total: items.size, key => items)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def get_resource(label:, id:)
|
|
27
|
+
warn "Fetching #{label} #{id}..."
|
|
28
|
+
result = yield
|
|
29
|
+
output_json(result)
|
|
30
|
+
end
|
|
31
|
+
|
|
20
32
|
def output_json(data)
|
|
21
33
|
json_output = JSON.pretty_generate(data)
|
|
22
34
|
|
|
@@ -31,26 +43,6 @@ module Sumologic
|
|
|
31
43
|
puts json_output
|
|
32
44
|
end
|
|
33
45
|
end
|
|
34
|
-
|
|
35
|
-
def format_collector(collector)
|
|
36
|
-
{
|
|
37
|
-
id: collector['id'],
|
|
38
|
-
name: collector['name'],
|
|
39
|
-
collectorType: collector['collectorType'],
|
|
40
|
-
alive: collector['alive'],
|
|
41
|
-
category: collector['category']
|
|
42
|
-
}
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def format_source(source)
|
|
46
|
-
{
|
|
47
|
-
id: source['id'],
|
|
48
|
-
name: source['name'],
|
|
49
|
-
category: source['category'],
|
|
50
|
-
sourceType: source['sourceType'],
|
|
51
|
-
alive: source['alive']
|
|
52
|
-
}
|
|
53
|
-
end
|
|
54
46
|
end
|
|
55
47
|
end
|
|
56
48
|
end
|
data/lib/sumologic/cli/commands/{discover_sources_command.rb → discover_source_metadata_command.rb}
RENAMED
|
@@ -6,8 +6,8 @@ require_relative '../../utils/time_parser'
|
|
|
6
6
|
module Sumologic
|
|
7
7
|
class CLI < Thor
|
|
8
8
|
module Commands
|
|
9
|
-
# Handles the discover-
|
|
10
|
-
class
|
|
9
|
+
# Handles the discover-source-metadata command execution
|
|
10
|
+
class DiscoverSourceMetadataCommand < BaseCommand
|
|
11
11
|
def execute
|
|
12
12
|
parse_time_options
|
|
13
13
|
log_discovery_info
|
|
@@ -32,7 +32,7 @@ module Sumologic
|
|
|
32
32
|
|
|
33
33
|
def log_discovery_info
|
|
34
34
|
warn '=' * 60
|
|
35
|
-
warn 'Discovering
|
|
35
|
+
warn 'Discovering Source Metadata'
|
|
36
36
|
warn '=' * 60
|
|
37
37
|
warn "Time Range: #{@original_from} to #{@original_to}"
|
|
38
38
|
if @original_from != @parsed_from || @original_to != @parsed_to
|
|
@@ -46,7 +46,7 @@ module Sumologic
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def perform_discovery
|
|
49
|
-
client.
|
|
49
|
+
client.discover_source_metadata(
|
|
50
50
|
from_time: @parsed_from,
|
|
51
51
|
to_time: @parsed_to,
|
|
52
52
|
time_zone: @parsed_timezone,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the export-content command execution
|
|
9
|
+
class ExportContentCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
get_resource(label: 'content', id: options[:content_id]) do
|
|
12
|
+
client.export_content(content_id: options[:content_id])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the get-content command execution
|
|
9
|
+
class GetContentCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
get_resource(label: 'content at path:', id: options[:path]) do
|
|
12
|
+
client.get_content(path: options[:path])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the get-dashboard command execution
|
|
9
|
+
class GetDashboardCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
get_resource(label: 'dashboard', id: options[:dashboard_id]) do
|
|
12
|
+
client.get_dashboard(dashboard_id: options[:dashboard_id])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the get-lookup command execution
|
|
9
|
+
class GetLookupCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
get_resource(label: 'lookup table', id: options[:lookup_id]) do
|
|
12
|
+
client.get_lookup(lookup_id: options[:lookup_id])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the get-monitor command execution
|
|
9
|
+
class GetMonitorCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
get_resource(label: 'monitor', id: options[:monitor_id]) do
|
|
12
|
+
client.get_monitor(monitor_id: options[:monitor_id])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the list-apps command execution
|
|
9
|
+
class ListAppsCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
list_resource(label: 'app catalog', key: :apps) { client.list_apps }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -8,13 +8,7 @@ module Sumologic
|
|
|
8
8
|
# Handles the list-collectors command execution
|
|
9
9
|
class ListCollectorsCommand < BaseCommand
|
|
10
10
|
def execute
|
|
11
|
-
|
|
12
|
-
collectors = client.list_collectors
|
|
13
|
-
|
|
14
|
-
output_json(
|
|
15
|
-
total: collectors.size,
|
|
16
|
-
collectors: collectors.map { |c| format_collector(c) }
|
|
17
|
-
)
|
|
11
|
+
list_resource(label: 'collectors', key: :collectors) { client.list_collectors }
|
|
18
12
|
end
|
|
19
13
|
end
|
|
20
14
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the list-dashboards command execution
|
|
9
|
+
class ListDashboardsCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
list_resource(label: 'dashboards', key: :dashboards) do
|
|
12
|
+
client.list_dashboards(limit: options[:limit] || 100)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the list-fields command execution
|
|
9
|
+
class ListFieldsCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
if options[:builtin]
|
|
12
|
+
warn 'Fetching built-in fields...'
|
|
13
|
+
fields = client.list_builtin_fields
|
|
14
|
+
else
|
|
15
|
+
warn 'Fetching custom fields...'
|
|
16
|
+
fields = client.list_fields
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
output_json(
|
|
20
|
+
total: fields.size,
|
|
21
|
+
fields: fields
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the list-folders command execution
|
|
9
|
+
class ListFoldersCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
if options[:tree]
|
|
12
|
+
fetch_tree
|
|
13
|
+
elsif options[:folder_id]
|
|
14
|
+
fetch_folder
|
|
15
|
+
else
|
|
16
|
+
fetch_personal
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def fetch_personal
|
|
23
|
+
warn 'Fetching personal folder...'
|
|
24
|
+
folder = client.personal_folder
|
|
25
|
+
output_folder_with_children(folder)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def fetch_folder
|
|
29
|
+
folder_id = options[:folder_id]
|
|
30
|
+
warn "Fetching folder #{folder_id}..."
|
|
31
|
+
folder = client.get_folder(folder_id: folder_id)
|
|
32
|
+
output_folder_with_children(folder)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def fetch_tree
|
|
36
|
+
folder_id = options[:folder_id]
|
|
37
|
+
max_depth = options[:depth] || 3
|
|
38
|
+
|
|
39
|
+
if folder_id
|
|
40
|
+
warn "Fetching folder tree for #{folder_id} (depth: #{max_depth})..."
|
|
41
|
+
else
|
|
42
|
+
warn "Fetching personal folder tree (depth: #{max_depth})..."
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
tree = client.folder_tree(folder_id: folder_id, max_depth: max_depth)
|
|
46
|
+
output_json(tree)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def output_folder_with_children(folder)
|
|
50
|
+
output_json(folder)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the list-health-events command execution
|
|
9
|
+
class ListHealthEventsCommand < BaseCommand
|
|
10
|
+
def execute
|
|
11
|
+
list_resource(label: 'health events', key: :healthEvents) do
|
|
12
|
+
client.list_health_events(limit: options[:limit] || 100)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_command'
|
|
4
|
+
|
|
5
|
+
module Sumologic
|
|
6
|
+
class CLI < Thor
|
|
7
|
+
module Commands
|
|
8
|
+
# Handles the list-monitors command execution
|
|
9
|
+
# Uses the monitors search API for flat, filterable results
|
|
10
|
+
class ListMonitorsCommand < BaseCommand
|
|
11
|
+
def execute
|
|
12
|
+
list_resource(label: 'monitors', key: :monitors) do
|
|
13
|
+
client.list_monitors(
|
|
14
|
+
query: options[:query],
|
|
15
|
+
status: options[:status],
|
|
16
|
+
limit: options[:limit] || 100
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -24,7 +24,7 @@ module Sumologic
|
|
|
24
24
|
output_json(
|
|
25
25
|
collector_id: options[:collector_id],
|
|
26
26
|
total: sources.size,
|
|
27
|
-
sources: sources
|
|
27
|
+
sources: sources
|
|
28
28
|
)
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -37,16 +37,9 @@ module Sumologic
|
|
|
37
37
|
output_json(
|
|
38
38
|
total_collectors: all_sources.size,
|
|
39
39
|
total_sources: all_sources.sum { |c| c['sources'].size },
|
|
40
|
-
data: all_sources
|
|
40
|
+
data: all_sources
|
|
41
41
|
)
|
|
42
42
|
end
|
|
43
|
-
|
|
44
|
-
def format_collector_with_sources(item)
|
|
45
|
-
{
|
|
46
|
-
collector: item['collector'],
|
|
47
|
-
sources: item['sources'].map { |s| format_source(s) }
|
|
48
|
-
}
|
|
49
|
-
end
|
|
50
43
|
end
|
|
51
44
|
end
|
|
52
45
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'erb'
|
|
3
4
|
require_relative 'base_command'
|
|
4
5
|
require_relative '../../utils/time_parser'
|
|
5
6
|
|
|
@@ -46,42 +47,83 @@ module Sumologic
|
|
|
46
47
|
end
|
|
47
48
|
warn "Query: #{options[:query]}"
|
|
48
49
|
warn "Limit: #{options[:limit] || 'unlimited'}"
|
|
50
|
+
warn "Open in Sumo: #{build_search_url}"
|
|
49
51
|
warn '-' * 60
|
|
50
52
|
warn 'Creating search job...'
|
|
51
53
|
$stderr.puts
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
def perform_search
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
if aggregate_mode?
|
|
58
|
+
client.search_aggregation(
|
|
59
|
+
query: options[:query],
|
|
60
|
+
from_time: @parsed_from,
|
|
61
|
+
to_time: @parsed_to,
|
|
62
|
+
time_zone: @parsed_timezone,
|
|
63
|
+
limit: options[:limit]
|
|
64
|
+
)
|
|
65
|
+
else
|
|
66
|
+
client.search(
|
|
67
|
+
query: options[:query],
|
|
68
|
+
from_time: @parsed_from,
|
|
69
|
+
to_time: @parsed_to,
|
|
70
|
+
time_zone: @parsed_timezone,
|
|
71
|
+
limit: options[:limit]
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def aggregate_mode?
|
|
77
|
+
options[:aggregate] || aggregation_query?(options[:query])
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def aggregation_query?(query)
|
|
81
|
+
query.match?(/\|\s*(count|sum|avg|min|max|pct|first|last|group)\b/i)
|
|
62
82
|
end
|
|
63
83
|
|
|
64
84
|
def display_results_summary(results)
|
|
85
|
+
result_type = aggregate_mode? ? 'records' : 'messages'
|
|
65
86
|
warn '=' * 60
|
|
66
|
-
warn "Results: #{results.size}
|
|
87
|
+
warn "Results: #{results.size} #{result_type}"
|
|
67
88
|
warn '=' * 60
|
|
68
89
|
$stderr.puts
|
|
69
90
|
end
|
|
70
91
|
|
|
71
92
|
def output_search_results(results)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
93
|
+
if aggregate_mode?
|
|
94
|
+
output_json(
|
|
95
|
+
query: options[:query],
|
|
96
|
+
from: @parsed_from,
|
|
97
|
+
to: @parsed_to,
|
|
98
|
+
from_original: @original_from,
|
|
99
|
+
to_original: @original_to,
|
|
100
|
+
time_zone: @parsed_timezone,
|
|
101
|
+
search_url: build_search_url,
|
|
102
|
+
record_count: results.size,
|
|
103
|
+
records: results
|
|
104
|
+
)
|
|
105
|
+
else
|
|
106
|
+
output_json(
|
|
107
|
+
query: options[:query],
|
|
108
|
+
from: @parsed_from,
|
|
109
|
+
to: @parsed_to,
|
|
110
|
+
from_original: @original_from,
|
|
111
|
+
to_original: @original_to,
|
|
112
|
+
time_zone: @parsed_timezone,
|
|
113
|
+
search_url: build_search_url,
|
|
114
|
+
message_count: results.size,
|
|
115
|
+
messages: results
|
|
116
|
+
)
|
|
117
|
+
end
|
|
82
118
|
end
|
|
83
119
|
|
|
84
120
|
def launch_interactive_mode(results)
|
|
121
|
+
if aggregate_mode?
|
|
122
|
+
warn 'Interactive mode is not supported for aggregation queries'
|
|
123
|
+
output_search_results(results)
|
|
124
|
+
return
|
|
125
|
+
end
|
|
126
|
+
|
|
85
127
|
require_relative '../../interactive'
|
|
86
128
|
|
|
87
129
|
formatted_results = build_formatted_results(results)
|
|
@@ -97,10 +139,20 @@ module Sumologic
|
|
|
97
139
|
'from' => @parsed_from,
|
|
98
140
|
'to' => @parsed_to,
|
|
99
141
|
'time_zone' => @parsed_timezone,
|
|
142
|
+
'search_url' => build_search_url,
|
|
100
143
|
'message_count' => results.size,
|
|
101
144
|
'messages' => results
|
|
102
145
|
}
|
|
103
146
|
end
|
|
147
|
+
|
|
148
|
+
def build_search_url
|
|
149
|
+
from_ms = (Time.parse("#{@parsed_from}Z").to_f * 1000).to_i
|
|
150
|
+
to_ms = (Time.parse("#{@parsed_to}Z").to_f * 1000).to_i
|
|
151
|
+
encoded_query = ERB::Util.url_encode(options[:query])
|
|
152
|
+
base = client.config.web_ui_base_url
|
|
153
|
+
|
|
154
|
+
"#{base}/ui/#/search/create?query=#{encoded_query}&startTime=#{from_ms}&endTime=#{to_ms}"
|
|
155
|
+
end
|
|
104
156
|
end
|
|
105
157
|
end
|
|
106
158
|
end
|