sumologic-query 1.3.5 → 1.4.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/README.md +1 -1
  4. data/lib/sumologic/cli/commands/base_command.rb +0 -20
  5. data/lib/sumologic/cli/commands/{discover_sources_command.rb → discover_source_metadata_command.rb} +4 -4
  6. data/lib/sumologic/cli/commands/export_content_command.rb +20 -0
  7. data/lib/sumologic/cli/commands/get_content_command.rb +20 -0
  8. data/lib/sumologic/cli/commands/get_dashboard_command.rb +20 -0
  9. data/lib/sumologic/cli/commands/get_lookup_command.rb +20 -0
  10. data/lib/sumologic/cli/commands/get_monitor_command.rb +20 -0
  11. data/lib/sumologic/cli/commands/list_apps_command.rb +22 -0
  12. data/lib/sumologic/cli/commands/list_collectors_command.rb +1 -1
  13. data/lib/sumologic/cli/commands/list_dashboards_command.rb +22 -0
  14. data/lib/sumologic/cli/commands/list_fields_command.rb +27 -0
  15. data/lib/sumologic/cli/commands/list_folders_command.rb +55 -0
  16. data/lib/sumologic/cli/commands/list_health_events_command.rb +22 -0
  17. data/lib/sumologic/cli/commands/list_monitors_command.rb +27 -0
  18. data/lib/sumologic/cli/commands/list_sources_command.rb +2 -9
  19. data/lib/sumologic/cli/commands/search_command.rb +56 -18
  20. data/lib/sumologic/cli.rb +290 -12
  21. data/lib/sumologic/client.rb +207 -12
  22. data/lib/sumologic/configuration.rb +23 -9
  23. data/lib/sumologic/http/client.rb +76 -11
  24. data/lib/sumologic/http/connection_pool.rb +7 -5
  25. data/lib/sumologic/http/response_handler.rb +65 -1
  26. data/lib/sumologic/metadata/app.rb +34 -0
  27. data/lib/sumologic/metadata/content.rb +95 -0
  28. data/lib/sumologic/metadata/dashboard.rb +104 -0
  29. data/lib/sumologic/metadata/field.rb +49 -0
  30. data/lib/sumologic/metadata/folder.rb +89 -0
  31. data/lib/sumologic/metadata/health_event.rb +35 -0
  32. data/lib/sumologic/metadata/lookup_table.rb +34 -0
  33. data/lib/sumologic/metadata/models.rb +2 -80
  34. data/lib/sumologic/metadata/monitor.rb +113 -0
  35. data/lib/sumologic/metadata/source.rb +5 -7
  36. data/lib/sumologic/metadata/{dynamic_source_discovery.rb → source_metadata_discovery.rb} +7 -7
  37. data/lib/sumologic/version.rb +1 -1
  38. data/lib/sumologic.rb +23 -1
  39. metadata +23 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83e78d35f43a7e12f98e3ed11d9d4b0ddd7fe4cf567c281fa4729c8873c583a0
4
- data.tar.gz: 4cc242bc523b5ce0cf709ec9f9aceb44cb1fe5911582983ae80e3a49d00a175d
3
+ metadata.gz: 5822fc268d1979e97d6993b7f233b720049f832c4d5d921a75c32ecccc16ce68
4
+ data.tar.gz: f9e1cde6a138f45d70ec4ed2e06b22f87faf9500a6cb4fb7274fe8df787bcba1
5
5
  SHA512:
6
- metadata.gz: 7b9d63d998ff14e1b9db86dc982dd84b508f642c01a62883b7bdce997ec21aed3097477956776319f01b68da2e8ed967b713894ed8002353ab99ee9fd72bad85
7
- data.tar.gz: '084c1c7db713d88f88979941d8b6a261f48c4bc533f3ce2ac04cb97ea3bae5fb0762889611dbfffd790740e0c7928acffb9e7df144c6e6d7b0fa129128d49e23'
6
+ metadata.gz: 661862b1dfbc17a5729fbffc54c459e9b2e52a996346b0c028179002c606689096c0a191a26d7bb06d737c197f50324eb86e574289a093c4a392b9248a3e2647
7
+ data.tar.gz: fda3e751c1dc953fa10d878288193ffe060dcd9366e9d18e8cad9d8eeaf8a194e0dcaa1f50ca245fdc5ab20a95c7f1b67809add3dbed2aa28341f68130188ffd
data/CHANGELOG.md CHANGED
@@ -6,6 +6,37 @@ 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.0](https://github.com/patrick204nqh/sumologic-query/compare/v1.3.5...v1.4.0) (2026-02-11)
10
+
11
+ ### 🎉 New Features
12
+
13
+ - add comprehensive skills documentation for Sumo Logic CLI commands
14
+ - add export-content command with async job handling
15
+ - add get-content command for path-based content lookup
16
+ - add get-lookup and list-apps commands
17
+ - add list-health-events and list-fields commands
18
+ - migrate monitors to search API with status/query filters
19
+ - add support for retrieving monitors and dashboards in the CLI, refactor monitor collection logic for improved readability
20
+ - Enhance Sumo Logic CLI with monitors, folders, and dashboards commands
21
+ - implement aggregation queries and enhance error handling for rate limits
22
+
23
+ ### 🐛 Bug Fixes
24
+
25
+ - migrate dashboards from v1 to v2 API
26
+
27
+ ### 🔧 Refactoring
28
+
29
+ - clean design for AI agent readiness (v1.4.0)
30
+
31
+ ### 📚 Documentation
32
+
33
+ - update naming conventions to match actual codebase
34
+ - reorganize into SDLC structure
35
+ - clarify discover-sources as search-based technique
36
+ - revise architecture overview with enhanced clarity on design philosophy, component structure, and key features
37
+
38
+
39
+
9
40
  ## [1.3.5](https://github.com/patrick204nqh/sumologic-query/compare/v1.3.4...v1.3.5) (2025-11-19)
10
41
 
11
42
  ### 🎉 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
- Finds dynamic source names from log data (CloudWatch, ECS, Lambda streams).
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`)
@@ -31,26 +31,6 @@ module Sumologic
31
31
  puts json_output
32
32
  end
33
33
  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
34
  end
55
35
  end
56
36
  end
@@ -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-sources command execution
10
- class DiscoverSourcesCommand < BaseCommand
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 Dynamic Source Names'
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.discover_dynamic_sources(
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,20 @@
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
+ content_id = options[:content_id]
12
+ warn "Exporting content #{content_id}..."
13
+ result = client.export_content(content_id: content_id)
14
+
15
+ output_json(result)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
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
+ path = options[:path]
12
+ warn "Looking up content at path: #{path}..."
13
+ content = client.get_content(path: path)
14
+
15
+ output_json(content)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
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
+ dashboard_id = options[:dashboard_id]
12
+ warn "Fetching dashboard #{dashboard_id}..."
13
+ dashboard = client.get_dashboard(dashboard_id: dashboard_id)
14
+
15
+ output_json(dashboard)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
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
+ lookup_id = options[:lookup_id]
12
+ warn "Fetching lookup table #{lookup_id}..."
13
+ lookup = client.get_lookup(lookup_id: lookup_id)
14
+
15
+ output_json(lookup)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
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
+ monitor_id = options[:monitor_id]
12
+ warn "Fetching monitor #{monitor_id}..."
13
+ monitor = client.get_monitor(monitor_id: monitor_id)
14
+
15
+ output_json(monitor)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
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
+ warn 'Fetching app catalog...'
12
+ apps = client.list_apps
13
+
14
+ output_json(
15
+ total: apps.size,
16
+ apps: apps
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -13,7 +13,7 @@ module Sumologic
13
13
 
14
14
  output_json(
15
15
  total: collectors.size,
16
- collectors: collectors.map { |c| format_collector(c) }
16
+ collectors: collectors
17
17
  )
18
18
  end
19
19
  end
@@ -0,0 +1,22 @@
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
+ warn 'Fetching dashboards...'
12
+ dashboards = client.list_dashboards(limit: options[:limit] || 100)
13
+
14
+ output_json(
15
+ total: dashboards.size,
16
+ dashboards: dashboards
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ 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,22 @@
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
+ warn 'Fetching health events...'
12
+ events = client.list_health_events(limit: options[:limit] || 100)
13
+
14
+ output_json(
15
+ total: events.size,
16
+ healthEvents: events
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ 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-monitors command execution
9
+ # Uses the monitors search API for flat, filterable results
10
+ class ListMonitorsCommand < BaseCommand
11
+ def execute
12
+ warn 'Fetching monitors...'
13
+ monitors = client.list_monitors(
14
+ query: options[:query],
15
+ status: options[:status],
16
+ limit: options[:limit] || 100
17
+ )
18
+
19
+ output_json(
20
+ total: monitors.size,
21
+ monitors: monitors
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+ 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.map { |s| format_source(s) }
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.map { |item| format_collector_with_sources(item) }
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
@@ -52,36 +52,74 @@ module Sumologic
52
52
  end
53
53
 
54
54
  def perform_search
55
- client.search(
56
- query: options[:query],
57
- from_time: @parsed_from,
58
- to_time: @parsed_to,
59
- time_zone: @parsed_timezone,
60
- limit: options[:limit]
61
- )
55
+ if aggregate_mode?
56
+ client.search_aggregation(
57
+ query: options[:query],
58
+ from_time: @parsed_from,
59
+ to_time: @parsed_to,
60
+ time_zone: @parsed_timezone,
61
+ limit: options[:limit]
62
+ )
63
+ else
64
+ client.search(
65
+ query: options[:query],
66
+ from_time: @parsed_from,
67
+ to_time: @parsed_to,
68
+ time_zone: @parsed_timezone,
69
+ limit: options[:limit]
70
+ )
71
+ end
72
+ end
73
+
74
+ def aggregate_mode?
75
+ options[:aggregate] || aggregation_query?(options[:query])
76
+ end
77
+
78
+ def aggregation_query?(query)
79
+ query.match?(/\|\s*(count|sum|avg|min|max|pct|first|last|group)\b/i)
62
80
  end
63
81
 
64
82
  def display_results_summary(results)
83
+ result_type = aggregate_mode? ? 'records' : 'messages'
65
84
  warn '=' * 60
66
- warn "Results: #{results.size} messages"
85
+ warn "Results: #{results.size} #{result_type}"
67
86
  warn '=' * 60
68
87
  $stderr.puts
69
88
  end
70
89
 
71
90
  def output_search_results(results)
72
- output_json(
73
- query: options[:query],
74
- from: @parsed_from,
75
- to: @parsed_to,
76
- from_original: @original_from,
77
- to_original: @original_to,
78
- time_zone: @parsed_timezone,
79
- message_count: results.size,
80
- messages: results
81
- )
91
+ if aggregate_mode?
92
+ output_json(
93
+ query: options[:query],
94
+ from: @parsed_from,
95
+ to: @parsed_to,
96
+ from_original: @original_from,
97
+ to_original: @original_to,
98
+ time_zone: @parsed_timezone,
99
+ record_count: results.size,
100
+ records: results
101
+ )
102
+ else
103
+ output_json(
104
+ query: options[:query],
105
+ from: @parsed_from,
106
+ to: @parsed_to,
107
+ from_original: @original_from,
108
+ to_original: @original_to,
109
+ time_zone: @parsed_timezone,
110
+ message_count: results.size,
111
+ messages: results
112
+ )
113
+ end
82
114
  end
83
115
 
84
116
  def launch_interactive_mode(results)
117
+ if aggregate_mode?
118
+ warn 'Interactive mode is not supported for aggregation queries'
119
+ output_search_results(results)
120
+ return
121
+ end
122
+
85
123
  require_relative '../../interactive'
86
124
 
87
125
  formatted_results = build_formatted_results(results)