kollabor 0.4.9__py3-none-any.whl → 0.4.15__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.
- agents/__init__.py +2 -0
- agents/coder/__init__.py +0 -0
- agents/coder/agent.json +4 -0
- agents/coder/api-integration.md +2150 -0
- agents/coder/cli-pretty.md +765 -0
- agents/coder/code-review.md +1092 -0
- agents/coder/database-design.md +1525 -0
- agents/coder/debugging.md +1102 -0
- agents/coder/dependency-management.md +1397 -0
- agents/coder/git-workflow.md +1099 -0
- agents/coder/refactoring.md +1454 -0
- agents/coder/security-hardening.md +1732 -0
- agents/coder/system_prompt.md +1448 -0
- agents/coder/tdd.md +1367 -0
- agents/creative-writer/__init__.py +0 -0
- agents/creative-writer/agent.json +4 -0
- agents/creative-writer/character-development.md +1852 -0
- agents/creative-writer/dialogue-craft.md +1122 -0
- agents/creative-writer/plot-structure.md +1073 -0
- agents/creative-writer/revision-editing.md +1484 -0
- agents/creative-writer/system_prompt.md +690 -0
- agents/creative-writer/worldbuilding.md +2049 -0
- agents/data-analyst/__init__.py +30 -0
- agents/data-analyst/agent.json +4 -0
- agents/data-analyst/data-visualization.md +992 -0
- agents/data-analyst/exploratory-data-analysis.md +1110 -0
- agents/data-analyst/pandas-data-manipulation.md +1081 -0
- agents/data-analyst/sql-query-optimization.md +881 -0
- agents/data-analyst/statistical-analysis.md +1118 -0
- agents/data-analyst/system_prompt.md +928 -0
- agents/default/__init__.py +0 -0
- agents/default/agent.json +4 -0
- agents/default/dead-code.md +794 -0
- agents/default/explore-agent-system.md +585 -0
- agents/default/system_prompt.md +1448 -0
- agents/kollabor/__init__.py +0 -0
- agents/kollabor/analyze-plugin-lifecycle.md +175 -0
- agents/kollabor/analyze-terminal-rendering.md +388 -0
- agents/kollabor/code-review.md +1092 -0
- agents/kollabor/debug-mcp-integration.md +521 -0
- agents/kollabor/debug-plugin-hooks.md +547 -0
- agents/kollabor/debugging.md +1102 -0
- agents/kollabor/dependency-management.md +1397 -0
- agents/kollabor/git-workflow.md +1099 -0
- agents/kollabor/inspect-llm-conversation.md +148 -0
- agents/kollabor/monitor-event-bus.md +558 -0
- agents/kollabor/profile-performance.md +576 -0
- agents/kollabor/refactoring.md +1454 -0
- agents/kollabor/system_prompt copy.md +1448 -0
- agents/kollabor/system_prompt.md +757 -0
- agents/kollabor/trace-command-execution.md +178 -0
- agents/kollabor/validate-config.md +879 -0
- agents/research/__init__.py +0 -0
- agents/research/agent.json +4 -0
- agents/research/architecture-mapping.md +1099 -0
- agents/research/codebase-analysis.md +1077 -0
- agents/research/dependency-audit.md +1027 -0
- agents/research/performance-profiling.md +1047 -0
- agents/research/security-review.md +1359 -0
- agents/research/system_prompt.md +492 -0
- agents/technical-writer/__init__.py +0 -0
- agents/technical-writer/agent.json +4 -0
- agents/technical-writer/api-documentation.md +2328 -0
- agents/technical-writer/changelog-management.md +1181 -0
- agents/technical-writer/readme-writing.md +1360 -0
- agents/technical-writer/style-guide.md +1410 -0
- agents/technical-writer/system_prompt.md +653 -0
- agents/technical-writer/tutorial-creation.md +1448 -0
- core/__init__.py +0 -2
- core/application.py +343 -88
- core/cli.py +229 -10
- core/commands/menu_renderer.py +463 -59
- core/commands/registry.py +14 -9
- core/commands/system_commands.py +2461 -14
- core/config/loader.py +151 -37
- core/config/service.py +18 -6
- core/events/bus.py +29 -9
- core/events/executor.py +205 -75
- core/events/models.py +27 -8
- core/fullscreen/command_integration.py +20 -24
- core/fullscreen/components/__init__.py +10 -1
- core/fullscreen/components/matrix_components.py +1 -2
- core/fullscreen/components/space_shooter_components.py +654 -0
- core/fullscreen/plugin.py +5 -0
- core/fullscreen/renderer.py +52 -13
- core/fullscreen/session.py +52 -15
- core/io/__init__.py +29 -5
- core/io/buffer_manager.py +6 -1
- core/io/config_status_view.py +7 -29
- core/io/core_status_views.py +267 -347
- core/io/input/__init__.py +25 -0
- core/io/input/command_mode_handler.py +711 -0
- core/io/input/display_controller.py +128 -0
- core/io/input/hook_registrar.py +286 -0
- core/io/input/input_loop_manager.py +421 -0
- core/io/input/key_press_handler.py +502 -0
- core/io/input/modal_controller.py +1011 -0
- core/io/input/paste_processor.py +339 -0
- core/io/input/status_modal_renderer.py +184 -0
- core/io/input_errors.py +5 -1
- core/io/input_handler.py +211 -2452
- core/io/key_parser.py +7 -0
- core/io/layout.py +15 -3
- core/io/message_coordinator.py +111 -2
- core/io/message_renderer.py +129 -4
- core/io/status_renderer.py +147 -607
- core/io/terminal_renderer.py +97 -51
- core/io/terminal_state.py +21 -4
- core/io/visual_effects.py +816 -165
- core/llm/agent_manager.py +1063 -0
- core/llm/api_adapters/__init__.py +44 -0
- core/llm/api_adapters/anthropic_adapter.py +432 -0
- core/llm/api_adapters/base.py +241 -0
- core/llm/api_adapters/openai_adapter.py +326 -0
- core/llm/api_communication_service.py +167 -113
- core/llm/conversation_logger.py +322 -16
- core/llm/conversation_manager.py +556 -30
- core/llm/file_operations_executor.py +84 -32
- core/llm/llm_service.py +934 -103
- core/llm/mcp_integration.py +541 -57
- core/llm/message_display_service.py +135 -18
- core/llm/plugin_sdk.py +1 -2
- core/llm/profile_manager.py +1183 -0
- core/llm/response_parser.py +274 -56
- core/llm/response_processor.py +16 -3
- core/llm/tool_executor.py +6 -1
- core/logging/__init__.py +2 -0
- core/logging/setup.py +34 -6
- core/models/resume.py +54 -0
- core/plugins/__init__.py +4 -2
- core/plugins/base.py +127 -0
- core/plugins/collector.py +23 -161
- core/plugins/discovery.py +37 -3
- core/plugins/factory.py +6 -12
- core/plugins/registry.py +5 -17
- core/ui/config_widgets.py +128 -28
- core/ui/live_modal_renderer.py +2 -1
- core/ui/modal_actions.py +5 -0
- core/ui/modal_overlay_renderer.py +0 -60
- core/ui/modal_renderer.py +268 -7
- core/ui/modal_state_manager.py +29 -4
- core/ui/widgets/base_widget.py +7 -0
- core/updates/__init__.py +10 -0
- core/updates/version_check_service.py +348 -0
- core/updates/version_comparator.py +103 -0
- core/utils/config_utils.py +685 -526
- core/utils/plugin_utils.py +1 -1
- core/utils/session_naming.py +111 -0
- fonts/LICENSE +21 -0
- fonts/README.md +46 -0
- fonts/SymbolsNerdFont-Regular.ttf +0 -0
- fonts/SymbolsNerdFontMono-Regular.ttf +0 -0
- fonts/__init__.py +44 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/METADATA +54 -4
- kollabor-0.4.15.dist-info/RECORD +228 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/top_level.txt +2 -0
- plugins/agent_orchestrator/__init__.py +39 -0
- plugins/agent_orchestrator/activity_monitor.py +181 -0
- plugins/agent_orchestrator/file_attacher.py +77 -0
- plugins/agent_orchestrator/message_injector.py +135 -0
- plugins/agent_orchestrator/models.py +48 -0
- plugins/agent_orchestrator/orchestrator.py +403 -0
- plugins/agent_orchestrator/plugin.py +976 -0
- plugins/agent_orchestrator/xml_parser.py +191 -0
- plugins/agent_orchestrator_plugin.py +9 -0
- plugins/enhanced_input/box_styles.py +1 -0
- plugins/enhanced_input/color_engine.py +19 -4
- plugins/enhanced_input/config.py +2 -2
- plugins/enhanced_input_plugin.py +61 -11
- plugins/fullscreen/__init__.py +6 -2
- plugins/fullscreen/example_plugin.py +1035 -222
- plugins/fullscreen/setup_wizard_plugin.py +592 -0
- plugins/fullscreen/space_shooter_plugin.py +131 -0
- plugins/hook_monitoring_plugin.py +436 -78
- plugins/query_enhancer_plugin.py +66 -30
- plugins/resume_conversation_plugin.py +1494 -0
- plugins/save_conversation_plugin.py +98 -32
- plugins/system_commands_plugin.py +70 -56
- plugins/tmux_plugin.py +154 -78
- plugins/workflow_enforcement_plugin.py +94 -92
- system_prompt/default.md +952 -886
- core/io/input_mode_manager.py +0 -402
- core/io/modal_interaction_handler.py +0 -315
- core/io/raw_input_processor.py +0 -946
- core/storage/__init__.py +0 -5
- core/storage/state_manager.py +0 -84
- core/ui/widget_integration.py +0 -222
- core/utils/key_reader.py +0 -171
- kollabor-0.4.9.dist-info/RECORD +0 -128
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/WHEEL +0 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/entry_points.txt +0 -0
- {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -15,11 +15,14 @@ demonstrating:
|
|
|
15
15
|
Perfect for developers learning the plugin system!
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
+
import asyncio
|
|
18
19
|
import datetime
|
|
19
20
|
import logging
|
|
20
21
|
import time
|
|
21
22
|
from typing import Any, Dict, List, Optional
|
|
22
23
|
|
|
24
|
+
from core.io.visual_effects import AgnosterSegment
|
|
25
|
+
|
|
23
26
|
# Import event system components
|
|
24
27
|
import sys
|
|
25
28
|
from pathlib import Path
|
|
@@ -42,7 +45,7 @@ logger = logging.getLogger(__name__)
|
|
|
42
45
|
class HookMonitoringPlugin:
|
|
43
46
|
"""[SHOWCASE] SHOWCASE: A comprehensive hook monitoring system demonstrating ALL plugin ecosystem features!"""
|
|
44
47
|
|
|
45
|
-
def __init__(self, name: str,
|
|
48
|
+
def __init__(self, name: str, event_bus, renderer, config) -> None:
|
|
46
49
|
"""Initialize the hook monitoring plugin with full ecosystem integration.
|
|
47
50
|
|
|
48
51
|
This initialization showcases:
|
|
@@ -53,14 +56,12 @@ class HookMonitoringPlugin:
|
|
|
53
56
|
|
|
54
57
|
Args:
|
|
55
58
|
name: Plugin name.
|
|
56
|
-
state_manager: State management system.
|
|
57
59
|
event_bus: Event bus for hook registration.
|
|
58
60
|
renderer: Terminal renderer.
|
|
59
61
|
config: Configuration manager.
|
|
60
62
|
"""
|
|
61
63
|
# [DATA] BASIC PLUGIN SETUP
|
|
62
64
|
self.name = name
|
|
63
|
-
self.state_manager = state_manager
|
|
64
65
|
self.event_bus = event_bus
|
|
65
66
|
self.renderer = renderer
|
|
66
67
|
self.config = config
|
|
@@ -75,6 +76,11 @@ class HookMonitoringPlugin:
|
|
|
75
76
|
self.error_log = [] # Recent errors for debugging
|
|
76
77
|
self.hook_health_status = "Starting"
|
|
77
78
|
|
|
79
|
+
# [DATA] ENHANCED PERFORMANCE TRACKING - Detailed metrics and degradation detection
|
|
80
|
+
self.detailed_metrics = {} # event_type -> detailed metrics (history, percentiles)
|
|
81
|
+
self.performance_baseline = {} # event_type -> baseline avg_time (set after 10 executions)
|
|
82
|
+
self.degradation_detected = False # Flag for performance degradation
|
|
83
|
+
|
|
78
84
|
# [FIND] PLUGIN ECOSYSTEM STATE - Showcasing service discovery
|
|
79
85
|
self.discovered_plugins = {} # plugin_name -> plugin_instance
|
|
80
86
|
self.available_services = {} # service_name -> plugin_info
|
|
@@ -85,11 +91,14 @@ class HookMonitoringPlugin:
|
|
|
85
91
|
# This shows how plugins can discover and communicate with each other
|
|
86
92
|
self.plugin_factory: Optional[PluginFactory] = None
|
|
87
93
|
self.plugin_discovery_enabled = config.get("plugins.hook_monitoring.enable_plugin_discovery", True)
|
|
94
|
+
self.discovery_task = None # Background task for periodic discovery
|
|
95
|
+
self.last_discovery_time = None # Timestamp of last discovery
|
|
88
96
|
|
|
89
97
|
# [TOOL] SDK INITIALIZATION - Demonstrating service registration
|
|
90
98
|
# This shows how plugins can register services for other plugins to use
|
|
91
99
|
self.sdk: Optional[KollaborPluginSDK] = None
|
|
92
100
|
self.service_registration_enabled = config.get("plugins.hook_monitoring.enable_service_registration", True)
|
|
101
|
+
self.registered_services = [] # Track which services are actually registered
|
|
93
102
|
|
|
94
103
|
if SDK_AVAILABLE and self.service_registration_enabled:
|
|
95
104
|
self.sdk = KollaborPluginSDK()
|
|
@@ -99,6 +108,19 @@ class HookMonitoringPlugin:
|
|
|
99
108
|
self.enable_cross_plugin_comm = config.get("plugins.hook_monitoring.enable_cross_plugin_communication", True)
|
|
100
109
|
self.message_history_limit = config.get("plugins.hook_monitoring.message_history_limit", 20)
|
|
101
110
|
|
|
111
|
+
# [METRICS] METRICS COLLECTION AND RETENTION - Timestamped metrics storage
|
|
112
|
+
self.collected_metrics = [] # List of timestamped metric snapshots
|
|
113
|
+
self.service_usage_stats = { # Track SDK service call counts
|
|
114
|
+
"monitor_performance": {"calls": 0, "last_called": None},
|
|
115
|
+
"check_plugin_health": {"calls": 0, "last_called": None},
|
|
116
|
+
"collect_system_metrics": {"calls": 0, "last_called": None}
|
|
117
|
+
}
|
|
118
|
+
self.metrics_collection_task = None # Background task for metrics collection
|
|
119
|
+
|
|
120
|
+
# [TARGET] DASHBOARD STATE - Dashboard update throttling and caching
|
|
121
|
+
self.last_dashboard_update = datetime.datetime.now()
|
|
122
|
+
self.cached_dashboard_content = []
|
|
123
|
+
|
|
102
124
|
# [TARGET] CREATE HOOKS - Standard hook creation for monitoring
|
|
103
125
|
self.hooks = self._create_all_hooks()
|
|
104
126
|
|
|
@@ -131,7 +153,7 @@ class HookMonitoringPlugin:
|
|
|
131
153
|
discovered_count = len(getattr(self, 'discovered_plugins', {}))
|
|
132
154
|
|
|
133
155
|
# [TOOL] SHOWCASE: Service Registration Status
|
|
134
|
-
registered_services =
|
|
156
|
+
registered_services = len(getattr(self, 'registered_services', []))
|
|
135
157
|
|
|
136
158
|
# [COMM] SHOWCASE: Cross-Plugin Communication Status
|
|
137
159
|
recent_messages = len(getattr(self, 'cross_plugin_messages', []))
|
|
@@ -149,8 +171,8 @@ class HookMonitoringPlugin:
|
|
|
149
171
|
"C": [ # Detailed ecosystem info in area C
|
|
150
172
|
f"SHOWCASE: Plugin Ecosystem Demo",
|
|
151
173
|
f"Last Event: {self.last_hook_event[:20]}",
|
|
152
|
-
f"Discovery: {'[
|
|
153
|
-
f"SDK: {'[
|
|
174
|
+
f"Discovery: {'[ok]' if self.plugin_discovery_enabled else '[X]'}",
|
|
175
|
+
f"SDK: {'[ok]' if SDK_AVAILABLE else '[X]'}",
|
|
154
176
|
f"Debug: {'On' if debug_mode else 'Off'}"
|
|
155
177
|
]
|
|
156
178
|
}
|
|
@@ -163,6 +185,7 @@ class HookMonitoringPlugin:
|
|
|
163
185
|
2. SDK service registration for providing monitoring services
|
|
164
186
|
3. Cross-plugin communication setup
|
|
165
187
|
4. Dynamic service discovery patterns
|
|
188
|
+
5. Background task management for periodic operations
|
|
166
189
|
"""
|
|
167
190
|
logger.info("Starting HookMonitoringPlugin initialization...")
|
|
168
191
|
|
|
@@ -170,6 +193,14 @@ class HookMonitoringPlugin:
|
|
|
170
193
|
if self.plugin_discovery_enabled:
|
|
171
194
|
await self._discover_other_plugins()
|
|
172
195
|
|
|
196
|
+
# Start periodic plugin discovery if interval is configured
|
|
197
|
+
interval = self.config.get("plugins.hook_monitoring.discovery_interval", 30)
|
|
198
|
+
if interval > 0:
|
|
199
|
+
self.discovery_task = asyncio.create_task(
|
|
200
|
+
self._periodic_plugin_discovery()
|
|
201
|
+
)
|
|
202
|
+
logger.info(f"Started periodic plugin discovery task (interval: {interval}s)")
|
|
203
|
+
|
|
173
204
|
# [TOOL] STEP 2: SERVICE REGISTRATION - Showcasing how to offer services to other plugins
|
|
174
205
|
if self.service_registration_enabled and self.sdk:
|
|
175
206
|
await self._register_monitoring_services()
|
|
@@ -181,6 +212,13 @@ class HookMonitoringPlugin:
|
|
|
181
212
|
# [DATA] STEP 4: INITIALIZE PLUGIN HEALTH MONITORING
|
|
182
213
|
await self._initialize_plugin_health_monitoring()
|
|
183
214
|
|
|
215
|
+
# [METRICS] STEP 5: START METRICS COLLECTION - Periodic metrics gathering
|
|
216
|
+
if self.config.get("plugins.hook_monitoring.collect_plugin_metrics", True):
|
|
217
|
+
self.metrics_collection_task = asyncio.create_task(
|
|
218
|
+
self._periodic_metrics_collection()
|
|
219
|
+
)
|
|
220
|
+
logger.info("Started periodic metrics collection task (interval: 60s)")
|
|
221
|
+
|
|
184
222
|
logger.info("HookMonitoringPlugin initialization complete - all ecosystem features active!")
|
|
185
223
|
|
|
186
224
|
async def _discover_other_plugins(self) -> None:
|
|
@@ -248,6 +286,114 @@ class HookMonitoringPlugin:
|
|
|
248
286
|
|
|
249
287
|
logger.debug(f"Analyzed {plugin_name}: {capabilities}")
|
|
250
288
|
|
|
289
|
+
async def _periodic_plugin_discovery(self) -> None:
|
|
290
|
+
"""[FIND] SHOWCASE: Periodically discover plugins at configured interval.
|
|
291
|
+
|
|
292
|
+
This demonstrates background task patterns for plugin ecosystem monitoring:
|
|
293
|
+
- Periodic task execution with configurable interval
|
|
294
|
+
- Auto-capability analysis based on configuration
|
|
295
|
+
- Proper exception handling and cleanup
|
|
296
|
+
- Task cancellation support
|
|
297
|
+
"""
|
|
298
|
+
interval = self.config.get("plugins.hook_monitoring.discovery_interval", 30)
|
|
299
|
+
auto_analyze = self.config.get("plugins.hook_monitoring.auto_analyze_capabilities", True)
|
|
300
|
+
|
|
301
|
+
logger.info(f"Starting periodic plugin discovery (interval: {interval}s, auto_analyze: {auto_analyze})")
|
|
302
|
+
|
|
303
|
+
while True:
|
|
304
|
+
try:
|
|
305
|
+
await asyncio.sleep(interval)
|
|
306
|
+
|
|
307
|
+
# Discover plugins
|
|
308
|
+
if hasattr(self.renderer, 'plugin_instances'):
|
|
309
|
+
plugin_instances = getattr(self.renderer, 'plugin_instances', {})
|
|
310
|
+
self.discovered_plugins = plugin_instances
|
|
311
|
+
|
|
312
|
+
# Auto-analyze capabilities if enabled
|
|
313
|
+
if auto_analyze:
|
|
314
|
+
for plugin_name, plugin_instance in plugin_instances.items():
|
|
315
|
+
if plugin_name != self.name:
|
|
316
|
+
await self._analyze_plugin_capabilities(plugin_name, plugin_instance)
|
|
317
|
+
|
|
318
|
+
self.last_discovery_time = datetime.datetime.now()
|
|
319
|
+
logger.debug(f"Plugin discovery complete: {len(self.discovered_plugins)} plugins found")
|
|
320
|
+
|
|
321
|
+
except asyncio.CancelledError:
|
|
322
|
+
logger.info("Plugin discovery task cancelled")
|
|
323
|
+
break
|
|
324
|
+
except Exception as e:
|
|
325
|
+
logger.error(f"Plugin discovery error: {e}")
|
|
326
|
+
await asyncio.sleep(interval)
|
|
327
|
+
|
|
328
|
+
async def _periodic_metrics_collection(self) -> None:
|
|
329
|
+
"""[METRICS] SHOWCASE: Periodically collect and store metrics.
|
|
330
|
+
|
|
331
|
+
This demonstrates:
|
|
332
|
+
- Periodic metrics gathering with retention policies
|
|
333
|
+
- Time-series data collection patterns
|
|
334
|
+
- Memory-efficient metrics storage with automatic cleanup
|
|
335
|
+
- Configuration-driven collection intervals
|
|
336
|
+
"""
|
|
337
|
+
logger.info("Starting periodic metrics collection")
|
|
338
|
+
|
|
339
|
+
while True:
|
|
340
|
+
try:
|
|
341
|
+
await asyncio.sleep(60) # Collect every 60 seconds
|
|
342
|
+
|
|
343
|
+
# Gather metrics snapshot
|
|
344
|
+
snapshot = {
|
|
345
|
+
"timestamp": datetime.datetime.now(),
|
|
346
|
+
"hook_executions": self.hook_executions,
|
|
347
|
+
"failed_hooks": self.failed_hooks,
|
|
348
|
+
"timeout_hooks": self.timeout_hooks,
|
|
349
|
+
"health_status": self.hook_health_status,
|
|
350
|
+
"discovered_plugins": len(self.discovered_plugins),
|
|
351
|
+
"service_usage": dict(self.service_usage_stats),
|
|
352
|
+
"performance_summary": {
|
|
353
|
+
event: {
|
|
354
|
+
"count": metrics["count"],
|
|
355
|
+
"avg_time": metrics["avg_time"]
|
|
356
|
+
}
|
|
357
|
+
for event, metrics in self.hook_performance.items()
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
self.collected_metrics.append(snapshot)
|
|
362
|
+
|
|
363
|
+
# Cleanup old metrics
|
|
364
|
+
self._cleanup_old_metrics()
|
|
365
|
+
|
|
366
|
+
logger.debug(f"Metrics collected: {len(self.collected_metrics)} snapshots retained")
|
|
367
|
+
|
|
368
|
+
except asyncio.CancelledError:
|
|
369
|
+
logger.info("Metrics collection task cancelled")
|
|
370
|
+
break
|
|
371
|
+
except Exception as e:
|
|
372
|
+
logger.error(f"Metrics collection error: {e}")
|
|
373
|
+
await asyncio.sleep(60)
|
|
374
|
+
|
|
375
|
+
def _cleanup_old_metrics(self) -> None:
|
|
376
|
+
"""[METRICS] SHOWCASE: Remove metrics older than retention period.
|
|
377
|
+
|
|
378
|
+
This demonstrates memory management for time-series data:
|
|
379
|
+
- Configuration-driven retention policies
|
|
380
|
+
- Efficient list comprehension for cleanup
|
|
381
|
+
- Automatic old data removal
|
|
382
|
+
"""
|
|
383
|
+
retention_hours = self.config.get("plugins.hook_monitoring.metrics_retention_hours", 24)
|
|
384
|
+
cutoff_time = datetime.datetime.now() - datetime.timedelta(hours=retention_hours)
|
|
385
|
+
|
|
386
|
+
# Remove old metrics
|
|
387
|
+
original_count = len(self.collected_metrics)
|
|
388
|
+
self.collected_metrics = [
|
|
389
|
+
m for m in self.collected_metrics
|
|
390
|
+
if m["timestamp"] > cutoff_time
|
|
391
|
+
]
|
|
392
|
+
|
|
393
|
+
removed_count = original_count - len(self.collected_metrics)
|
|
394
|
+
if removed_count > 0:
|
|
395
|
+
logger.debug(f"Cleaned up {removed_count} old metrics (retention: {retention_hours}h)")
|
|
396
|
+
|
|
251
397
|
async def _register_monitoring_services(self) -> None:
|
|
252
398
|
"""[TOOL] SHOWCASE: Register monitoring services for other plugins to use.
|
|
253
399
|
|
|
@@ -262,50 +408,62 @@ class HookMonitoringPlugin:
|
|
|
262
408
|
logger.warning("SDK not available - cannot register services")
|
|
263
409
|
return
|
|
264
410
|
|
|
411
|
+
# Reset registered services list
|
|
412
|
+
self.registered_services = []
|
|
413
|
+
|
|
265
414
|
try:
|
|
266
415
|
# [DATA] SERVICE 1: Performance Monitoring
|
|
267
|
-
self.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
"
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
416
|
+
if self.config.get("plugins.hook_monitoring.register_performance_service", True):
|
|
417
|
+
self.sdk.register_custom_tool({
|
|
418
|
+
"name": "monitor_performance",
|
|
419
|
+
"description": "Monitor plugin performance and hook execution times",
|
|
420
|
+
"handler": self._provide_performance_monitoring,
|
|
421
|
+
"parameters": {
|
|
422
|
+
"plugin_name": {"type": "string", "description": "Plugin to monitor"},
|
|
423
|
+
"metric_type": {"type": "string", "description": "Type of metric to collect"}
|
|
424
|
+
},
|
|
425
|
+
"plugin": self.name,
|
|
426
|
+
"enabled": True,
|
|
427
|
+
"category": "monitoring"
|
|
428
|
+
})
|
|
429
|
+
self.registered_services.append("monitor_performance")
|
|
430
|
+
logger.debug("Registered performance monitoring service")
|
|
279
431
|
|
|
280
432
|
# [HEALTH] SERVICE 2: Health Checking
|
|
281
|
-
self.
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
"
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
433
|
+
if self.config.get("plugins.hook_monitoring.register_health_service", True):
|
|
434
|
+
self.sdk.register_custom_tool({
|
|
435
|
+
"name": "check_plugin_health",
|
|
436
|
+
"description": "Check the health status of any plugin in the system",
|
|
437
|
+
"handler": self._provide_health_check,
|
|
438
|
+
"parameters": {
|
|
439
|
+
"plugin_name": {"type": "string", "description": "Plugin to check"},
|
|
440
|
+
"detailed": {"type": "boolean", "description": "Return detailed health info"}
|
|
441
|
+
},
|
|
442
|
+
"plugin": self.name,
|
|
443
|
+
"enabled": True,
|
|
444
|
+
"category": "health"
|
|
445
|
+
})
|
|
446
|
+
self.registered_services.append("check_plugin_health")
|
|
447
|
+
logger.debug("Registered health check service")
|
|
293
448
|
|
|
294
449
|
# [METRICS] SERVICE 3: Metrics Collection
|
|
295
|
-
self.
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
"
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
450
|
+
if self.config.get("plugins.hook_monitoring.register_metrics_service", True):
|
|
451
|
+
self.sdk.register_custom_tool({
|
|
452
|
+
"name": "collect_system_metrics",
|
|
453
|
+
"description": "Collect comprehensive system and plugin metrics",
|
|
454
|
+
"handler": self._provide_metrics_collection,
|
|
455
|
+
"parameters": {
|
|
456
|
+
"time_range": {"type": "string", "description": "Time range for metrics"},
|
|
457
|
+
"include_performance": {"type": "boolean", "description": "Include performance data"}
|
|
458
|
+
},
|
|
459
|
+
"plugin": self.name,
|
|
460
|
+
"enabled": True,
|
|
461
|
+
"category": "analytics"
|
|
462
|
+
})
|
|
463
|
+
self.registered_services.append("collect_system_metrics")
|
|
464
|
+
logger.debug("Registered metrics collection service")
|
|
307
465
|
|
|
308
|
-
logger.
|
|
466
|
+
logger.info(f"Registered {len(self.registered_services)} monitoring services: {', '.join(self.registered_services)}")
|
|
309
467
|
|
|
310
468
|
except Exception as e:
|
|
311
469
|
logger.error(f"Service registration failed: {e}")
|
|
@@ -407,7 +565,7 @@ class HookMonitoringPlugin:
|
|
|
407
565
|
|
|
408
566
|
registry = self.renderer.status_renderer.status_registry
|
|
409
567
|
registry.register_status_view("hook_monitoring", developer_view)
|
|
410
|
-
logger.info("[
|
|
568
|
+
logger.info("[ok] Registered 'Developer Metrics' status view")
|
|
411
569
|
|
|
412
570
|
else:
|
|
413
571
|
logger.warning("Status registry not available - cannot register status view")
|
|
@@ -416,38 +574,136 @@ class HookMonitoringPlugin:
|
|
|
416
574
|
logger.error(f"Failed to register status view: {e}")
|
|
417
575
|
|
|
418
576
|
def _get_developer_metrics_content(self) -> List[str]:
|
|
419
|
-
"""Get developer metrics
|
|
577
|
+
"""[TARGET] SHOWCASE: Get developer metrics with conditional display and throttling.
|
|
578
|
+
|
|
579
|
+
This demonstrates:
|
|
580
|
+
- Configuration-driven dashboard visibility
|
|
581
|
+
- Update throttling for performance optimization
|
|
582
|
+
- Multi-line dashboard with plugin interactions and service usage
|
|
583
|
+
- Content caching with configurable refresh intervals
|
|
584
|
+
"""
|
|
420
585
|
try:
|
|
586
|
+
# Check if dashboard is enabled
|
|
587
|
+
dashboard_enabled = self.config.get('plugins.hook_monitoring.enable_health_dashboard', True)
|
|
588
|
+
if not dashboard_enabled:
|
|
589
|
+
return [] # Don't show anything when disabled
|
|
590
|
+
|
|
591
|
+
# Check if plugin is enabled
|
|
421
592
|
enabled = self.config.get('plugins.hook_monitoring.enabled', False)
|
|
422
593
|
if not enabled:
|
|
423
|
-
|
|
594
|
+
seg = AgnosterSegment()
|
|
595
|
+
seg.add_neutral("Hooks: Off", "dark")
|
|
596
|
+
return [seg.render()]
|
|
597
|
+
|
|
598
|
+
# Check dashboard update interval (throttling)
|
|
599
|
+
update_interval = self.config.get('plugins.hook_monitoring.dashboard_update_interval', 10)
|
|
600
|
+
now = datetime.datetime.now()
|
|
601
|
+
seconds_since_update = (now - self.last_dashboard_update).total_seconds()
|
|
602
|
+
|
|
603
|
+
if seconds_since_update < update_interval and self.cached_dashboard_content:
|
|
604
|
+
return self.cached_dashboard_content # Return cached content
|
|
605
|
+
|
|
606
|
+
# Regenerate dashboard content
|
|
607
|
+
self.last_dashboard_update = now
|
|
424
608
|
|
|
425
|
-
#
|
|
609
|
+
# Build main metrics line
|
|
610
|
+
seg = AgnosterSegment()
|
|
611
|
+
|
|
612
|
+
# Calculate failure rate
|
|
426
613
|
failure_rate = 0
|
|
427
614
|
if self.hook_executions > 0:
|
|
428
615
|
failure_rate = (self.failed_hooks + self.timeout_hooks) / self.hook_executions
|
|
429
616
|
|
|
430
|
-
# Plugin discovery
|
|
617
|
+
# Plugin discovery
|
|
431
618
|
discovered_count = len(getattr(self, 'discovered_plugins', {}))
|
|
432
619
|
|
|
433
|
-
#
|
|
434
|
-
registered_services =
|
|
620
|
+
# Services
|
|
621
|
+
registered_services = len(getattr(self, 'registered_services', []))
|
|
435
622
|
|
|
436
|
-
#
|
|
437
|
-
|
|
623
|
+
# Build agnoster bar
|
|
624
|
+
seg.add_lime(f"Hooks: {self.hook_health_status}", "dark")
|
|
625
|
+
seg.add_cyan(f"Exec: {self.hook_executions}", "dark")
|
|
626
|
+
seg.add_lime(f"Plugins: {discovered_count}")
|
|
438
627
|
|
|
439
|
-
|
|
440
|
-
f"
|
|
441
|
-
|
|
442
|
-
|
|
628
|
+
if self.hook_executions > 0:
|
|
629
|
+
seg.add_cyan(f"Fail: {failure_rate:.1%}")
|
|
630
|
+
else:
|
|
631
|
+
seg.add_cyan("Fail: N/A")
|
|
632
|
+
|
|
633
|
+
seg.add_neutral(f"Services: {registered_services}", "mid")
|
|
634
|
+
|
|
635
|
+
result = [seg.render()]
|
|
636
|
+
|
|
637
|
+
# Add plugin interactions line if enabled
|
|
638
|
+
show_interactions = self.config.get('plugins.hook_monitoring.show_plugin_interactions', True)
|
|
639
|
+
if show_interactions and hasattr(self, 'cross_plugin_messages'):
|
|
640
|
+
recent_messages = len(self.cross_plugin_messages)
|
|
641
|
+
if recent_messages > 0:
|
|
642
|
+
int_seg = AgnosterSegment()
|
|
643
|
+
int_seg.add_neutral(f"Interactions: {recent_messages}", "dark")
|
|
644
|
+
|
|
645
|
+
# Show top communicators
|
|
646
|
+
senders = {}
|
|
647
|
+
for msg in self.cross_plugin_messages:
|
|
648
|
+
sender = msg.get("sender", "unknown")
|
|
649
|
+
senders[sender] = senders.get(sender, 0) + 1
|
|
650
|
+
|
|
651
|
+
for sender, count in list(senders.items())[:3]: # Top 3
|
|
652
|
+
int_seg.add_cyan(f"{sender}: {count}")
|
|
653
|
+
|
|
654
|
+
result.append(int_seg.render())
|
|
655
|
+
|
|
656
|
+
# Add service usage line if enabled
|
|
657
|
+
show_service_usage = self.config.get('plugins.hook_monitoring.show_service_usage', True)
|
|
658
|
+
if show_service_usage and hasattr(self, 'service_usage_stats'):
|
|
659
|
+
svc_seg = AgnosterSegment()
|
|
660
|
+
|
|
661
|
+
total_calls = sum(s["calls"] for s in self.service_usage_stats.values())
|
|
662
|
+
svc_seg.add_neutral(f"Service Calls: {total_calls}", "dark")
|
|
663
|
+
|
|
664
|
+
for service_name, stats in self.service_usage_stats.items():
|
|
665
|
+
if stats["calls"] > 0:
|
|
666
|
+
# Shorten service names for display
|
|
667
|
+
short_name = service_name.replace("monitor_", "").replace("check_plugin_", "").replace("collect_system_", "")
|
|
668
|
+
svc_seg.add_lime(f"{short_name}: {stats['calls']}")
|
|
669
|
+
|
|
670
|
+
if total_calls > 0: # Only show if there are service calls
|
|
671
|
+
result.append(svc_seg.render())
|
|
672
|
+
|
|
673
|
+
# Cache the result
|
|
674
|
+
self.cached_dashboard_content = result
|
|
675
|
+
return result
|
|
443
676
|
|
|
444
677
|
except Exception as e:
|
|
445
678
|
logger.error(f"Error getting developer metrics content: {e}")
|
|
446
|
-
|
|
679
|
+
seg = AgnosterSegment()
|
|
680
|
+
seg.add_neutral("Hooks: Error", "dark")
|
|
681
|
+
return [seg.render()]
|
|
447
682
|
|
|
448
683
|
async def shutdown(self) -> None:
|
|
449
|
-
"""Shutdown the hook monitoring plugin."""
|
|
684
|
+
"""Shutdown the hook monitoring plugin with proper task cleanup."""
|
|
450
685
|
logger.info(f"Hook Monitor: Shutting down - processed {self.hook_executions} events, {self.failed_hooks} failures")
|
|
686
|
+
|
|
687
|
+
# Cancel discovery task if running
|
|
688
|
+
if self.discovery_task and not self.discovery_task.done():
|
|
689
|
+
self.discovery_task.cancel()
|
|
690
|
+
try:
|
|
691
|
+
await asyncio.wait_for(self.discovery_task, timeout=2.0)
|
|
692
|
+
except (asyncio.TimeoutError, asyncio.CancelledError):
|
|
693
|
+
logger.debug("Discovery task cancelled during shutdown")
|
|
694
|
+
except Exception as e:
|
|
695
|
+
logger.warning(f"Error cancelling discovery task: {e}")
|
|
696
|
+
|
|
697
|
+
# Cancel metrics collection task if running
|
|
698
|
+
if self.metrics_collection_task and not self.metrics_collection_task.done():
|
|
699
|
+
self.metrics_collection_task.cancel()
|
|
700
|
+
try:
|
|
701
|
+
await asyncio.wait_for(self.metrics_collection_task, timeout=2.0)
|
|
702
|
+
except (asyncio.TimeoutError, asyncio.CancelledError):
|
|
703
|
+
logger.debug("Metrics collection task cancelled during shutdown")
|
|
704
|
+
except Exception as e:
|
|
705
|
+
logger.warning(f"Error cancelling metrics collection task: {e}")
|
|
706
|
+
|
|
451
707
|
self._log_final_report()
|
|
452
708
|
# Only show shutdown message if not in pipe mode
|
|
453
709
|
# if not getattr(self.renderer, 'pipe_mode', False):
|
|
@@ -859,6 +1115,10 @@ class HookMonitoringPlugin:
|
|
|
859
1115
|
"metric_type": "execution_time"
|
|
860
1116
|
})
|
|
861
1117
|
"""
|
|
1118
|
+
# Track service usage
|
|
1119
|
+
self.service_usage_stats["monitor_performance"]["calls"] += 1
|
|
1120
|
+
self.service_usage_stats["monitor_performance"]["last_called"] = datetime.datetime.now()
|
|
1121
|
+
|
|
862
1122
|
plugin_name = params.get("plugin_name", "all")
|
|
863
1123
|
metric_type = params.get("metric_type", "summary")
|
|
864
1124
|
|
|
@@ -896,6 +1156,10 @@ class HookMonitoringPlugin:
|
|
|
896
1156
|
"detailed": True
|
|
897
1157
|
})
|
|
898
1158
|
"""
|
|
1159
|
+
# Track service usage
|
|
1160
|
+
self.service_usage_stats["check_plugin_health"]["calls"] += 1
|
|
1161
|
+
self.service_usage_stats["check_plugin_health"]["last_called"] = datetime.datetime.now()
|
|
1162
|
+
|
|
899
1163
|
plugin_name = params.get("plugin_name", "system")
|
|
900
1164
|
detailed = params.get("detailed", False)
|
|
901
1165
|
|
|
@@ -936,6 +1200,10 @@ class HookMonitoringPlugin:
|
|
|
936
1200
|
"include_performance": True
|
|
937
1201
|
})
|
|
938
1202
|
"""
|
|
1203
|
+
# Track service usage
|
|
1204
|
+
self.service_usage_stats["collect_system_metrics"]["calls"] += 1
|
|
1205
|
+
self.service_usage_stats["collect_system_metrics"]["last_called"] = datetime.datetime.now()
|
|
1206
|
+
|
|
939
1207
|
time_range = params.get("time_range", "current")
|
|
940
1208
|
include_performance = params.get("include_performance", True)
|
|
941
1209
|
|
|
@@ -961,10 +1229,13 @@ class HookMonitoringPlugin:
|
|
|
961
1229
|
|
|
962
1230
|
# [COMM] CROSS-PLUGIN COMMUNICATION HANDLERS
|
|
963
1231
|
|
|
964
|
-
async def _handle_health_check_request(self, message: Dict[str, Any], sender: str) ->
|
|
965
|
-
"""[COMM] SHOWCASE: Handle health check requests from other plugins.
|
|
1232
|
+
async def _handle_health_check_request(self, message: Dict[str, Any], sender: str) -> Dict[str, Any]:
|
|
1233
|
+
"""[COMM] SHOWCASE: Handle health check requests from other plugins with optional auto-response.
|
|
966
1234
|
|
|
967
|
-
This demonstrates
|
|
1235
|
+
This demonstrates:
|
|
1236
|
+
- Direct plugin-to-plugin communication
|
|
1237
|
+
- Automatic service response based on configuration
|
|
1238
|
+
- Message tracking and statistics
|
|
968
1239
|
"""
|
|
969
1240
|
logger.info(f"[COMM] Health check request received from {sender}")
|
|
970
1241
|
|
|
@@ -985,6 +1256,18 @@ class HookMonitoringPlugin:
|
|
|
985
1256
|
self.plugin_health_stats[sender]["message_count"] += 1
|
|
986
1257
|
self.plugin_health_stats[sender]["last_seen"] = datetime.datetime.now()
|
|
987
1258
|
|
|
1259
|
+
# Auto-respond if configured
|
|
1260
|
+
auto_respond = self.config.get("plugins.hook_monitoring.auto_respond_to_health_checks", True)
|
|
1261
|
+
if auto_respond:
|
|
1262
|
+
response = await self._provide_health_check({
|
|
1263
|
+
"plugin_name": message.get("plugin_name", "system"),
|
|
1264
|
+
"detailed": message.get("detailed", False)
|
|
1265
|
+
})
|
|
1266
|
+
logger.debug(f"[COMM] Auto-responded to {sender} with health check")
|
|
1267
|
+
return response
|
|
1268
|
+
|
|
1269
|
+
return {"status": "acknowledged", "auto_respond": False}
|
|
1270
|
+
|
|
988
1271
|
async def _handle_performance_data_request(self, message: Dict[str, Any], sender: str) -> Dict[str, Any]:
|
|
989
1272
|
"""[COMM] SHOWCASE: Handle performance data requests from other plugins."""
|
|
990
1273
|
logger.info(f"[DATA] Performance data request from {sender}")
|
|
@@ -1063,7 +1346,7 @@ class HookMonitoringPlugin:
|
|
|
1063
1346
|
}
|
|
1064
1347
|
|
|
1065
1348
|
def _update_performance_metrics(self, event_type: str, start_time: float) -> None:
|
|
1066
|
-
"""Update performance metrics
|
|
1349
|
+
"""Update performance metrics with optional detailed tracking.
|
|
1067
1350
|
|
|
1068
1351
|
Args:
|
|
1069
1352
|
event_type: The event type being monitored.
|
|
@@ -1071,6 +1354,7 @@ class HookMonitoringPlugin:
|
|
|
1071
1354
|
"""
|
|
1072
1355
|
execution_time = (time.time() - start_time) * 1000 # Convert to milliseconds
|
|
1073
1356
|
|
|
1357
|
+
# Standard metrics (always tracked)
|
|
1074
1358
|
if event_type not in self.hook_performance:
|
|
1075
1359
|
self.hook_performance[event_type] = {
|
|
1076
1360
|
"total_time": 0,
|
|
@@ -1087,8 +1371,82 @@ class HookMonitoringPlugin:
|
|
|
1087
1371
|
metrics["max_time"] = max(metrics["max_time"], execution_time)
|
|
1088
1372
|
metrics["min_time"] = min(metrics["min_time"], execution_time)
|
|
1089
1373
|
|
|
1374
|
+
# Set baseline after 10 executions
|
|
1375
|
+
if metrics["count"] == 10 and event_type not in self.performance_baseline:
|
|
1376
|
+
self.performance_baseline[event_type] = metrics["avg_time"]
|
|
1377
|
+
logger.debug(f"Set performance baseline for {event_type}: {metrics['avg_time']:.2f}ms")
|
|
1378
|
+
|
|
1379
|
+
# Detailed tracking (optional)
|
|
1380
|
+
detailed_tracking = self.config.get("plugins.hook_monitoring.detailed_performance_tracking", True)
|
|
1381
|
+
if detailed_tracking:
|
|
1382
|
+
if event_type not in self.detailed_metrics:
|
|
1383
|
+
self.detailed_metrics[event_type] = {
|
|
1384
|
+
"execution_history": [], # Last 100 executions
|
|
1385
|
+
"percentile_95": 0,
|
|
1386
|
+
"percentile_99": 0,
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
detail = self.detailed_metrics[event_type]
|
|
1390
|
+
detail["execution_history"].append(execution_time)
|
|
1391
|
+
|
|
1392
|
+
# Keep only last 100 executions
|
|
1393
|
+
if len(detail["execution_history"]) > 100:
|
|
1394
|
+
detail["execution_history"] = detail["execution_history"][-100:]
|
|
1395
|
+
|
|
1396
|
+
# Calculate percentiles (require at least 20 samples)
|
|
1397
|
+
if len(detail["execution_history"]) >= 20:
|
|
1398
|
+
sorted_times = sorted(detail["execution_history"])
|
|
1399
|
+
p95_idx = int(len(sorted_times) * 0.95)
|
|
1400
|
+
p99_idx = int(len(sorted_times) * 0.99)
|
|
1401
|
+
detail["percentile_95"] = sorted_times[p95_idx]
|
|
1402
|
+
detail["percentile_99"] = sorted_times[p99_idx]
|
|
1403
|
+
|
|
1404
|
+
def _check_performance_degradation(self) -> bool:
|
|
1405
|
+
"""[DATA] SHOWCASE: Check if performance has degraded beyond threshold.
|
|
1406
|
+
|
|
1407
|
+
This demonstrates:
|
|
1408
|
+
- Performance baseline comparison
|
|
1409
|
+
- Configuration-driven degradation thresholds
|
|
1410
|
+
- Automatic performance degradation detection
|
|
1411
|
+
- Warning logging for degraded performance
|
|
1412
|
+
|
|
1413
|
+
Returns:
|
|
1414
|
+
True if degradation detected, False otherwise
|
|
1415
|
+
"""
|
|
1416
|
+
threshold = self.config.get("plugins.hook_monitoring.performance_degradation_threshold", 0.15)
|
|
1417
|
+
degraded_events = []
|
|
1418
|
+
|
|
1419
|
+
for event_type, baseline_time in self.performance_baseline.items():
|
|
1420
|
+
if event_type in self.hook_performance:
|
|
1421
|
+
current_time = self.hook_performance[event_type]["avg_time"]
|
|
1422
|
+
# Only check degradation if baseline is meaningful (> 0.1ms)
|
|
1423
|
+
# This avoids false positives from sub-millisecond execution times
|
|
1424
|
+
if baseline_time > 0.1:
|
|
1425
|
+
degradation = (current_time - baseline_time) / baseline_time
|
|
1426
|
+
|
|
1427
|
+
if degradation > threshold:
|
|
1428
|
+
degraded_events.append({
|
|
1429
|
+
"event_type": event_type,
|
|
1430
|
+
"baseline_ms": baseline_time,
|
|
1431
|
+
"current_ms": current_time,
|
|
1432
|
+
"degradation_pct": degradation * 100
|
|
1433
|
+
})
|
|
1434
|
+
|
|
1435
|
+
if degraded_events:
|
|
1436
|
+
self.degradation_detected = True
|
|
1437
|
+
for event in degraded_events:
|
|
1438
|
+
logger.warning(
|
|
1439
|
+
f"Performance degradation detected: {event['event_type']} "
|
|
1440
|
+
f"baseline={event['baseline_ms']:.1f}ms current={event['current_ms']:.1f}ms "
|
|
1441
|
+
f"({event['degradation_pct']:.1f}% slower)"
|
|
1442
|
+
)
|
|
1443
|
+
return True
|
|
1444
|
+
|
|
1445
|
+
self.degradation_detected = False
|
|
1446
|
+
return False
|
|
1447
|
+
|
|
1090
1448
|
def _update_health_status(self) -> None:
|
|
1091
|
-
"""Update
|
|
1449
|
+
"""Update health status including performance degradation check."""
|
|
1092
1450
|
total_hooks = self.hook_executions
|
|
1093
1451
|
if total_hooks == 0:
|
|
1094
1452
|
self.hook_health_status = "Starting"
|
|
@@ -1096,11 +1454,15 @@ class HookMonitoringPlugin:
|
|
|
1096
1454
|
|
|
1097
1455
|
failure_rate = (self.failed_hooks + self.timeout_hooks) / total_hooks
|
|
1098
1456
|
|
|
1099
|
-
|
|
1457
|
+
# Check performance degradation
|
|
1458
|
+
degraded = self._check_performance_degradation()
|
|
1459
|
+
|
|
1460
|
+
# Determine health status (degradation affects status)
|
|
1461
|
+
if failure_rate == 0 and not degraded:
|
|
1100
1462
|
self.hook_health_status = "Healthy"
|
|
1101
|
-
elif failure_rate < self.config.get("performance.failure_rate_warning", 0.05):
|
|
1463
|
+
elif failure_rate < self.config.get("performance.failure_rate_warning", 0.05) and not degraded:
|
|
1102
1464
|
self.hook_health_status = "Good"
|
|
1103
|
-
elif failure_rate < self.config.get("performance.failure_rate_critical", 0.15):
|
|
1465
|
+
elif failure_rate < self.config.get("performance.failure_rate_critical", 0.15) or degraded:
|
|
1104
1466
|
self.hook_health_status = "Warning"
|
|
1105
1467
|
else:
|
|
1106
1468
|
self.hook_health_status = "Critical"
|
|
@@ -1204,7 +1566,7 @@ class HookMonitoringPlugin:
|
|
|
1204
1566
|
"summary": {
|
|
1205
1567
|
"total_plugins": total_plugins,
|
|
1206
1568
|
"active_plugins": active_plugins,
|
|
1207
|
-
"registered_services":
|
|
1569
|
+
"registered_services": len(getattr(self, 'registered_services', [])),
|
|
1208
1570
|
"system_health": self.hook_health_status,
|
|
1209
1571
|
"overall_failure_rate": failure_rate,
|
|
1210
1572
|
"last_updated": datetime.datetime.now().isoformat()
|
|
@@ -1226,11 +1588,7 @@ class HookMonitoringPlugin:
|
|
|
1226
1588
|
"service_registration": {
|
|
1227
1589
|
"sdk_available": SDK_AVAILABLE,
|
|
1228
1590
|
"services_enabled": self.service_registration_enabled,
|
|
1229
|
-
"available_services": [
|
|
1230
|
-
"monitor_performance",
|
|
1231
|
-
"check_plugin_health",
|
|
1232
|
-
"collect_system_metrics"
|
|
1233
|
-
] if (self.service_registration_enabled and SDK_AVAILABLE) else []
|
|
1591
|
+
"available_services": getattr(self, 'registered_services', [])
|
|
1234
1592
|
},
|
|
1235
1593
|
|
|
1236
1594
|
"cross_plugin_communication": {
|
|
@@ -1241,12 +1599,12 @@ class HookMonitoringPlugin:
|
|
|
1241
1599
|
},
|
|
1242
1600
|
|
|
1243
1601
|
"showcase_features": {
|
|
1244
|
-
"[FIND] Plugin Discovery": "[
|
|
1245
|
-
"[TOOL] Service Registration": "[
|
|
1246
|
-
"[COMM] Cross-Plugin Comm": "[
|
|
1247
|
-
"[DATA] Performance Monitoring": "[
|
|
1248
|
-
"[HEALTH] Health Monitoring": "[
|
|
1249
|
-
"[METRICS] Metrics Collection": "[
|
|
1602
|
+
"[FIND] Plugin Discovery": "[ok] Active" if self.plugin_discovery_enabled else "Disabled",
|
|
1603
|
+
"[TOOL] Service Registration": "[ok] Active" if (self.service_registration_enabled and SDK_AVAILABLE) else "Disabled",
|
|
1604
|
+
"[COMM] Cross-Plugin Comm": "[ok] Active" if self.enable_cross_plugin_comm else "Disabled",
|
|
1605
|
+
"[DATA] Performance Monitoring": "[ok] Active",
|
|
1606
|
+
"[HEALTH] Health Monitoring": "[ok] Active",
|
|
1607
|
+
"[METRICS] Metrics Collection": "[ok] Active"
|
|
1250
1608
|
}
|
|
1251
1609
|
}
|
|
1252
1610
|
|