catocli 3.0.25__py3-none-any.whl → 3.0.29__py3-none-any.whl

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.

Potentially problematic release.


This version of catocli might be problematic. Click here for more details.

Files changed (33) hide show
  1. catocli/Utils/clidriver.py +6 -6
  2. catocli/Utils/formatter_utils.py +0 -11
  3. catocli/Utils/help_formatter.py +145 -56
  4. catocli/__init__.py +1 -1
  5. catocli/clisettings.json +2 -1
  6. catocli/parsers/query_accountMetrics/README.md +64 -17
  7. catocli/parsers/query_appStats/README.md +127 -0
  8. catocli/parsers/query_appStatsTimeSeries/README.md +110 -26
  9. catocli/parsers/query_container/__init__.py +118 -10
  10. catocli/parsers/query_container_fqdn_downloadFile/README.md +27 -0
  11. catocli/parsers/query_container_fqdn_search/README.md +29 -0
  12. catocli/parsers/query_container_fqdn_searchFqdn/README.md +26 -0
  13. catocli/parsers/query_container_ipAddressRange_downloadFile/README.md +27 -0
  14. catocli/parsers/query_container_ipAddressRange_search/README.md +29 -0
  15. catocli/parsers/query_container_ipAddressRange_searchIpAddressRange/README.md +29 -0
  16. catocli/parsers/query_container_list/README.md +30 -0
  17. catocli/parsers/query_eventsTimeSeries/README.md +36 -59
  18. catocli/parsers/query_socketPortMetrics/README.md +64 -0
  19. catocli/parsers/query_socketPortMetricsTimeSeries/README.md +177 -18
  20. {catocli-3.0.25.dist-info → catocli-3.0.29.dist-info}/METADATA +16 -8
  21. {catocli-3.0.25.dist-info → catocli-3.0.29.dist-info}/RECORD +32 -19
  22. models/query.container.fqdn.downloadFile.json +519 -0
  23. models/query.container.fqdn.search.json +790 -0
  24. models/query.container.fqdn.searchFqdn.json +567 -0
  25. models/query.container.ipAddressRange.downloadFile.json +519 -0
  26. models/query.container.ipAddressRange.search.json +790 -0
  27. models/query.container.ipAddressRange.searchIpAddressRange.json +720 -0
  28. models/query.container.list.json +1316 -0
  29. catocli/parsers/query_container/README.md +0 -65
  30. {catocli-3.0.25.dist-info → catocli-3.0.29.dist-info}/WHEEL +0 -0
  31. {catocli-3.0.25.dist-info → catocli-3.0.29.dist-info}/entry_points.txt +0 -0
  32. {catocli-3.0.25.dist-info → catocli-3.0.29.dist-info}/licenses/LICENSE +0 -0
  33. {catocli-3.0.25.dist-info → catocli-3.0.29.dist-info}/top_level.txt +0 -0
@@ -29,7 +29,6 @@ from ..parsers.query_hardwareManagement import query_hardwareManagement_parse
29
29
  from ..parsers.query_events import query_events_parse
30
30
  from ..parsers.query_eventsTimeSeries import query_eventsTimeSeries_parse
31
31
  from ..parsers.query_auditFeed import query_auditFeed_parse
32
- from ..parsers.query_container import query_container_parse
33
32
  from ..parsers.query_admins import query_admins_parse
34
33
  from ..parsers.query_entityLookup import query_entityLookup_parse
35
34
  from ..parsers.query_accountRoles import query_accountRoles_parse
@@ -50,12 +49,13 @@ from ..parsers.query_accountSnapshot import query_accountSnapshot_parse
50
49
  from ..parsers.query_catalogs import query_catalogs_parse
51
50
  from ..parsers.query_xdr import query_xdr_parse
52
51
  from ..parsers.query_site import query_site_parse
53
- from ..parsers.query_policy import query_policy_parse
54
52
  from ..parsers.query_groups import query_groups_parse
53
+ from ..parsers.query_container import query_container_parse
54
+ from ..parsers.query_policy import query_policy_parse
55
55
  from ..parsers.mutation_xdr import mutation_xdr_parse
56
56
  from ..parsers.mutation_site import mutation_site_parse
57
- from ..parsers.mutation_policy import mutation_policy_parse
58
57
  from ..parsers.mutation_sites import mutation_sites_parse
58
+ from ..parsers.mutation_policy import mutation_policy_parse
59
59
  from ..parsers.mutation_container import mutation_container_parse
60
60
  from ..parsers.mutation_admin import mutation_admin_parse
61
61
  from ..parsers.mutation_accountManagement import mutation_accountManagement_parse
@@ -164,7 +164,6 @@ query_hardwareManagement_parser = query_hardwareManagement_parse(query_subparser
164
164
  query_events_parser = query_events_parse(query_subparsers)
165
165
  query_eventsTimeSeries_parser = query_eventsTimeSeries_parse(query_subparsers)
166
166
  query_auditFeed_parser = query_auditFeed_parse(query_subparsers)
167
- query_container_parser = query_container_parse(query_subparsers)
168
167
  query_admins_parser = query_admins_parse(query_subparsers)
169
168
  query_entityLookup_parser = query_entityLookup_parse(query_subparsers)
170
169
  query_accountRoles_parser = query_accountRoles_parse(query_subparsers)
@@ -185,12 +184,13 @@ query_accountSnapshot_parser = query_accountSnapshot_parse(query_subparsers)
185
184
  query_catalogs_parser = query_catalogs_parse(query_subparsers)
186
185
  query_xdr_parser = query_xdr_parse(query_subparsers)
187
186
  query_site_parser = query_site_parse(query_subparsers)
188
- query_policy_parser = query_policy_parse(query_subparsers)
189
187
  query_groups_parser = query_groups_parse(query_subparsers)
188
+ query_container_parser = query_container_parse(query_subparsers)
189
+ query_policy_parser = query_policy_parse(query_subparsers)
190
190
  mutation_xdr_parser = mutation_xdr_parse(mutation_subparsers)
191
191
  mutation_site_parser = mutation_site_parse(mutation_subparsers)
192
- mutation_policy_parser = mutation_policy_parse(mutation_subparsers)
193
192
  mutation_sites_parser = mutation_sites_parse(mutation_subparsers)
193
+ mutation_policy_parser = mutation_policy_parse(mutation_subparsers)
194
194
  mutation_container_parser = mutation_container_parse(mutation_subparsers)
195
195
  mutation_admin_parser = mutation_admin_parse(mutation_subparsers)
196
196
  mutation_accountManagement_parser = mutation_accountManagement_parse(mutation_subparsers)
@@ -165,17 +165,6 @@ def build_wide_timeseries_header(dimension_names: List[str], measures: List[str]
165
165
  return header
166
166
 
167
167
 
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
168
  def format_to_csv(response_data: Dict[str, Any], operation_name: str) -> str:
180
169
  """
181
170
  Main function to format response data to CSV based on operation type
@@ -82,19 +82,33 @@ class JSONExample:
82
82
  """Format the JSON example for the specific platform - show only the best format"""
83
83
  if platform_info.platform == 'windows':
84
84
  if platform_info.shell == 'powershell':
85
- # For PowerShell, show multiple options to work around quote stripping issues
85
+ # For PowerShell, show here-string format
86
86
  return self._format_powershell_comprehensive(command_name)
87
87
  else:
88
88
  # For cmd, use single-line with escaped quotes
89
89
  single_line = json.dumps(self.parsed_json) if self.parsed_json else self.json_data.replace('\n', ' ')
90
90
  escaped_json = single_line.replace('"', '\\"')
91
- return [f'catocli {command_name} "{escaped_json}" -p']
91
+ # Extract flags from command template
92
+ flags = self._extract_flags_from_template()
93
+ return [f'catocli {command_name} "{escaped_json}" {flags}'.strip()]
92
94
  else:
93
- # For Unix-like systems, use multi-line
95
+ # For Unix-like systems, use multi-line with proper formatting
94
96
  return [self.command_template.format(command=command_name, json=self.json_data)]
95
97
 
98
+ def _extract_flags_from_template(self) -> str:
99
+ """Extract flags from the command template (everything after {json})"""
100
+ # Extract everything after '{json}' in the template
101
+ if "'{json}'" in self.command_template:
102
+ parts = self.command_template.split("'{json}'")
103
+ if len(parts) > 1:
104
+ return parts[1].strip()
105
+ return ""
106
+
96
107
  def _format_powershell_comprehensive(self, command_name: str) -> List[str]:
97
108
  """Format PowerShell here-string example with proper quote escaping"""
109
+ # Extract flags from command template
110
+ flags = self._extract_flags_from_template()
111
+
98
112
  # Escape double quotes in JSON for PowerShell compatibility
99
113
  escaped_json = self.json_data.replace('"', '\\"')
100
114
 
@@ -103,7 +117,7 @@ class JSONExample:
103
117
  "# PowerShell (using here-string):",
104
118
  f"catocli {command_name} @'",
105
119
  escaped_json,
106
- "'@ -p"
120
+ f"'@ {flags}".strip() if flags else "'@"
107
121
  ]
108
122
 
109
123
  return examples
@@ -227,52 +241,94 @@ class UniversalHelpFormatter:
227
241
  readme_examples = self._extract_from_readme(command_path)
228
242
  if readme_examples:
229
243
  for example in readme_examples:
230
- # Check if this example starts with a comment (lines starting with #)
231
- if example.startswith('#') and '\n' in example:
232
- # This is a comment followed by a command - need to format the command part
244
+ # Check if this is a header or description line (not a command)
245
+ if example.startswith('###') or (example.startswith('-') and 'catocli' not in example):
246
+ # This is a header or description - preserve as-is
247
+ help_lines.append(example)
248
+ continue
249
+
250
+ # Check if this example starts with a comment followed by a command
251
+ if example.startswith('#') and '\n' in example and 'catocli' in example:
252
+ # This is a comment followed by a command - extract both parts
233
253
  lines = example.split('\n', 1)
234
254
  if len(lines) == 2:
235
255
  comment_line = lines[0]
236
- command_line = lines[1]
256
+ command_part = lines[1]
237
257
 
238
- # Check if command has JSON and format appropriately
239
- if '{' in command_line and '}' in command_line:
240
- json_match = self._extract_json_from_example(command_line)
258
+ # Check if command has multi-line JSON and format appropriately
259
+ if "'{" in command_part and "}'" in command_part:
260
+ json_match = self._extract_json_from_example(command_part)
241
261
  if json_match:
262
+ # Extract command flags (everything after }')
263
+ flags = ""
264
+ if "}'" in command_part:
265
+ flags_match = re.search(r"}'\s*(.*)$", command_part, re.MULTILINE)
266
+ if flags_match:
267
+ flags = flags_match.group(1).strip()
268
+
269
+ # Create command template with flags
270
+ if flags:
271
+ command_template = f"catocli {{command}} '{{json}}' {flags}"
272
+ else:
273
+ command_template = "catocli {command} '{json}'"
274
+
242
275
  # Create JSONExample and apply platform-specific formatting
243
- json_example = JSONExample(json_match)
276
+ json_example = JSONExample(json_match, command_template)
244
277
  formatted_commands = json_example.format_for_platform(self.platform_info, command_name)
245
278
  # Add comment first, then formatted commands
246
279
  help_lines.append(comment_line)
247
280
  help_lines.extend(formatted_commands)
248
281
  else:
249
282
  # JSON extraction failed, format as simple command
250
- formatted_command = self._format_simple_command_for_platform(command_line)
283
+ formatted_command = self._format_simple_command_for_platform(command_part)
251
284
  help_lines.append(comment_line)
252
285
  help_lines.append(formatted_command)
253
286
  else:
254
287
  # Simple command - apply platform formatting
255
- formatted_command = self._format_simple_command_for_platform(command_line)
288
+ formatted_command = self._format_simple_command_for_platform(command_part)
256
289
  help_lines.append(comment_line)
257
290
  help_lines.append(formatted_command)
258
291
  else:
259
292
  # Fallback - preserve as-is
260
293
  help_lines.append(example)
261
- elif '{' in example and '}' in example:
262
- # Check if this is a multi-line JSON example that can be platform-formatted
263
- json_match = self._extract_json_from_example(example)
264
- if json_match and not example.startswith('#'):
265
- # Create JSONExample and apply platform-specific formatting
266
- json_example = JSONExample(json_match)
267
- formatted_examples = json_example.format_for_platform(self.platform_info, command_name)
268
- help_lines.extend(formatted_examples)
294
+ elif 'catocli' in example and '{' in example and '}' in example:
295
+ # This is a catocli command with JSON - check if multi-line
296
+ if '\n' in example and "'{" in example:
297
+ # Multi-line JSON command
298
+ json_match = self._extract_json_from_example(example)
299
+ if json_match:
300
+ # Extract command flags (everything after }')
301
+ flags = ""
302
+ if "}'" in example:
303
+ flags_match = re.search(r"}'\s*(.*)$", example, re.MULTILINE)
304
+ if flags_match:
305
+ flags = flags_match.group(1).strip()
306
+
307
+ # Create command template with flags
308
+ if flags:
309
+ command_template = f"catocli {{command}} '{{json}}' {flags}"
310
+ else:
311
+ command_template = "catocli {command} '{json}'"
312
+
313
+ # Create JSONExample and apply platform-specific formatting
314
+ json_example = JSONExample(json_match, command_template)
315
+ formatted_examples = json_example.format_for_platform(self.platform_info, command_name)
316
+ help_lines.extend(formatted_examples)
317
+ else:
318
+ # Preserve as-is if JSON extraction fails
319
+ help_lines.append(example)
269
320
  else:
270
- # Preserve as-is if it has comments or JSON extraction fails
271
- help_lines.append(example)
321
+ # Single-line command with JSON - format as simple command
322
+ formatted_example = self._format_simple_command_for_platform(example)
323
+ help_lines.append(formatted_example)
272
324
  else:
273
- # Simple command examples without JSON - apply platform formatting
274
- formatted_example = self._format_simple_command_for_platform(example)
275
- help_lines.append(formatted_example)
325
+ # Simple command examples without JSON or description text - apply platform formatting
326
+ if 'catocli' in example:
327
+ formatted_example = self._format_simple_command_for_platform(example)
328
+ help_lines.append(formatted_example)
329
+ else:
330
+ # Not a command - preserve as-is (likely description text)
331
+ help_lines.append(example)
276
332
  help_lines.append("") # Add spacing between examples
277
333
 
278
334
  description_examples = []
@@ -307,7 +363,7 @@ class UniversalHelpFormatter:
307
363
  return "\n".join(help_lines)
308
364
 
309
365
  def _extract_from_readme(self, command_path: str) -> List[str]:
310
- """Extract all catocli examples from README.md files with comments"""
366
+ """Extract catocli examples from README.md files, prioritizing Additional Examples section"""
311
367
  examples = []
312
368
 
313
369
  # Find README.md file
@@ -328,21 +384,48 @@ class UniversalHelpFormatter:
328
384
 
329
385
  command_name = command_path.replace('_', ' ')
330
386
 
331
- # Check if "### Examples Summary" or "### Additional Examples" sections exist
332
- has_examples_summary = "### Examples Summary" in content or "### Additional Examples" in content
333
- if has_examples_summary:
334
- # Extract and display the examples summary section
335
- summary_pattern = r'### (?:Examples Summary|Additional Examples)\n(.*?)(?=\n###|\n## |\Z)'
336
- summary_match = re.search(summary_pattern, content, re.DOTALL)
337
- if summary_match:
338
- summary_content = summary_match.group(1).strip()
339
- examples.append(f"\n### Examples Summary")
340
- examples.append(summary_content)
387
+ # Check if "## Advanced Usage" or "### Additional Examples" section exists
388
+ has_advanced_usage = "## Advanced Usage" in content
389
+ has_additional_examples = "### Additional Examples" in content
390
+
391
+ # Define content to parse
392
+ content_to_parse = content
393
+ if has_advanced_usage:
394
+ # Extract the Advanced Usage section (up to #### which is next level heading)
395
+ advanced_pattern = r'## Advanced Usage\n(.*?)(?=\n####|\Z)'
396
+ advanced_match = re.search(advanced_pattern, content, re.DOTALL)
397
+ if advanced_match:
398
+ content_to_parse = advanced_match.group(1)
399
+ # Add a header for the examples
400
+ examples.append("### Examples")
401
+ # Extract list items from Additional Examples intro (before first # heading)
402
+ intro_pattern = r'### Additional Examples\n(.*?)(?=\n#[^#])'
403
+ intro_match = re.search(intro_pattern, content_to_parse, re.DOTALL)
404
+ if intro_match and intro_match.group(1).strip():
405
+ intro_text = intro_match.group(1).strip()
406
+ # Only add if it contains bullet points or descriptions
407
+ if '-' in intro_text:
408
+ examples.append(intro_text)
409
+ examples.append("") # Add spacing
410
+ elif has_additional_examples:
411
+ # Fallback: Extract only the Additional Examples section
412
+ additional_pattern = r'### Additional Examples\n(.*?)(?=\n####|\n## |\Z)'
413
+ additional_match = re.search(additional_pattern, content, re.DOTALL)
414
+ if additional_match:
415
+ content_to_parse = additional_match.group(1)
416
+ examples.append("### Examples")
417
+ # Extract list items from the section intro
418
+ intro_pattern = r'^(.*?)(?=\n#[^#])'
419
+ intro_match = re.search(intro_pattern, content_to_parse, re.DOTALL)
420
+ if intro_match and intro_match.group(1).strip():
421
+ intro_text = intro_match.group(1).strip()
422
+ if '-' in intro_text:
423
+ examples.append(intro_text)
341
424
  examples.append("") # Add spacing
342
425
 
343
- # Extract ALL catocli commands from markdown code blocks
426
+ # Extract catocli commands from markdown code blocks
344
427
  code_block_pattern = r'```(?:bash|shell|json)?\n(.*?)```'
345
- matches = re.findall(code_block_pattern, content, re.DOTALL)
428
+ matches = re.findall(code_block_pattern, content_to_parse, re.DOTALL)
346
429
 
347
430
  for match in matches:
348
431
  # Split the match into individual lines and extract catocli commands with comments
@@ -375,10 +458,14 @@ class UniversalHelpFormatter:
375
458
  # Keep the full command line including the opening bracket
376
459
  elif in_multiline_json and current_command:
377
460
  # We're in a multi-line JSON block - preserve exact formatting
378
- if stripped_line == "}'":
379
- # End of multi-line JSON
461
+ if "}'" in stripped_line:
462
+ # End of multi-line JSON - include any flags after }'
380
463
  current_command += '\n' + line
381
464
  in_multiline_json = False
465
+ # Append the completed command
466
+ examples.append(current_command)
467
+ current_command = None
468
+ current_comment = None
382
469
  else:
383
470
  # Continue multi-line JSON with exact indentation
384
471
  current_command += '\n' + line
@@ -402,13 +489,14 @@ class UniversalHelpFormatter:
402
489
  if current_command and not in_multiline_json:
403
490
  examples.append(current_command)
404
491
 
405
- # Also look for inline catocli commands (in backticks)
406
- inline_pattern = r'`(catocli[^`]+)`'
407
- inline_matches = re.findall(inline_pattern, content)
408
-
409
- for cmd in inline_matches:
410
- if command_name in cmd and cmd not in examples:
411
- examples.append(cmd)
492
+ # If no Additional Examples section was found, also look for inline catocli commands (in backticks)
493
+ if not has_additional_examples:
494
+ inline_pattern = r'`(catocli[^`]+)`'
495
+ inline_matches = re.findall(inline_pattern, content)
496
+
497
+ for cmd in inline_matches:
498
+ if command_name in cmd and cmd not in examples:
499
+ examples.append(cmd)
412
500
 
413
501
  except Exception as e:
414
502
  print(f"Warning: Could not parse README for {command_path}: {e}")
@@ -465,20 +553,21 @@ class UniversalHelpFormatter:
465
553
  def _extract_json_from_example(self, example: str) -> str:
466
554
  """Extract JSON data from a catocli command example"""
467
555
  try:
468
- # Look for JSON in single quotes first (most common)
469
- single_quote_pattern = r"catocli[^']*'([^']+)'"
470
- match = re.search(single_quote_pattern, example)
556
+ # Look for multi-line JSON first (between '{ and }' with potential flags after)
557
+ # This pattern captures everything between '{ and }' (non-greedy)
558
+ multiline_pattern = r"'(\{[\s\S]*?\})'(?:\s+[-\w])*"
559
+ match = re.search(multiline_pattern, example)
471
560
  if match:
472
561
  json_str = match.group(1)
473
562
  # Validate it's JSON by trying to parse it
474
563
  json.loads(json_str)
475
564
  return json_str
476
565
 
477
- # Look for multi-line JSON (between '{ and }')
478
- multiline_pattern = r"'\{([\s\S]*?)\}'"
479
- match = re.search(multiline_pattern, example)
566
+ # Fallback to simple single-line JSON in single quotes
567
+ single_quote_pattern = r"catocli[^']*'([^']+)'"
568
+ match = re.search(single_quote_pattern, example)
480
569
  if match:
481
- json_str = "{" + match.group(1) + "}"
570
+ json_str = match.group(1)
482
571
  # Validate it's JSON by trying to parse it
483
572
  json.loads(json_str)
484
573
  return json_str
catocli/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "3.0.25"
1
+ __version__ = "3.0.29"
2
2
  __cato_host__ = "https://api.catonetworks.com/api/v1/graphql2"
catocli/clisettings.json CHANGED
@@ -16,7 +16,8 @@
16
16
  "policy": true,
17
17
  "groups": true,
18
18
  "newGroups": true,
19
- "site": true
19
+ "site": true,
20
+ "container": true
20
21
  },
21
22
  "childOperationObjects": {
22
23
  "ipAddressRange": true,
@@ -42,7 +42,10 @@ catocli query accountMetrics '{
42
42
  ### Additional Examples
43
43
  - Example all values and lables
44
44
  - Example all values and lables for a single account
45
- - Example all values and lables for a single user
45
+ - Monitor all key performance indicators for a specific site:
46
+ - Analyze network performance for specific users:
47
+ - Get a simple health snapshot without filters:
48
+ - Focus on bandwidth utilization with packet loss metrics
46
49
  - Last hour no filters
47
50
 
48
51
  # Example all values and lables
@@ -88,34 +91,78 @@ catocli query accountMetrics '{
88
91
  }'
89
92
  ```
90
93
 
91
- # Example all values and lables for a single user
94
+ # Monitor all key performance indicators for a specific site:
92
95
 
93
96
  ```bash
94
- # Example all values and lables for a single user
97
+ # Monitor all key performance indicators for a specific site:
95
98
  catocli query accountMetrics '{
96
99
  "buckets": 24,
100
+ "groupDevices": true,
101
+ "groupInterfaces": true,
97
102
  "labels": [
103
+ "bytesDownstream",
104
+ "bytesUpstream",
98
105
  "health",
99
- "jitterDownstream",
106
+ "lastMileLatency",
107
+ "lastMilePacketLoss",
108
+ "rtt"
109
+ ],
110
+ "siteIDs": ["132814"],
111
+ "timeFrame": "last.P1D",
112
+ "perSecond": true,
113
+ "toRate": true
114
+ }' -f csv --csv-filename=accountmetrics_site.csv
115
+ ```
116
+
117
+ # Analyze network performance for specific users:
118
+
119
+ ```bash
120
+ # Analyze network performance for specific users:
121
+ catocli query accountMetrics '{
122
+ "buckets": 24,
123
+ "labels": [
124
+ "health",
125
+ "jitterDownstream",
100
126
  "jitterUpstream",
101
127
  "lastMileLatency",
102
128
  "lastMilePacketLoss",
103
- "lostDownstream",
104
- "lostDownstreamPcnt",
105
- "lostUpstream",
106
- "lostUpstreamPcnt",
107
- "packetsDiscardedDownstream",
108
- "packetsDiscardedDownstreamPcnt",
109
- "packetsDiscardedUpstream",
110
- "packetsDiscardedUpstreamPcnt",
111
129
  "packetsDownstream",
112
130
  "packetsUpstream"
113
131
  ],
114
- "timeFrame": "last.PT1H",
115
- "userIDs": [
116
- "0"
117
- ]
118
- }'
132
+ "timeFrame": "last.P1D",
133
+ "userIDs": ["1000000"]
134
+ }' -f csv --csv-filename=accountmetrics_user.csv
135
+ ```
136
+
137
+ # Get a simple health snapshot without filters:
138
+
139
+ ```bash
140
+ # Get a simple health snapshot without filters:
141
+ catocli query accountMetrics '{
142
+ "timeFrame": "last.PT1H"
143
+ }' -f csv --csv-filename=accountmetrics_health.csv
144
+ ```
145
+
146
+ # Focus on bandwidth utilization with packet loss metrics
147
+
148
+ ```bash
149
+ # Focus on bandwidth utilization with packet loss metrics
150
+ catocli query accountMetrics '{
151
+ "buckets": 48,
152
+ "labels": [
153
+ "bytesDownstream",
154
+ "bytesUpstream",
155
+ "bytesTotal",
156
+ "bytesDownstreamMax",
157
+ "bytesUpstreamMax",
158
+ "lostDownstreamPcnt",
159
+ "lostUpstreamPcnt"
160
+ ],
161
+ "siteIDs": ["132814"],
162
+ "timeFrame": "last.P2D",
163
+ "perSecond": true,
164
+ "withMissingData": true
165
+ }' -f csv --csv-filename=accountmetrics_packet_loss.csv
119
166
  ```
120
167
 
121
168
  # Last hour no filters
@@ -44,6 +44,12 @@ catocli query appStats '{
44
44
  ### Additional Examples
45
45
  - Query to export user activity as in flows_created, for distinct users (user_name) for the last day
46
46
  - Query to export application_name, user_name and risk_score with traffic sum(upstream, downstream, trafffic) for last day
47
+ - Track daily user engagement and flow creation
48
+ - Analyze applications by usage and security risk
49
+ - Analyze applications by usage and security risk:
50
+ - Top applications weekly by bandwidth
51
+ - Daily per-user bandwidth consumption
52
+ - Monthly traffic patterns by country
47
53
 
48
54
  # Query to export user activity as in flows_created, for distinct users (user_name) for the last day
49
55
 
@@ -107,6 +113,127 @@ catocli query appStats '{
107
113
  }' -f csv --csv-filename app_user_account_metrics_report.csv
108
114
  ```
109
115
 
116
+ # Track daily user engagement and flow creation
117
+
118
+ ```bash
119
+ # Track daily user engagement and flow creation
120
+ catocli query appStats '{
121
+ "dimension": [
122
+ {"fieldName": "user_name"},
123
+ {"fieldName": "domain"}
124
+ ],
125
+ "measure": [
126
+ {"aggType": "sum", "fieldName": "flows_created"},
127
+ {"aggType": "count_distinct", "fieldName": "user_name"},
128
+ {"aggType": "sum", "fieldName": "traffic"}
129
+ ],
130
+ "timeFrame": "last.P1D"
131
+ }' -f csv --csv-filename=appstats_user_activity.csv
132
+ ```
133
+
134
+ # Analyze applications by usage and security risk
135
+
136
+ ```bash
137
+ # Analyze applications by usage and security risk:
138
+ catocli query appStats '{
139
+ "dimension": [
140
+ {"fieldName": "application_name"},
141
+ {"fieldName": "user_name"},
142
+ {"fieldName": "risk_score"}
143
+ ],
144
+ "measure": [
145
+ {"aggType": "sum", "fieldName": "downstream"},
146
+ {"aggType": "sum", "fieldName": "upstream"},
147
+ {"aggType": "sum", "fieldName": "traffic"}
148
+ ],
149
+ "timeFrame": "last.P1D"
150
+ }' -f csv --csv-filename=appstats_user_risk_report.csv
151
+ ```
152
+
153
+ # Top applications weekly by bandwidth
154
+
155
+ ```bash
156
+ # Top applications weekly by bandwidth
157
+ catocli query appStats '{
158
+ "dimension": [{"fieldName": "application_name"}],
159
+ "measure": [
160
+ {"aggType": "sum", "fieldName": "traffic"},
161
+ {"aggType": "sum", "fieldName": "flows_created"}
162
+ ],
163
+ "appStatsSort": [
164
+ {"fieldName": "traffic", "order": "desc"}
165
+ ],
166
+ "timeFrame": "last.P7D"
167
+ }' -f csv --csv-filename=appstats_app_utilization.csv
168
+ ```
169
+
170
+ # Daily per-user bandwidth consumption
171
+
172
+ ```bash
173
+ # Daily per-user bandwidth consumption
174
+ catocli query appStats '{
175
+ "dimension": [
176
+ {"fieldName": "user_name"}
177
+ ],
178
+ "measure": [
179
+ {"aggType": "sum", "fieldName": "downstream"},
180
+ {"aggType": "sum", "fieldName": "upstream"},
181
+ {"aggType": "sum", "fieldName": "traffic"},
182
+ {"aggType": "sum", "fieldName": "flows_created"}
183
+ ],
184
+ "timeFrame": "last.P1D"
185
+ }' -f csv --csv-filename=appstats_user_bw.csv
186
+ ```
187
+
188
+ ### 5. High-Risk Application Analysis
189
+
190
+ Focus on applications with elevated risk scores:
191
+
192
+ ```bash
193
+ catocli query appStats '{
194
+ "appStatsFilter": [
195
+ {
196
+ "fieldName": "risk_score",
197
+ "operator": "gte",
198
+ "values": ["5"]
199
+ }
200
+ ],
201
+ "appStatsSort": [
202
+ {
203
+ "fieldName": "risk_score",
204
+ "order": "desc"
205
+ }
206
+ ],
207
+ "dimension": [
208
+ {"fieldName": "application_name"},
209
+ {"fieldName": "risk_score"},
210
+ {"fieldName": "user_name"}
211
+ ],
212
+ "measure": [
213
+ {"aggType": "sum", "fieldName": "traffic"},
214
+ {"aggType": "sum", "fieldName": "flows_created"}
215
+ ],
216
+ "timeFrame": "last.P7D"
217
+ }' -f csv --csv-filename=appstats_app_by_risk.csv
218
+ ```
219
+
220
+ # Monthly traffic patterns by country
221
+
222
+ ```bash
223
+ # Monthly traffic patterns by country
224
+ catocli query appStats '{
225
+ "dimension": [
226
+ {"fieldName": "site_country"},
227
+ {"fieldName": "src_site_country_code"}
228
+ ],
229
+ "measure": [
230
+ {"aggType": "sum", "fieldName": "traffic"},
231
+ {"aggType": "count_distinct", "fieldName": "user_name"}
232
+ ],
233
+ "timeFrame": "last.P1M"
234
+ }' -f csv --csv-filename=appstats_by_country.csv
235
+ ```
236
+
110
237
 
111
238
 
112
239