Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2005298
Improve source_analyer tool
shetsa-amzn Oct 15, 2025
3f2e0b1
commiting the test files
shetsa-amzn Oct 15, 2025
119ab30
Improving Database Analysis Queries and changes to data modeller
shetsa-amzn Oct 16, 2025
8add119
Cleaning up queries and data modeller prompt
shetsa-amzn Oct 21, 2025
218e890
adding extra condition to ignore system or performance schema related…
shetsa-amzn Oct 21, 2025
9270ffc
Merge branch 'main' into source-analys-improvements
shetsa-amzn Oct 28, 2025
14228b4
Fixing secret and formating issue
shetsa-amzn Oct 28, 2025
d884804
Fixing the unit tests
shetsa-amzn Oct 28, 2025
714a8c4
Increasing the test coverage
shetsa-amzn Oct 28, 2025
a2283b2
Merge branch 'main' into source-analys-improvements
shetsa-amzn Oct 29, 2025
d756b8a
Merge branch 'main' into source-analys-improvements
shetsa-amzn Oct 30, 2025
2c867f4
Increasing the test coverage
shetsa-amzn Oct 28, 2025
43db35a
Merge branch 'main' into source-analys-improvements
shetsa-amzn Oct 31, 2025
c3748e1
add some more test for markdown formater
shetsa-amzn Oct 31, 2025
0a78d8f
Update the readme
shetsa-amzn Oct 31, 2025
296921d
Adding precommit changes
shetsa-amzn Oct 31, 2025
69c0249
Merge branch 'main' into source-analys-improvements
shetsa-amzn Nov 3, 2025
a0fd557
Merge branch 'main' into source-analys-improvements
shetsa-amzn Nov 3, 2025
c2116e3
Removing the unreachable code
shetsa-amzn Nov 3, 2025
6f60846
Increasing coverage for partially covered lines on markdown_formatter.py
shetsa-amzn Nov 3, 2025
63aae3f
Merge branch 'main' into source-analys-improvements
shetsa-amzn Nov 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@
"filename": "src/dynamodb-mcp-server/awslabs/dynamodb_mcp_server/database_analyzers.py",
"hashed_secret": "38a2bae6275b4d868c488758d213827833cd8570",
"is_verified": false,
"line_number": 103,
"line_number": 107,
"is_secret": false
}
],
Expand All @@ -235,15 +235,15 @@
"filename": "src/dynamodb-mcp-server/tests/test_source_db_integration.py",
"hashed_secret": "fe1bae27cb7c1fb823f496f286e78f1d2ae87734",
"is_verified": false,
"line_number": 19,
"line_number": 18,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "src/dynamodb-mcp-server/tests/test_source_db_integration.py",
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
"is_verified": false,
"line_number": 286,
"line_number": 292,
"is_secret": false
}
],
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@

"""Database analyzer classes for source database analysis."""

import json
import os
from awslabs.dynamodb_mcp_server.database_analysis_queries import get_query_resource
from awslabs.dynamodb_mcp_server.database_analysis_queries import (
get_performance_queries,
get_query_resource,
get_schema_queries,
)
from awslabs.dynamodb_mcp_server.markdown_formatter import MarkdownFormatter
from awslabs.mysql_mcp_server.server import DBConnection, DummyCtx
from awslabs.mysql_mcp_server.server import run_query as mysql_query
from datetime import datetime
Expand Down Expand Up @@ -115,8 +119,10 @@ def save_analysis_files(
pattern_analysis_days: int,
max_results: int,
output_dir: str,
performance_enabled: bool = True,
skipped_queries: List[str] = None,
) -> Tuple[List[str], List[str]]:
"""Save analysis results to JSON files.
"""Save analysis results to Markdown files using MarkdownFormatter.

Args:
results: Dictionary of query results
Expand All @@ -125,6 +131,8 @@ def save_analysis_files(
pattern_analysis_days: Number of days to analyze the logs for pattern analysis query
max_results: Maximum results per query
output_dir: Absolute directory path where the timestamped output analysis folder will be created
performance_enabled: Whether performance schema is enabled
skipped_queries: List of query names that were skipped during analysis

Returns:
Tuple of (saved_files, save_errors)
Expand All @@ -150,36 +158,33 @@ def save_analysis_files(
save_errors.append(f'Failed to create folder {analysis_folder}: {str(e)}')
return saved_files, save_errors

for query_name, query_result in results.items():
filename = os.path.join(analysis_folder, f'{query_name}_results.json')
# Prepare metadata for MarkdownFormatter
metadata = {
'database': database,
'source_db_type': source_db_type,
'analysis_period': f'{pattern_analysis_days} days',
'max_query_results': max_results,
'performance_enabled': performance_enabled,
'skipped_queries': skipped_queries or [],
}

analysis_data = query_result['data']
if query_name == 'query_pattern_analysis':
analysis_data = DatabaseAnalyzer.filter_pattern_data(
analysis_data, pattern_analysis_days
)
# Use MarkdownFormatter to generate files
try:
formatter = MarkdownFormatter(results, metadata, analysis_folder)
generated_files, generation_errors = formatter.generate_all_files()
saved_files = generated_files

try:
with open(filename, 'w') as f:
json.dump(
{
'query_name': query_name,
'description': query_result['description'],
'source_db_type': source_db_type,
'database': database,
'pattern_analysis_days': pattern_analysis_days,
'max_query_results': max_results,
'data': analysis_data,
},
f,
indent=2,
default=str,
)
saved_files.append(filename)
logger.info(f'Saved {query_name} results to {filename}')
except Exception as e:
logger.error(f'Failed to save {query_name}: {str(e)}')
save_errors.append(f'Failed to save {query_name}: {str(e)}')
# Convert error tuples to error strings
if generation_errors:
for query_name, error_msg in generation_errors:
save_errors.append(f'{query_name}: {error_msg}')

logger.info(
f'Successfully generated {len(saved_files)} Markdown files with {len(save_errors)} errors'
)
except Exception as e:
logger.error(f'Failed to generate Markdown files: {str(e)}')
save_errors.append(f'Failed to generate Markdown files: {str(e)}')

return saved_files, save_errors

Expand Down Expand Up @@ -219,13 +224,9 @@ def filter_pattern_data(
class MySQLAnalyzer(DatabaseAnalyzer):
"""MySQL-specific database analyzer."""

SCHEMA_QUERIES = [
'table_analysis',
'column_analysis',
'foreign_key_analysis',
'index_analysis',
]
ACCESS_PATTERN_QUERIES = ['performance_schema_check', 'query_pattern_analysis']
# Use centralized query definitions from database_analysis_queries
SCHEMA_QUERIES = get_schema_queries()
PERFORMANCE_QUERIES = get_performance_queries()

@staticmethod
def is_performance_schema_enabled(result):
Expand Down Expand Up @@ -278,19 +279,11 @@ async def execute_query_batch(
for query_name in query_names:
try:
# Get query with appropriate parameters
if query_name == 'query_pattern_analysis' and pattern_analysis_days:
query = get_query_resource(
query_name,
max_query_results=self.max_results,
target_database=self.database,
pattern_analysis_days=pattern_analysis_days,
)
else:
query = get_query_resource(
query_name,
max_query_results=self.max_results,
target_database=self.database,
)
query = get_query_resource(
query_name,
max_query_results=self.max_results,
target_database=self.database,
)

result = await self._run_query(query['sql'])

Expand Down Expand Up @@ -322,7 +315,7 @@ async def analyze(cls, connection_params: Dict[str, Any]) -> Dict[str, Any]:
connection_params: Dictionary of connection parameters

Returns:
Dictionary containing results, errors, and performance schema status
Dictionary containing results, errors, performance schema status, and skipped queries
"""
analyzer = cls(connection_params)

Expand All @@ -338,6 +331,7 @@ async def analyze(cls, connection_params: Dict[str, Any]) -> Dict[str, Any]:
performance_enabled = False
all_results = {**schema_results}
all_errors = schema_errors + performance_schema_check_errors
skipped_queries = []

# Check performance schema status and run pattern analysis if enabled
if 'performance_schema_check' in performance_schema_check_results:
Expand All @@ -346,19 +340,23 @@ async def analyze(cls, connection_params: Dict[str, Any]) -> Dict[str, Any]:
)

if performance_enabled:
pattern_results, pattern_errors = await analyzer.execute_query_batch(
['query_pattern_analysis'], analyzer.pattern_analysis_days
# Run performance queries
perf_results, perf_errors = await analyzer.execute_query_batch(
cls.PERFORMANCE_QUERIES
)
all_results.update(pattern_results)
all_errors.extend(pattern_errors)
if not performance_enabled:
all_errors.append('Performance Schema disabled - skipping query_pattern_analysis')
all_results.update(perf_results)
all_errors.extend(perf_errors)
else:
# Track skipped performance queries
skipped_queries.extend(cls.PERFORMANCE_QUERIES)
all_errors.append('Performance Schema disabled - skipping performance queries')

return {
'results': all_results,
'errors': all_errors,
'performance_enabled': performance_enabled,
'performance_feature': 'Performance Schema',
'skipped_queries': skipped_queries,
}


Expand Down
Loading
Loading