diff --git a/skyvern/forge/skyvern_json_encoder.py b/skyvern/forge/skyvern_json_encoder.py index 206334acb2..49363e4210 100644 --- a/skyvern/forge/skyvern_json_encoder.py +++ b/skyvern/forge/skyvern_json_encoder.py @@ -50,4 +50,7 @@ def _encode_value(self, value: Any) -> Any: @classmethod def dumps(cls, obj: Any, **kwargs: Any) -> str: """Helper method to properly encode objects to JSON string""" - return json.dumps(obj, cls=cls, **kwargs) + # Directly insert 'cls' into kwargs for performance (avoid re-binding at runtime) + if 'cls' not in kwargs: + kwargs['cls'] = cls + return json.dumps(obj, **kwargs) diff --git a/skyvern/forge/skyvern_log_encoder.py b/skyvern/forge/skyvern_log_encoder.py index 9b8dd23e9e..01a88d05eb 100644 --- a/skyvern/forge/skyvern_log_encoder.py +++ b/skyvern/forge/skyvern_log_encoder.py @@ -1,3 +1,4 @@ +import functools import json from datetime import datetime from typing import Any @@ -21,7 +22,14 @@ def __init__(self) -> None: @classmethod def _format_value(cls, value: Any) -> str: - return SkyvernJSONLogEncoder.dumps(value, sort_keys=True) + # Add simple caching for repeated values. Only hashable values are cached. + try: + # Only cache immutable values, since mutable objects might change between calls + # Values that are not hashable will raise TypeError + return _cached_skyvern_json_dump(value) + except TypeError: + # Fallback for unhashable types (e.g., dict, list) + return SkyvernJSONLogEncoder.dumps(value, sort_keys=True) @staticmethod def _parse_json_entry(entry: dict[str, Any]) -> dict[str, Any]: @@ -81,3 +89,8 @@ def encode(cls, log_entries: list[dict[str, Any]]) -> str: formatted_lines.append(encoder.renderer(None, None, error_entry)) return "\n".join(formatted_lines) + +@functools.lru_cache(maxsize=128) +def _cached_skyvern_json_dump(value: Any) -> str: + # For immutable/hashable values only + return SkyvernJSONLogEncoder.dumps(value, sort_keys=True)