catocli 3.0.26__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.
- catocli/Utils/clidriver.py +10 -10
- catocli/Utils/formatter_utils.py +0 -11
- catocli/Utils/help_formatter.py +145 -56
- catocli/__init__.py +1 -1
- catocli/parsers/query_accountMetrics/README.md +64 -17
- catocli/parsers/query_appStats/README.md +127 -0
- catocli/parsers/query_appStatsTimeSeries/README.md +110 -26
- catocli/parsers/query_eventsTimeSeries/README.md +36 -59
- catocli/parsers/query_socketPortMetrics/README.md +64 -0
- catocli/parsers/query_socketPortMetricsTimeSeries/README.md +177 -18
- {catocli-3.0.26.dist-info → catocli-3.0.29.dist-info}/METADATA +16 -8
- {catocli-3.0.26.dist-info → catocli-3.0.29.dist-info}/RECORD +16 -16
- {catocli-3.0.26.dist-info → catocli-3.0.29.dist-info}/WHEEL +0 -0
- {catocli-3.0.26.dist-info → catocli-3.0.29.dist-info}/entry_points.txt +0 -0
- {catocli-3.0.26.dist-info → catocli-3.0.29.dist-info}/licenses/LICENSE +0 -0
- {catocli-3.0.26.dist-info → catocli-3.0.29.dist-info}/top_level.txt +0 -0
catocli/Utils/clidriver.py
CHANGED
|
@@ -47,16 +47,16 @@ from ..parsers.query_enterpriseDirectory import query_enterpriseDirectory_parse
|
|
|
47
47
|
from ..parsers.query_devices import query_devices_parse
|
|
48
48
|
from ..parsers.query_accountSnapshot import query_accountSnapshot_parse
|
|
49
49
|
from ..parsers.query_catalogs import query_catalogs_parse
|
|
50
|
-
from ..parsers.query_site import query_site_parse
|
|
51
50
|
from ..parsers.query_xdr import query_xdr_parse
|
|
52
|
-
from ..parsers.
|
|
53
|
-
from ..parsers.query_container import query_container_parse
|
|
51
|
+
from ..parsers.query_site import query_site_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
|
-
from ..parsers.mutation_sites import mutation_sites_parse
|
|
57
|
-
from ..parsers.mutation_container import mutation_container_parse
|
|
58
56
|
from ..parsers.mutation_site import mutation_site_parse
|
|
57
|
+
from ..parsers.mutation_sites import mutation_sites_parse
|
|
59
58
|
from ..parsers.mutation_policy import mutation_policy_parse
|
|
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
|
|
62
62
|
from ..parsers.mutation_sandbox import mutation_sandbox_parse
|
|
@@ -182,16 +182,16 @@ query_enterpriseDirectory_parser = query_enterpriseDirectory_parse(query_subpars
|
|
|
182
182
|
query_devices_parser = query_devices_parse(query_subparsers)
|
|
183
183
|
query_accountSnapshot_parser = query_accountSnapshot_parse(query_subparsers)
|
|
184
184
|
query_catalogs_parser = query_catalogs_parse(query_subparsers)
|
|
185
|
-
query_site_parser = query_site_parse(query_subparsers)
|
|
186
185
|
query_xdr_parser = query_xdr_parse(query_subparsers)
|
|
187
|
-
|
|
188
|
-
query_container_parser = query_container_parse(query_subparsers)
|
|
186
|
+
query_site_parser = query_site_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
|
-
mutation_sites_parser = mutation_sites_parse(mutation_subparsers)
|
|
192
|
-
mutation_container_parser = mutation_container_parse(mutation_subparsers)
|
|
193
191
|
mutation_site_parser = mutation_site_parse(mutation_subparsers)
|
|
192
|
+
mutation_sites_parser = mutation_sites_parse(mutation_subparsers)
|
|
194
193
|
mutation_policy_parser = mutation_policy_parse(mutation_subparsers)
|
|
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)
|
|
197
197
|
mutation_sandbox_parser = mutation_sandbox_parse(mutation_subparsers)
|
catocli/Utils/formatter_utils.py
CHANGED
|
@@ -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
|
catocli/Utils/help_formatter.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
"'@
|
|
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
|
|
231
|
-
if example.startswith('
|
|
232
|
-
# This is a
|
|
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
|
-
|
|
256
|
+
command_part = lines[1]
|
|
237
257
|
|
|
238
|
-
# Check if command has JSON and format appropriately
|
|
239
|
-
if '{
|
|
240
|
-
json_match = self._extract_json_from_example(
|
|
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(
|
|
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(
|
|
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
|
-
#
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
#
|
|
271
|
-
|
|
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
|
-
|
|
275
|
-
|
|
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
|
|
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 "
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
#
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
examples
|
|
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
|
|
469
|
-
|
|
470
|
-
|
|
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
|
-
#
|
|
478
|
-
|
|
479
|
-
match = re.search(
|
|
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 =
|
|
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.
|
|
1
|
+
__version__ = "3.0.29"
|
|
2
2
|
__cato_host__ = "https://api.catonetworks.com/api/v1/graphql2"
|
|
@@ -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
|
-
-
|
|
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
|
-
#
|
|
94
|
+
# Monitor all key performance indicators for a specific site:
|
|
92
95
|
|
|
93
96
|
```bash
|
|
94
|
-
#
|
|
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
|
-
"
|
|
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.
|
|
115
|
-
"userIDs": [
|
|
116
|
-
|
|
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
|
|