From 3456ba2ac53bc0d709675e3993e9b0f29c16e110 Mon Sep 17 00:00:00 2001 From: Dipesh Mittal Date: Tue, 13 Jan 2026 16:16:02 +0530 Subject: [PATCH 1/2] Working standalone example usage script --- credentials.yaml | 7 +++++++ example_usage.py | 6 +++++- settings_stub.py | 6 ++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 credentials.yaml create mode 100644 settings_stub.py diff --git a/credentials.yaml b/credentials.yaml new file mode 100644 index 0000000..6049f84 --- /dev/null +++ b/credentials.yaml @@ -0,0 +1,7 @@ +# DrDroid SDK Credentials for Testing +# Sentry Integration Test + +sentry: + id: 1 + sentry_api_key: "9423mvmefm311fffff3334v" + sentry_org_slug: "doctor-droid" \ No newline at end of file diff --git a/example_usage.py b/example_usage.py index 67a0a1a..cab03ac 100644 --- a/example_usage.py +++ b/example_usage.py @@ -5,9 +5,13 @@ This file demonstrates how to use the SDK with Grafana and Signoz integrations. """ +import os +os.environ['DJANGO_SETTINGS_MODULE'] = 'settings_stub' + import json from datetime import datetime, timedelta -from drdroid_sdk import DroidSDK, ConfigurationError, ConnectionError, TaskExecutionError +from drdroid_debug_toolkit import DroidSDK, ConfigurationError, ConnectionError +from drdroid_debug_toolkit.exceptions import TaskExecutionError def main(): diff --git a/settings_stub.py b/settings_stub.py new file mode 100644 index 0000000..219647c --- /dev/null +++ b/settings_stub.py @@ -0,0 +1,6 @@ +DEBUG = True +IS_PROD_ENV = False +MASTER_ASSETS_TOKEN = None +DRD_CLOUD_API_TOKEN = None +SECRET_KEY = 'dummy-secret-key-for-standalone-usage' +INSTALLED_APPS = [] \ No newline at end of file From cbbc2d1b290e8eccf77e3cdd21e1dce5d76ba19d Mon Sep 17 00:00:00 2001 From: Dipesh Mittal Date: Tue, 13 Jan 2026 17:59:56 +0530 Subject: [PATCH 2/2] feat: improved example --- EXAMPLE_USAGE_README.md | 75 ++++++++++ example_usage.py | 296 ++++++++++++---------------------------- 2 files changed, 163 insertions(+), 208 deletions(-) create mode 100644 EXAMPLE_USAGE_README.md diff --git a/EXAMPLE_USAGE_README.md b/EXAMPLE_USAGE_README.md new file mode 100644 index 0000000..bd6c70e --- /dev/null +++ b/EXAMPLE_USAGE_README.md @@ -0,0 +1,75 @@ +# Running the Example Usage Script + +This guide explains how to get the `example_usage.py` script working. + +## Prerequisites + +- Python 3.8+ +- pip + +## Setup Steps + +### 1. Install the Package + +```bash +cd /path/to/drdroid-debug-toolkit +pip install -e . +``` + +### 2. Create credentials.yaml + +Create a `credentials.yaml` file in the project root with your Grafana credentials: + +```yaml +grafana: + id: 1 + type: GRAFANA + grafana_host: "https://your-grafana-instance.grafana.net" + grafana_api_key: "your-grafana-api-key-here" + ssl_verify: "true" +``` + +**Note:** Replace the placeholder values with your actual Grafana host and API key. + +### 3. Run the Script + +```bash +python example_usage.py +``` + +## Available Integrations + +The following integrations are available in the SDK registry: + +| Integration | Credentials Required | +|-------------|---------------------| +| grafana | `grafana_host`, `grafana_api_key`, `ssl_verify` | +| signoz | `signoz_api_url`, `signoz_api_token` | +| postgres | `host`, `user`, `password`, `database`, `port` | +| clickhouse | `host`, `user`, `password`, `port`, `interface` | +| cloudwatch | `region`, `aws_access_key`, `aws_secret_key` | +| newrelic | `api_key`, `app_id`, `api_domain` | +| posthog | `api_key`, `app_host`, `project_id` | +| bash | `remote_host`, `remote_user`, `remote_password` or `remote_pem` | +| kubernetes | `cluster_api_server`, `cluster_token` | +| sql_database_connection | `connection_string` | + +Each integration block in `credentials.yaml` must include a `type` field matching the integration name in uppercase (e.g., `type: GRAFANA`). + +## Troubleshooting + +### Django ImproperlyConfigured Error + +The example script already includes Django configuration. If you see this error, ensure you're running the updated `example_usage.py`. + +### Module Not Found Error + +```bash +pip install -e . +``` + +### Connection Errors + +- Verify your credentials in `credentials.yaml` +- Check that your API endpoints are accessible +- For self-signed certificates, set `ssl_verify: "false"` diff --git a/example_usage.py b/example_usage.py index cab03ac..5cb7b8b 100644 --- a/example_usage.py +++ b/example_usage.py @@ -2,228 +2,108 @@ """ Example usage of the DroidSpace SDK -This file demonstrates how to use the SDK with Grafana and Signoz integrations. +This file demonstrates how to use the toolkit with integrations like Sentry, +using the same approach as the prototype backend. """ -import os -os.environ['DJANGO_SETTINGS_MODULE'] = 'settings_stub' +# Configure Django settings BEFORE importing toolkit modules +from django.conf import settings -import json -from datetime import datetime, timedelta -from drdroid_debug_toolkit import DroidSDK, ConfigurationError, ConnectionError -from drdroid_debug_toolkit.exceptions import TaskExecutionError +if not settings.configured: + settings.configure( + DEBUG=True, + IS_PROD_ENV=False, + MASTER_ASSETS_TOKEN=None, + DRD_CLOUD_API_TOKEN=None, + SECRET_KEY='dummy-secret-key-for-standalone-usage', + INSTALLED_APPS=[], + ) + +import yaml +from drdroid_debug_toolkit.core.utils.credentilal_utils import credential_yaml_to_connector_proto +from drdroid_debug_toolkit.core.integrations.source_managers.sentry_source_manager import SentrySourceManager +from drdroid_debug_toolkit.core.integrations.source_managers.datadog_source_manager import DatadogSourceManager + + +def load_credentials(credentials_file: str) -> dict: + """Load credentials from YAML file""" + with open(credentials_file, 'r') as f: + return yaml.safe_load(f) + + +def test_sentry_connection(credentials: dict) -> bool: + """ + Test Sentry connection using the prototype backend approach. + + This directly uses credential_yaml_to_connector_proto and the source manager, + exactly like the prototype backend does. + """ + if 'sentry' not in credentials: + print("No Sentry configuration found in credentials") + return False + + # Convert YAML credentials to Connector proto (prototype approach) + connector_proto = credential_yaml_to_connector_proto('sentry', credentials['sentry']) + + # Use the source manager directly to test connection + source_manager = SentrySourceManager() + return source_manager.test_connector_processor(connector_proto) + + +def test_datadog_connection(credentials: dict) -> bool: + """ + Test Datadog connection using the prototype backend approach. + + This directly uses credential_yaml_to_connector_proto and the source manager, + exactly like the prototype backend does. + """ + if 'datadog' not in credentials: + print("No Datadog configuration found in credentials") + return False + + # Convert YAML credentials to Connector proto (prototype approach) + connector_proto = credential_yaml_to_connector_proto('datadog', credentials['datadog']) + + # Use the source manager directly to test connection + source_manager = DatadogSourceManager() + return source_manager.test_connector_processor(connector_proto) def main(): """Main example function""" - - # Initialize SDK + + # Load credentials try: - sdk = DroidSDK("credentials.yaml") - print("āœ… SDK initialized successfully") - except ConfigurationError as e: - print(f"āŒ Configuration error: {e}") - return + credentials = load_credentials("credentials.yaml") + print("Credentials loaded successfully") except Exception as e: - print(f"āŒ Unexpected error: {e}") + print(f"Failed to load credentials: {e}") return - + # Show configured sources - print(f"šŸ“‹ Configured sources: {sdk.get_configured_sources()}") - print(f"šŸ”§ Supported sources: {sdk.get_supported_sources()}") - - # Test connections - print("\nšŸ” Testing connections...") - - if "grafana" in sdk.get_configured_sources(): + print(f"Configured sources: {list(credentials.keys())}") + + # Test Sentry connection + if "sentry" in credentials: + print("\nTesting Sentry connection...") try: - if sdk.test_connection("grafana"): - print("āœ… Grafana connection successful") + if test_sentry_connection(credentials): + print("Sentry connection successful") else: - print("āŒ Grafana connection failed") - except ConnectionError as e: - print(f"āŒ Grafana connection error: {e}") - - if "signoz" in sdk.get_configured_sources(): + print("Sentry connection failed") + except Exception as e: + print(f"Sentry connection error: {e}") + + # Test Datadog connection + if "datadog" in credentials: + print("\nTesting Datadog connection...") try: - if sdk.test_connection("signoz"): - print("āœ… Signoz connection successful") + if test_datadog_connection(credentials): + print("Datadog connection successful") else: - print("āŒ Signoz connection failed") - except ConnectionError as e: - print(f"āŒ Signoz connection error: {e}") - - # Grafana Examples - if "grafana" in sdk.get_configured_sources(): - print("\nšŸ“Š Grafana Examples:") - - # Example 1: Query Prometheus datasource - try: - print("\n1. Querying Prometheus datasource...") - result = sdk.grafana_query_prometheus( - datasource_uid="prometheus", - query="up", - duration_minutes=30, - interval=60 - ) - print(f"āœ… Prometheus query result: {json.dumps(result, indent=2)}") - except TaskExecutionError as e: - print(f"āŒ Prometheus query failed: {e}") - - # Example 2: Query dashboard panel - try: - print("\n2. Querying dashboard panel...") - result = sdk.grafana_query_dashboard_panel( - dashboard_id="1", - panel_id="2", - datasource_uid="prometheus", - queries=["up", "rate(http_requests_total[5m])"], - duration_minutes=30 - ) - print(f"āœ… Dashboard panel query result: {json.dumps(result, indent=2)}") - except TaskExecutionError as e: - print(f"āŒ Dashboard panel query failed: {e}") - - # Example 3: Execute all dashboard panels - try: - print("\n3. Executing all dashboard panels...") - results = sdk.grafana_execute_all_dashboard_panels( - dashboard_uid="your-dashboard-uid", - duration_minutes=30, - interval=60, - panel_ids=["1", "2"], # Optional: specific panels - template_variables={"instance": "server-1"} # Optional: template variables - ) - print(f"āœ… Dashboard execution results: {json.dumps(results, indent=2)}") - except TaskExecutionError as e: - print(f"āŒ Dashboard execution failed: {e}") - - # Signoz Examples - if "signoz" in sdk.get_configured_sources(): - print("\nšŸ“ˆ Signoz Examples:") - - # Example 1: Clickhouse query - try: - print("\n1. Executing Clickhouse query...") - result = sdk.signoz_clickhouse_query( - query="SELECT * FROM traces LIMIT 10", - duration_minutes=30, - step=60, - fill_gaps=True, - panel_type="table" - ) - print(f"āœ… Clickhouse query result: {json.dumps(result, indent=2)}") - except TaskExecutionError as e: - print(f"āŒ Clickhouse query failed: {e}") - - # Example 2: Builder query - try: - print("\n2. Executing builder query...") - builder_queries = { - "A": { - "queryName": "A", - "dataSource": "traces", - "aggregateOperator": "count", - "aggregateAttribute": {"key": "service_name"}, - "groupBy": [{"key": "service_name"}], - "legend": "{{service_name}}", - "disabled": False - } - } - - result = sdk.signoz_builder_query( - builder_queries=builder_queries, - duration_minutes=30, - step=60, - panel_type="graph" - ) - print(f"āœ… Builder query result: {json.dumps(result, indent=2)}") - except TaskExecutionError as e: - print(f"āŒ Builder query failed: {e}") - - # Example 3: Dashboard data - try: - print("\n3. Getting dashboard data...") - results = sdk.signoz_dashboard_data( - dashboard_name="My Dashboard", - duration_minutes=30, - step=60, - variables={"service": "api-gateway"} - ) - print(f"āœ… Dashboard data results: {json.dumps(results, indent=2)}") - except TaskExecutionError as e: - print(f"āŒ Dashboard data query failed: {e}") - - print("\nšŸŽ‰ Example completed!") - - -def advanced_examples(): - """Advanced usage examples""" - - print("\nšŸš€ Advanced Examples:") - - try: - sdk = DroidSDK("credentials.yaml") - - # Custom time ranges - start_time = datetime.now() - timedelta(hours=2) - end_time = datetime.now() - - # Grafana with custom time range - if "grafana" in sdk.get_configured_sources(): - try: - result = sdk.grafana_query_prometheus( - datasource_uid="prometheus", - query="rate(http_requests_total[5m])", - start_time=start_time, - end_time=end_time, - interval=120 - ) - print(f"āœ… Custom time range query: {json.dumps(result, indent=2)}") - except TaskExecutionError as e: - print(f"āŒ Custom time range query failed: {e}") - - # Signoz with complex builder query - if "signoz" in sdk.get_configured_sources(): - try: - complex_builder_queries = { - "A": { - "queryName": "A", - "dataSource": "traces", - "aggregateOperator": "avg", - "aggregateAttribute": {"key": "duration"}, - "groupBy": [ - {"key": "service_name"}, - {"key": "operation_name"} - ], - "legend": "{{service_name}} - {{operation_name}}", - "disabled": False - }, - "B": { - "queryName": "B", - "dataSource": "traces", - "aggregateOperator": "count", - "aggregateAttribute": {"key": "trace_id"}, - "groupBy": [{"key": "service_name"}], - "legend": "{{service_name}} count", - "disabled": False - } - } - - result = sdk.signoz_builder_query( - builder_queries=complex_builder_queries, - start_time=start_time, - end_time=end_time, - panel_type="graph" - ) - print(f"āœ… Complex builder query: {json.dumps(result, indent=2)}") - except TaskExecutionError as e: - print(f"āŒ Complex builder query failed: {e}") - - except Exception as e: - print(f"āŒ Advanced examples failed: {e}") - + print("Datadog connection failed") + except Exception as e: + print(f"Datadog connection error: {e}") if __name__ == "__main__": - main() - advanced_examples() \ No newline at end of file + main() \ No newline at end of file