diff --git a/tools/github_tool.py b/tools/github_tool.py index d9c256a..8ec83d7 100644 --- a/tools/github_tool.py +++ b/tools/github_tool.py @@ -1,5 +1,6 @@ # tools/github_tool.py from .base_tool import BaseTool +from .metrics import metrics import requests import os import base64 @@ -313,6 +314,7 @@ class GitHubTool(BaseTool): } ] + @metrics.measure def execute(self, function_name, **kwargs): self.logger.info(f"Executing: {function_name}") @@ -354,6 +356,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _read_file(self, path): self.logger.info(f"Reading file: {path} from branch: {self.current_branch}") url = f"{self.base_url}/repos/{self.repo}/contents/{path}" @@ -368,6 +371,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _create_branch(self, branch_name, base_branch): self.logger.info(f"Creating branch: {branch_name} from base: {base_branch}") url = f"{self.base_url}/repos/{self.repo}/git/refs" @@ -376,7 +380,7 @@ class GitHubTool(BaseTool): error_message = f"Error getting base branch: {response.status_code}" self.logger.error(error_message) return error_message - + sha = response.json()["object"]["sha"] data = { "ref": f"refs/heads/{branch_name}", @@ -393,33 +397,34 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _commit_file(self, file_path, content, commit_message): self.logger.info(f"Committing file: {file_path} to branch: {self.current_branch}") if self.current_branch == "main": error_message = "Cannot commit directly to main branch" self.logger.error(error_message) return error_message - + url = f"{self.base_url}/repos/{self.repo}/contents/{file_path}" - + self.logger.info("Checking if file already exists") response = requests.get(url, headers=self.headers, params={"ref": self.current_branch}) - + data = { "message": commit_message, "content": base64.b64encode(content.encode()).decode(), "branch": self.current_branch } - + if response.status_code == 200: self.logger.info("File exists, updating") file_sha = response.json()["sha"] data["sha"] = file_sha else: self.logger.info("File does not exist, creating new file") - + response = requests.put(url, headers=self.headers, json=data) - + if response.status_code in [200, 201]: success_message = f"File committed successfully to branch '{self.current_branch}'" self.logger.info(success_message) @@ -429,6 +434,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _create_pull_request(self, title, body, base): self.logger.info(f"Creating pull request: {title} from {self.current_branch} to {base}") url = f"{self.base_url}/repos/{self.repo}/pulls" @@ -448,6 +454,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _get_branch_sha(self, branch): url = f"{self.base_url}/repos/{self.repo}/git/refs/heads/{branch}" response = requests.get(url, headers=self.headers) @@ -456,6 +463,7 @@ class GitHubTool(BaseTool): else: return f"Error getting branch SHA: {response.status_code}" + @metrics.measure def _list_files(self, path): self.logger.info(f"Listing files in: {path} on branch: {self.current_branch}") url = f"{self.base_url}/repos/{self.repo}/contents/{path}" @@ -470,6 +478,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _search_code(self, query): self.logger.info(f"Searching code with query: {query}") url = f"{self.base_url}/search/code" @@ -487,6 +496,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _get_commit_history(self, file_path, num_commits): self.logger.info(f"Getting commit history for file: {file_path}, number of commits: {num_commits}") url = f"{self.base_url}/repos/{self.repo}/commits" @@ -504,15 +514,18 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _get_current_branch(self): self.logger.info(f"Getting current branch: {self.current_branch}") return self.current_branch + @metrics.measure def _set_current_branch(self, branch_name): self.logger.info(f"Setting current branch from {self.current_branch} to {branch_name}") self.current_branch = branch_name return f"Current branch set to: {self.current_branch}" + @metrics.measure def _get_file_at_commit(self, file_path, commit_sha): self.logger.info(f"Getting file: {file_path} at commit: {commit_sha}") url = f"{self.base_url}/repos/{self.repo}/contents/{file_path}" @@ -527,6 +540,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _list_branches(self, per_page=100, all_pages=True): self.logger.info(f"Listing branches. Per page: {per_page}, All pages: {all_pages}") url = f"{self.base_url}/repos/{self.repo}/branches" @@ -556,6 +570,7 @@ class GitHubTool(BaseTool): self.logger.info(f"Successfully listed all branches. Total: {len(all_branches)}") return all_branches + @metrics.measure def _approve_pull_request(self, pull_number): self.logger.info(f"Approving pull request: {pull_number}") url = f"{self.base_url}/repos/{self.repo}/pulls/{pull_number}/reviews" @@ -572,6 +587,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _close_pull_request(self, pull_number): self.logger.info(f"Closing pull request: {pull_number}") url = f"{self.base_url}/repos/{self.repo}/pulls/{pull_number}" @@ -588,6 +604,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _merge_pull_request(self, pull_number, commit_title, commit_message, merge_method): self.logger.info(f"Merging pull request: {pull_number}") url = f"{self.base_url}/repos/{self.repo}/pulls/{pull_number}/merge" @@ -606,6 +623,7 @@ class GitHubTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _delete_branch(self, branch_name): self.logger.info(f"Deleting branch: {branch_name}") url = f"{self.base_url}/repos/{self.repo}/git/refs/heads/{branch_name}" @@ -617,4 +635,4 @@ class GitHubTool(BaseTool): else: error_message = f"Error deleting branch: {response.status_code}\nResponse: {response.text}" self.logger.error(error_message) - return error_message \ No newline at end of file + return error_message diff --git a/tools/log_tool.py b/tools/log_tool.py index 9e579e3..e051f25 100644 --- a/tools/log_tool.py +++ b/tools/log_tool.py @@ -1,6 +1,7 @@ # tools/log_tool.py from .base_tool import BaseTool +from .metrics import metrics import logging import os from datetime import datetime, timedelta @@ -49,6 +50,7 @@ class LogTool(BaseTool): } ] + @metrics.measure def execute(self, function_name, **kwargs): self.logger.info(f"Executing: {function_name}") @@ -59,6 +61,7 @@ class LogTool(BaseTool): self.logger.error(error_message) return error_message + @metrics.measure def _get_log_contents(self, line_count=150): log_file_path = 'logs/output.log' diff --git a/tools/metrics.py b/tools/metrics.py new file mode 100644 index 0000000..f4a695d --- /dev/null +++ b/tools/metrics.py @@ -0,0 +1,45 @@ +import cProfile +import pstats +import io +from functools import wraps +from collections import defaultdict + +class Metrics: + def __init__(self): + self.call_count = defaultdict(int) + self.total_time = defaultdict(float) + + def measure(self, func): + @wraps(func) + def wrapper(*args, **kwargs): + self.call_count[func.__name__] += 1 + + pr = cProfile.Profile() + pr.enable() + + result = func(*args, **kwargs) + + pr.disable() + s = io.StringIO() + ps = pstats.Stats(pr, stream=s).sort_stats('cumulative') + ps.print_stats() + + # Extract the total time spent in the function + time_spent = float(s.getvalue().split('\n')[0].split()[-2]) + self.total_time[func.__name__] += time_spent + + return result + return wrapper + + def get_metrics(self): + metrics = {} + for func_name in self.call_count: + metrics[func_name] = { + 'call_count': self.call_count[func_name], + 'total_time': self.total_time[func_name], + 'average_time': self.total_time[func_name] / self.call_count[func_name] if self.call_count[func_name] > 0 else 0 + } + return metrics + +# Create a global instance of Metrics +metrics = Metrics() \ No newline at end of file