ref: Propagate traceback in exception logs (#4030)

Propagate traceback in exception logs
This commit is contained in:
Christophe Bornet 2024-10-07 14:16:58 +02:00 • committed by GitHub
commit 32b5da8d1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 202 additions and 217 deletions

View file

@ -72,8 +72,8 @@ def run_migrations_online() -> None:
initialize_settings_service()
service_manager.register_factory(DatabaseServiceFactory())
connectable = get_db_service().engine
except Exception as e:
logger.error(f"Error getting database engine: {e}")
except Exception:
logger.exception("Error getting database engine")
url = os.getenv("LANGFLOW_DATABASE_URL")
url = url or config.get_main_option("sqlalchemy.url")
if url:

View file

@ -74,8 +74,8 @@ class AsyncStreamingLLMCallbackHandleSIO(AsyncCallbackHandler):
# This is to emulate the stream of tokens
for resp in resps:
await self.socketio_service.emit_token(to=self.sid, data=resp.model_dump())
except Exception as exc:
logger.error(f"Error sending response: {exc}")
except Exception:
logger.exception("Error sending response")
async def on_tool_error(
self,

View file

@ -60,8 +60,8 @@ async def try_running_celery_task(vertex, user_id):
task = build_vertex.delay(vertex)
vertex.task_id = task.id
except Exception as exc:
logger.debug(f"Error running task in celery: {exc}")
except Exception:
logger.opt(exception=True).debug("Error running task in celery")
vertex.task_id = None
await vertex.build(user_id=user_id)
return vertex
@ -135,8 +135,7 @@ async def retrieve_vertices_order(
)
if "stream or streaming set to True" in str(exc):
raise HTTPException(status_code=400, detail=str(exc)) from exc
logger.error(f"Error checking build status: {exc}")
logger.exception(exc)
logger.exception("Error checking build status")
raise HTTPException(status_code=500, detail=str(exc)) from exc
@ -169,7 +168,7 @@ async def build_flow(
try:
first_layer = graph.sort_vertices(stop_component_id, start_component_id)
except Exception as exc:
logger.error(exc)
logger.exception(exc)
first_layer = graph.sort_vertices()
else:
first_layer = graph.sort_vertices()
@ -203,8 +202,7 @@ async def build_flow(
)
if "stream or streaming set to True" in str(exc):
raise HTTPException(status_code=400, detail=str(exc)) from exc
logger.error(f"Error checking build status: {exc}")
logger.exception(exc)
logger.exception("Error checking build status")
raise HTTPException(status_code=500, detail=str(exc)) from exc
async def _build_vertex(vertex_id: str, graph: Graph, event_manager: EventManager) -> VertexBuildResponse:
@ -241,7 +239,7 @@ async def build_flow(
tb = exc.formatted_traceback
else:
tb = traceback.format_exc()
logger.exception(f"Error building Component: {exc}")
logger.exception("Error building Component")
params = format_exception_message(exc)
message = {"errorMessage": params, "stackTrace": tb}
valid = False
@ -315,8 +313,7 @@ async def build_flow(
componentErrorMessage=str(exc),
),
)
logger.error(f"Error building Component: \n\n{exc}")
logger.exception(exc)
logger.exception("Error building Component")
message = parse_exception(exc)
raise HTTPException(status_code=500, detail=message) from exc
@ -524,7 +521,7 @@ async def build_vertex(
tb = exc.formatted_traceback
else:
tb = traceback.format_exc()
logger.exception(f"Error building Component: {exc}")
logger.exception("Error building Component")
params = format_exception_message(exc)
message = {"errorMessage": params, "stackTrace": tb}
valid = False
@ -602,8 +599,7 @@ async def build_vertex(
componentErrorMessage=str(exc),
),
)
logger.error(f"Error building Component: \n\n{exc}")
logger.exception(exc)
logger.exception("Error building Component")
message = parse_exception(exc)
raise HTTPException(status_code=500, detail=message) from exc
@ -695,7 +691,7 @@ async def build_vertex_stream(
raise ValueError(msg)
except Exception as exc:
logger.exception(f"Error building Component: {exc}")
logger.exception("Error building Component")
exc_message = parse_exception(exc)
if exc_message == "The message must be an iterator or an async iterator.":
exc_message = "This stream has already been closed."

View file

@ -168,8 +168,8 @@ async def simple_run_flow_task(
api_key_user=api_key_user,
)
except Exception as exc:
logger.exception(f"Error running flow {flow.id} task: {exc}")
except Exception:
logger.exception(f"Error running flow {flow.id} task")
@router.post("/run/{flow_id_or_name}", response_model=RunResponse, response_model_exclude_none=True)
@ -280,7 +280,7 @@ async def simplified_run_flow(
logger.exception(exc)
raise APIException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=exc, flow=flow) from exc
except InvalidChatInputException as exc:
logger.error(exc)
logger.exception(exc)
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
except Exception as exc:
logger.exception(exc)
@ -293,7 +293,6 @@ async def simplified_run_flow(
runErrorMessage=str(exc),
),
)
logger.exception(exc)
raise APIException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=exc, flow=flow) from exc
@ -478,15 +477,15 @@ async def experimental_run_flow(
except sa.exc.StatementError as exc:
# StatementError('(builtins.ValueError) badly formed hexadecimal UUID string')
if "badly formed hexadecimal UUID string" in str(exc):
logger.error(f"Flow ID {flow_id_str} is not a valid UUID")
logger.exception(f"Flow ID {flow_id_str} is not a valid UUID")
# This means the Flow ID is not a valid UUID which means it can't find the flow
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
except ValueError as exc:
if f"Flow {flow_id_str} not found" in str(exc):
logger.error(f"Flow {flow_id_str} not found")
logger.exception(f"Flow {flow_id_str} not found")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
if f"Session {session_id} not found" in str(exc):
logger.error(f"Session {session_id} not found")
logger.exception(f"Session {session_id} not found")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
logger.exception(exc)
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc
@ -573,7 +572,7 @@ async def create_upload_file(
file_path=file_path,
)
except Exception as exc:
logger.error(f"Error saving file: {exc}")
logger.exception("Error saving file")
raise HTTPException(status_code=500, detail=str(exc)) from exc

View file

@ -170,7 +170,7 @@ def read_flows(
if example_flow.id not in flow_ids:
flows.append(example_flow) # type: ignore
except Exception as e:
logger.error(e)
logger.exception(e)
if remove_example_flows:
flows = [flow for flow in flows if flow.folder_id != folder.id]

View file

@ -19,5 +19,5 @@ def get_starter_projects(
try:
return get_starter_projects_dump()
except Exception as exc:
logger.error(exc)
logger.exception(exc)
raise HTTPException(status_code=500, detail=str(exc)) from exc

View file

@ -42,8 +42,8 @@ def get_optional_user_store_api_key(
return None
try:
return auth_utils.decrypt_api_key(user.store_api_key, settings_service)
except Exception as e:
logger.error(f"Failed to decrypt API key: {e}")
except Exception:
logger.exception("Failed to decrypt API key")
return user.store_api_key

View file

@ -133,9 +133,9 @@ def validate_prompt(prompt_template: str, silent_errors: bool = False) -> list[s
try:
PromptTemplate(template=prompt_template, input_variables=input_variables)
except Exception as exc:
logger.error(f"Invalid prompt: {exc}")
msg = f"Invalid prompt: {exc}"
logger.exception(msg)
if not silent_errors:
msg = f"Invalid prompt: {exc}"
raise ValueError(msg) from exc
return input_variables

View file

@ -103,8 +103,8 @@ class FlowTool(BaseTool):
tweaks = self.build_tweaks_dict(args, kwargs)
try:
run_id = self.graph.run_id if self.graph else None
except Exception as e:
logger.warning(f"Failed to set run_id: {e}")
except Exception:
logger.opt(exception=True).warning("Failed to set run_id")
run_id = None
run_outputs = await run_flow(
tweaks={key: {"input_value": value} for key, value in tweaks.items()},

View file

@ -77,7 +77,7 @@ class NotionPageUpdate(LCToolComponent):
parsed_properties = json.loads(properties)
except json.JSONDecodeError as e:
error_message = f"Invalid JSON format for properties: {e}"
logger.error(error_message)
logger.exception(error_message)
return error_message
else:
@ -98,15 +98,15 @@ class NotionPageUpdate(LCToolComponent):
if e.response is not None:
error_message += f"\nStatus code: {e.response.status_code}"
error_message += f"\nResponse body: {e.response.text}"
logger.error(error_message)
logger.exception(error_message)
return error_message
except requests.exceptions.RequestException as e:
error_message = f"An error occurred while making the request: {e}"
logger.error(error_message)
logger.exception(error_message)
return error_message
except Exception as e:
error_message = f"An unexpected error occurred: {e}"
logger.error(error_message)
logger.exception(error_message)
return error_message
def __call__(self, *args, **kwargs):

View file

@ -87,13 +87,13 @@ class APIRequestComponent(Component):
try:
json_data = json.loads(parsed.data)
build_config["body"]["value"] = json_data
except json.JSONDecodeError as e:
logger.error(f"Error decoding JSON data: {e}")
except json.JSONDecodeError:
logger.exception("Error decoding JSON data")
else:
build_config["body"]["value"] = {}
except Exception as exc:
logger.error(f"Error parsing curl: {exc}")
msg = f"Error parsing curl: {exc}"
logger.exception(msg)
raise ValueError(msg) from exc
return build_config
@ -120,9 +120,9 @@ class APIRequestComponent(Component):
try:
body = json.loads(body)
except Exception as e:
logger.error(f"Error decoding JSON data: {e}")
body = None
msg = f"Error decoding JSON data: {e}"
logger.exception(msg)
body = None
raise ValueError(msg) from e
data = body if body else None

View file

@ -54,8 +54,8 @@ class SubFlowComponent(CustomComponent):
inputs = get_flow_inputs(graph)
# Add inputs to the build config
build_config = self.add_inputs_to_build_config(inputs, build_config)
except Exception as e:
logger.error(f"Error getting flow {field_value}: {e}")
except Exception:
logger.exception(f"Error getting flow {field_value}")
return build_config

View file

@ -36,8 +36,8 @@ class AIMLEmbeddingsImpl(BaseModel, Embeddings):
httpx.RequestError,
json.JSONDecodeError,
KeyError,
) as e:
logger.error(f"Error occurred: {e}")
):
logger.exception("Error occurred")
raise
return embeddings # type: ignore

View file

@ -85,8 +85,8 @@ class FlowToolComponent(LCToolComponent):
graph = Graph.from_payload(flow_data.data["data"])
try:
graph.set_run_id(self.graph.run_id)
except Exception as e:
logger.warning(f"Failed to set run_id: {e}")
except Exception:
logger.opt(exception=True).warning("Failed to set run_id")
inputs = get_flow_inputs(graph)
tool = FlowTool(
name=self.name,

View file

@ -46,8 +46,8 @@ class SubFlowComponent(Component):
inputs = get_flow_inputs(graph)
# Add inputs to the build config
build_config = self.add_inputs_to_build_config(inputs, build_config)
except Exception as e:
logger.error(f"Error getting flow {field_value}: {e}")
except Exception:
logger.exception(f"Error getting flow {field_value}")
return build_config

View file

@ -85,8 +85,8 @@ class ComposioAPIComponent(LCToolComponent):
if auth_schemes[0].auth_mode == "API_KEY":
return self._process_api_key_auth(entity, app)
return self._initiate_default_connection(entity, app)
except Exception as exc:
logger.error(f"Authorization error: {exc}")
except Exception:
logger.exception("Authorization error")
return "Error"
def _process_api_key_auth(self, entity: Any, app: str) -> str:

View file

@ -198,11 +198,11 @@ class ElasticsearchVectorStoreComponent(LCVectorStoreComponent):
msg = f"Invalid search type: {self.search_type}"
raise ValueError(msg)
except Exception as e:
logger.error(f"Search query failed: {e}")
msg = (
"Error occurred while querying the Elasticsearch VectorStore,"
" there is no Data into the VectorStore."
)
logger.exception(msg)
raise ValueError(msg) from e
return [
{"page_content": doc.page_content, "metadata": doc.metadata, "score": score} for doc, score in results

View file

@ -1,5 +1,4 @@
import json
import traceback
from typing import Any
from langchain_community.vectorstores import OpenSearchVectorSearch
@ -125,7 +124,7 @@ class OpenSearchVectorStoreComponent(LCVectorStoreComponent):
from langchain_community.vectorstores import OpenSearchVectorSearch
except ImportError as e:
error_message = f"Failed to import required modules: {e}"
logger.error(error_message)
logger.exception(error_message)
raise ImportError(error_message) from e
try:
@ -141,7 +140,7 @@ class OpenSearchVectorStoreComponent(LCVectorStoreComponent):
)
except Exception as e:
error_message = f"Failed to create OpenSearchVectorSearch instance: {e}"
logger.error(error_message)
logger.exception(error_message)
raise RuntimeError(error_message) from e
if self.ingest_data:
@ -168,8 +167,7 @@ class OpenSearchVectorStoreComponent(LCVectorStoreComponent):
vector_store.add_documents(documents)
except Exception as e:
error_message = f"Error adding documents to Vector Store: {e}"
logger.error(error_message)
logger.error(f"Traceback: {traceback.format_exc()}")
logger.exception(error_message)
raise RuntimeError(error_message) from e
else:
logger.debug("No documents to add to the Vector Store.")
@ -188,7 +186,7 @@ class OpenSearchVectorStoreComponent(LCVectorStoreComponent):
hybrid_query = json.loads(self.hybrid_search_query)
except json.JSONDecodeError as e:
error_message = f"Invalid hybrid search query JSON: {e}"
logger.error(error_message)
logger.exception(error_message)
raise ValueError(error_message) from e
results = vector_store.client.search(index=self.index_name, body=hybrid_query)
@ -232,13 +230,12 @@ class OpenSearchVectorStoreComponent(LCVectorStoreComponent):
return [{"page_content": doc.page_content, "metadata": doc.metadata} for doc in results]
error_message = f"Invalid search type:: {self.search_type}"
logger.error(error_message)
logger.exception(error_message)
raise ValueError(error_message)
except Exception as e:
error_message = f"Error during search: {e}"
logger.error(error_message)
logger.error(f"Traceback: {traceback.format_exc()}")
logger.exception(error_message)
raise RuntimeError(error_message) from e
def search_documents(self) -> list[Data]:
@ -260,6 +257,5 @@ class OpenSearchVectorStoreComponent(LCVectorStoreComponent):
return retrieved_data
except Exception as e:
error_message = f"Error during document search: {e}"
logger.error(error_message)
logger.error(f"Traceback: {traceback.format_exc()}")
logger.exception(error_message)
raise RuntimeError(error_message) from e

View file

@ -340,8 +340,8 @@ class CodeParser:
for import_node in import_nodes:
self.parse_imports(import_node)
nodes.append(class_node)
except Exception as exc:
logger.error(f"Error finding base class node: {exc}")
except Exception:
logger.exception("Error finding base class node")
nodes.insert(0, node)
class_details = ClassCodeDetails(
name=node.name,

View file

@ -215,9 +215,8 @@ class DirectoryReader:
"""
try:
file_content = self.read_file_content(file_path)
except Exception as exc:
logger.exception(exc)
logger.error(f"Error while reading file {file_path}: {exc}")
except Exception:
logger.exception(f"Error while reading file {file_path}")
return False, f"Could not read {file_path}"
if file_content is None:
@ -292,9 +291,8 @@ class DirectoryReader:
async def process_file_async(self, file_path):
try:
file_content = self.read_file_content(file_path)
except Exception as exc:
logger.exception(exc)
logger.error(f"Error while reading file {file_path}: {exc}")
except Exception:
logger.exception(f"Error while reading file {file_path}")
return False, f"Could not read {file_path}"
if file_content is None:
@ -346,8 +344,8 @@ class DirectoryReader:
if validation_result:
try:
output_types = await self.get_output_types_from_code_async(result_content)
except Exception as exc:
logger.error(f"Error while getting output types from code: {exc}")
except Exception:
logger.exception("Error while getting output types from code")
output_types = [component_name_camelcase]
else:
output_types = [component_name_camelcase]

Some files were not shown because too many files have changed in this diff Show more