mermaid-trace 0.3.1__py3-none-any.whl → 0.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mermaid_trace/__init__.py +83 -20
- mermaid_trace/cli.py +144 -34
- mermaid_trace/core/context.py +102 -41
- mermaid_trace/core/decorators.py +322 -104
- mermaid_trace/core/events.py +160 -45
- mermaid_trace/core/formatter.py +107 -28
- mermaid_trace/handlers/async_handler.py +105 -0
- mermaid_trace/handlers/mermaid_handler.py +84 -51
- mermaid_trace/integrations/fastapi.py +94 -50
- {mermaid_trace-0.3.1.dist-info → mermaid_trace-0.4.1.dist-info}/METADATA +25 -8
- mermaid_trace-0.4.1.dist-info/RECORD +16 -0
- mermaid_trace-0.3.1.dist-info/RECORD +0 -15
- {mermaid_trace-0.3.1.dist-info → mermaid_trace-0.4.1.dist-info}/WHEEL +0 -0
- {mermaid_trace-0.3.1.dist-info → mermaid_trace-0.4.1.dist-info}/entry_points.txt +0 -0
- {mermaid_trace-0.3.1.dist-info → mermaid_trace-0.4.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,86 +1,119 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Mermaid File Handler Module
|
|
3
|
+
|
|
4
|
+
This module provides a custom logging handler that writes FlowEvent objects to
|
|
5
|
+
Mermaid (.mmd) files. It handles the Mermaid syntax formatting, file headers, and
|
|
6
|
+
ensures thread-safe file writing.
|
|
7
|
+
"""
|
|
8
|
+
|
|
1
9
|
import logging
|
|
2
10
|
import os
|
|
3
11
|
|
|
12
|
+
|
|
4
13
|
class MermaidFileHandler(logging.FileHandler):
|
|
5
14
|
"""
|
|
6
15
|
A custom logging handler that writes `FlowEvent` objects to a Mermaid (.mmd) file.
|
|
7
|
-
|
|
16
|
+
|
|
8
17
|
Strategy & Optimization:
|
|
9
|
-
1. **Inheritance**: Inherits from `logging.FileHandler` to leverage robust,
|
|
18
|
+
1. **Inheritance**: Inherits from `logging.FileHandler` to leverage robust,
|
|
10
19
|
thread-safe file writing capabilities (locking, buffering) provided by the stdlib.
|
|
11
|
-
2. **Header Management**: Automatically handles the Mermaid file header
|
|
12
|
-
(`sequenceDiagram`, `title`, `autonumber`) to ensure the output file
|
|
13
|
-
is a valid Mermaid document. It smartly detects if the file is new or
|
|
20
|
+
2. **Header Management**: Automatically handles the Mermaid file header
|
|
21
|
+
(`sequenceDiagram`, `title`, `autonumber`) to ensure the output file
|
|
22
|
+
is a valid Mermaid document. It smartly detects if the file is new or
|
|
14
23
|
being appended to.
|
|
15
|
-
3. **Deferred Formatting**: The actual string conversion happens in the `emit`
|
|
24
|
+
3. **Deferred Formatting**: The actual string conversion happens in the `emit`
|
|
16
25
|
method (via the formatter), keeping the handler focused on I/O.
|
|
17
26
|
"""
|
|
18
|
-
|
|
19
|
-
def __init__(
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
filename: str,
|
|
31
|
+
title: str = "Log Flow",
|
|
32
|
+
mode: str = "a",
|
|
33
|
+
encoding: str = "utf-8",
|
|
34
|
+
delay: bool = False,
|
|
35
|
+
):
|
|
20
36
|
"""
|
|
21
|
-
Initialize the handler.
|
|
22
|
-
|
|
37
|
+
Initialize the Mermaid file handler.
|
|
38
|
+
|
|
23
39
|
Args:
|
|
24
40
|
filename (str): The path to the output .mmd file.
|
|
25
|
-
title (str): The title of the Mermaid diagram
|
|
26
|
-
mode (str): File open mode. 'w' (overwrite) or 'a' (append).
|
|
27
|
-
encoding (str): File encoding. Defaults to
|
|
28
|
-
delay (bool): If True, file opening is deferred until the first call to emit.
|
|
29
|
-
|
|
41
|
+
title (str, optional): The title of the Mermaid diagram. Defaults to "Log Flow".
|
|
42
|
+
mode (str, optional): File open mode. 'w' (overwrite) or 'a' (append). Defaults to "a".
|
|
43
|
+
encoding (str, optional): File encoding. Defaults to "utf-8".
|
|
44
|
+
delay (bool, optional): If True, file opening is deferred until the first call to emit.
|
|
45
|
+
Useful to avoid creating empty files if no logs occur. Defaults to False.
|
|
30
46
|
"""
|
|
31
|
-
# Ensure directory exists to prevent FileNotFoundError
|
|
47
|
+
# Ensure the directory exists to prevent FileNotFoundError when opening the file
|
|
32
48
|
os.makedirs(os.path.dirname(os.path.abspath(filename)) or ".", exist_ok=True)
|
|
33
|
-
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
# 1. We are overwriting the file (mode='w')
|
|
37
|
-
# 2. We are appending (mode='a')
|
|
49
|
+
|
|
50
|
+
# Determine if we need to write a header
|
|
51
|
+
# Header is written only if:
|
|
52
|
+
# 1. We are overwriting the file (mode='w'), or
|
|
53
|
+
# 2. We are appending (mode='a') but the file doesn't exist or is empty
|
|
38
54
|
should_write_header = False
|
|
39
|
-
if mode ==
|
|
55
|
+
if mode == "w":
|
|
40
56
|
should_write_header = True
|
|
41
|
-
elif mode ==
|
|
57
|
+
elif mode == "a":
|
|
42
58
|
if not os.path.exists(filename) or os.path.getsize(filename) == 0:
|
|
43
59
|
should_write_header = True
|
|
44
|
-
|
|
45
|
-
# Initialize
|
|
60
|
+
|
|
61
|
+
# Initialize the parent FileHandler (opens the file unless delay=True)
|
|
46
62
|
super().__init__(filename, mode, encoding, delay)
|
|
47
63
|
self.title = title
|
|
48
|
-
|
|
49
|
-
# Write header immediately if needed
|
|
64
|
+
|
|
65
|
+
# Write the header immediately if needed
|
|
50
66
|
if should_write_header:
|
|
51
67
|
self._write_header()
|
|
52
68
|
|
|
53
69
|
def _write_header(self) -> None:
|
|
54
70
|
"""
|
|
55
|
-
Writes the initial Mermaid syntax lines.
|
|
56
|
-
|
|
57
|
-
This setup is required for Mermaid JS or Live Editor to render the diagram.
|
|
71
|
+
Writes the initial Mermaid syntax lines to the file.
|
|
72
|
+
|
|
73
|
+
This setup is required for Mermaid JS or Live Editor to render the diagram correctly.
|
|
74
|
+
It defines:
|
|
75
|
+
- Diagram type (sequenceDiagram)
|
|
76
|
+
- Title of the diagram
|
|
77
|
+
- Autonumbering of steps
|
|
78
|
+
|
|
79
|
+
Thread Safety: Uses the handler's internal lock to prevent concurrent writes
|
|
80
|
+
when delay=True, ensuring the header is written only once.
|
|
58
81
|
"""
|
|
59
|
-
#
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
self.stream
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
82
|
+
# Use the handler's internal lock to ensure thread safety
|
|
83
|
+
assert self.lock is not None, "Handler lock should always be initialized"
|
|
84
|
+
with self.lock:
|
|
85
|
+
# Write to the existing stream if available, otherwise open temporarily
|
|
86
|
+
if self.stream:
|
|
87
|
+
# Stream is already open (delay=False or emit() has been called)
|
|
88
|
+
self.stream.write("sequenceDiagram\n")
|
|
89
|
+
self.stream.write(f" title {self.title}\n")
|
|
90
|
+
self.stream.write(" autonumber\n")
|
|
91
|
+
# Flush ensures the header is written to disk immediately
|
|
92
|
+
self.flush()
|
|
93
|
+
else:
|
|
94
|
+
# Handle delay=True case: file not yet opened
|
|
95
|
+
# Temporarily open the file just to write the header
|
|
96
|
+
with open(self.baseFilename, self.mode, encoding=self.encoding) as f:
|
|
97
|
+
f.write("sequenceDiagram\n")
|
|
98
|
+
f.write(f" title {self.title}\n")
|
|
99
|
+
f.write(" autonumber\n")
|
|
73
100
|
|
|
74
101
|
def emit(self, record: logging.LogRecord) -> None:
|
|
75
102
|
"""
|
|
76
|
-
Process a log record.
|
|
77
|
-
|
|
103
|
+
Process a log record and write it to the Mermaid file.
|
|
104
|
+
|
|
105
|
+
This method overrides the parent's emit method to filter out non-FlowEvent records.
|
|
106
|
+
|
|
78
107
|
Optimization:
|
|
79
|
-
- Checks for `flow_event` attribute first
|
|
80
|
-
|
|
81
|
-
- Delegates
|
|
82
|
-
|
|
108
|
+
- Checks for `flow_event` attribute first, acting as a high-performance filter
|
|
109
|
+
- Only processes records containing structured FlowEvent data
|
|
110
|
+
- Delegates actual writing to parent's emit() method, which handles locking and flushing
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
record (logging.LogRecord): The log record to process
|
|
83
114
|
"""
|
|
84
115
|
# Only process records that contain our structured FlowEvent data
|
|
85
|
-
|
|
116
|
+
# This allows the handler to be attached to the root logger without processing
|
|
117
|
+
# irrelevant system logs
|
|
118
|
+
if hasattr(record, "flow_event"):
|
|
86
119
|
super().emit(record)
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FastAPI Integration Module
|
|
3
|
+
|
|
4
|
+
This module provides middleware for integrating MermaidTrace with FastAPI applications.
|
|
5
|
+
It automatically traces HTTP requests and responses, converting them into Mermaid
|
|
6
|
+
sequence diagram events.
|
|
7
|
+
"""
|
|
8
|
+
|
|
1
9
|
from typing import Any, TYPE_CHECKING
|
|
2
10
|
import time
|
|
3
11
|
import uuid
|
|
@@ -6,92 +14,121 @@ from ..core.events import FlowEvent
|
|
|
6
14
|
from ..core.context import LogContext
|
|
7
15
|
from ..core.decorators import get_flow_logger
|
|
8
16
|
|
|
17
|
+
# Conditional imports to support optional FastAPI dependency
|
|
9
18
|
if TYPE_CHECKING:
|
|
19
|
+
# For type checking only, import the actual FastAPI/Starlette types
|
|
10
20
|
from fastapi import Request, Response
|
|
11
21
|
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
|
|
12
22
|
else:
|
|
13
23
|
try:
|
|
24
|
+
# Try to import FastAPI/Starlette at runtime
|
|
14
25
|
from fastapi import Request, Response
|
|
15
|
-
from starlette.middleware.base import
|
|
26
|
+
from starlette.middleware.base import (
|
|
27
|
+
BaseHTTPMiddleware,
|
|
28
|
+
RequestResponseEndpoint,
|
|
29
|
+
)
|
|
16
30
|
except ImportError:
|
|
17
|
-
# Handle the case where FastAPI/Starlette are not installed
|
|
18
|
-
#
|
|
19
|
-
#
|
|
31
|
+
# Handle the case where FastAPI/Starlette are not installed
|
|
32
|
+
# Define dummy types to prevent NameErrors at import time
|
|
33
|
+
# Instantiation will fail explicitly in __init__
|
|
20
34
|
BaseHTTPMiddleware = object # type: ignore[misc,assignment]
|
|
21
35
|
Request = Any # type: ignore[assignment]
|
|
22
36
|
Response = Any # type: ignore[assignment]
|
|
23
37
|
RequestResponseEndpoint = Any # type: ignore[assignment]
|
|
24
38
|
|
|
39
|
+
|
|
25
40
|
class MermaidTraceMiddleware(BaseHTTPMiddleware):
|
|
26
41
|
"""
|
|
27
42
|
FastAPI Middleware to trace HTTP requests as interactions in the sequence diagram.
|
|
28
|
-
|
|
29
|
-
This middleware acts as the entry point for tracing
|
|
30
|
-
1.
|
|
31
|
-
2.
|
|
32
|
-
3.
|
|
33
|
-
4.
|
|
43
|
+
|
|
44
|
+
This middleware acts as the entry point for tracing web requests, handling:
|
|
45
|
+
1. Identification of the client (Source participant)
|
|
46
|
+
2. Logging of incoming requests
|
|
47
|
+
3. Initialization of the `LogContext` for the request lifecycle
|
|
48
|
+
4. Logging of responses or errors
|
|
49
|
+
5. Cleanup of context after request completion
|
|
34
50
|
"""
|
|
51
|
+
|
|
35
52
|
def __init__(self, app: Any, app_name: str = "FastAPI"):
|
|
36
53
|
"""
|
|
37
54
|
Initialize the middleware.
|
|
38
|
-
|
|
55
|
+
|
|
39
56
|
Args:
|
|
40
|
-
app: The FastAPI application instance
|
|
41
|
-
app_name: The name of this service to appear in the diagram (e.g., "UserAPI")
|
|
57
|
+
app: The FastAPI application instance
|
|
58
|
+
app_name: The name of this service to appear in the diagram (e.g., "UserAPI")
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
ImportError: If FastAPI/Starlette are not installed
|
|
42
62
|
"""
|
|
43
|
-
if BaseHTTPMiddleware is
|
|
44
|
-
|
|
63
|
+
# Check if FastAPI is installed by verifying BaseHTTPMiddleware is not our dummy object
|
|
64
|
+
if BaseHTTPMiddleware is object: # type: ignore[comparison-overlap]
|
|
65
|
+
raise ImportError(
|
|
66
|
+
"FastAPI/Starlette is required to use MermaidTraceMiddleware"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Initialize the parent BaseHTTPMiddleware
|
|
45
70
|
super().__init__(app)
|
|
46
71
|
self.app_name = app_name
|
|
47
72
|
|
|
48
|
-
async def dispatch(
|
|
73
|
+
async def dispatch(
|
|
74
|
+
self, request: Request, call_next: RequestResponseEndpoint
|
|
75
|
+
) -> Response:
|
|
49
76
|
"""
|
|
50
|
-
Intercepts
|
|
51
|
-
|
|
77
|
+
Intercepts and processes incoming HTTP requests.
|
|
78
|
+
|
|
79
|
+
This method is called for each incoming request and handles the full
|
|
80
|
+
request-response cycle tracing.
|
|
81
|
+
|
|
52
82
|
Args:
|
|
53
|
-
request (Request): The incoming HTTP request
|
|
54
|
-
call_next (
|
|
55
|
-
|
|
83
|
+
request (Request): The incoming HTTP request object
|
|
84
|
+
call_next (RequestResponseEndpoint): Function to call the next middleware or endpoint
|
|
85
|
+
|
|
56
86
|
Returns:
|
|
57
|
-
Response: The HTTP response
|
|
87
|
+
Response: The HTTP response object
|
|
58
88
|
"""
|
|
59
|
-
# 1. Determine Source (Client)
|
|
60
|
-
# Try to get a specific ID from
|
|
61
|
-
# otherwise fallback to "Client"
|
|
89
|
+
# 1. Determine Source (Client participant)
|
|
90
|
+
# Try to get a specific ID from X-Source header (useful for distributed tracing),
|
|
91
|
+
# otherwise fallback to "Client"
|
|
62
92
|
source = request.headers.get("X-Source", "Client")
|
|
63
|
-
|
|
64
|
-
# Determine Trace ID
|
|
65
|
-
# Check X-Trace-ID header or generate new UUID
|
|
93
|
+
|
|
94
|
+
# 2. Determine Trace ID
|
|
95
|
+
# Check for X-Trace-ID header (for distributed tracing) or generate new UUID
|
|
66
96
|
trace_id = request.headers.get("X-Trace-ID") or str(uuid.uuid4())
|
|
67
|
-
|
|
68
|
-
#
|
|
69
|
-
# Format: "METHOD /path" (e.g., "GET /users")
|
|
97
|
+
|
|
98
|
+
# 3. Determine Action name
|
|
99
|
+
# Format: "METHOD /path" (e.g., "GET /users", "POST /items")
|
|
70
100
|
action = f"{request.method} {request.url.path}"
|
|
71
|
-
|
|
101
|
+
|
|
72
102
|
logger = get_flow_logger()
|
|
73
|
-
|
|
74
|
-
#
|
|
103
|
+
|
|
104
|
+
# 4. Log Request (Source -> App)
|
|
105
|
+
# Create and log the initial request event
|
|
75
106
|
req_event = FlowEvent(
|
|
76
107
|
source=source,
|
|
77
108
|
target=self.app_name,
|
|
78
109
|
action=action,
|
|
79
110
|
message=action,
|
|
80
111
|
params=f"query={request.query_params}" if request.query_params else None,
|
|
81
|
-
trace_id=trace_id
|
|
112
|
+
trace_id=trace_id,
|
|
113
|
+
)
|
|
114
|
+
logger.info(
|
|
115
|
+
f"{source}->{self.app_name}: {action}", extra={"flow_event": req_event}
|
|
82
116
|
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
|
|
117
|
+
|
|
118
|
+
# 5. Set Context and Process Request
|
|
119
|
+
# Use async context manager to set the current participant to the app name
|
|
120
|
+
# This context will be inherited by all code called within call_next()
|
|
121
|
+
async with LogContext.ascope(
|
|
122
|
+
{"participant": self.app_name, "trace_id": trace_id}
|
|
123
|
+
):
|
|
89
124
|
start_time = time.time()
|
|
90
125
|
try:
|
|
91
|
-
# Pass control to the
|
|
126
|
+
# Pass control to the next middleware or endpoint
|
|
127
|
+
# This executes the actual route logic and returns the response
|
|
92
128
|
response = await call_next(request)
|
|
93
|
-
|
|
94
|
-
#
|
|
129
|
+
|
|
130
|
+
# 6. Log Success Response (App -> Source)
|
|
131
|
+
# Calculate execution duration in milliseconds
|
|
95
132
|
duration = (time.time() - start_time) * 1000
|
|
96
133
|
resp_event = FlowEvent(
|
|
97
134
|
source=self.app_name,
|
|
@@ -100,14 +137,18 @@ class MermaidTraceMiddleware(BaseHTTPMiddleware):
|
|
|
100
137
|
message="Return",
|
|
101
138
|
is_return=True,
|
|
102
139
|
result=f"{response.status_code} ({duration:.1f}ms)",
|
|
103
|
-
trace_id=trace_id
|
|
140
|
+
trace_id=trace_id,
|
|
141
|
+
)
|
|
142
|
+
logger.info(
|
|
143
|
+
f"{self.app_name}->{source}: Return",
|
|
144
|
+
extra={"flow_event": resp_event},
|
|
104
145
|
)
|
|
105
|
-
logger.info(f"{self.app_name}->{source}: Return", extra={"flow_event": resp_event})
|
|
106
146
|
return response
|
|
107
|
-
|
|
147
|
+
|
|
108
148
|
except Exception as e:
|
|
109
|
-
#
|
|
149
|
+
# 7. Log Error Response (App --x Source)
|
|
110
150
|
# This captures unhandled exceptions that bubble up to the middleware
|
|
151
|
+
# Note: FastAPI's ExceptionHandlers might catch some exceptions before they reach here
|
|
111
152
|
err_event = FlowEvent(
|
|
112
153
|
source=self.app_name,
|
|
113
154
|
target=source,
|
|
@@ -116,7 +157,10 @@ class MermaidTraceMiddleware(BaseHTTPMiddleware):
|
|
|
116
157
|
is_return=True,
|
|
117
158
|
is_error=True,
|
|
118
159
|
error_message=str(e),
|
|
119
|
-
trace_id=trace_id
|
|
160
|
+
trace_id=trace_id,
|
|
161
|
+
)
|
|
162
|
+
logger.error(
|
|
163
|
+
f"{self.app_name}-x{source}: Error", extra={"flow_event": err_event}
|
|
120
164
|
)
|
|
121
|
-
|
|
165
|
+
# Re-raise the exception to maintain normal error handling flow
|
|
122
166
|
raise
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mermaid-trace
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Visualize your Python code execution flow as Mermaid Sequence Diagrams.
|
|
5
5
|
Project-URL: Documentation, https://github.com/xt765/mermaid-trace#readme
|
|
6
6
|
Project-URL: Changelog, https://github.com/xt765/mermaid-trace/blob/main/docs/en/CHANGELOG.md
|
|
@@ -38,6 +38,8 @@ Classifier: Programming Language :: Python
|
|
|
38
38
|
Classifier: Programming Language :: Python :: 3.10
|
|
39
39
|
Classifier: Programming Language :: Python :: 3.11
|
|
40
40
|
Classifier: Programming Language :: Python :: 3.12
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
41
43
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
42
44
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
43
45
|
Classifier: Topic :: Software Development :: Debuggers
|
|
@@ -61,17 +63,31 @@ Description-Content-Type: text/markdown
|
|
|
61
63
|
|
|
62
64
|
# MermaidTrace: The Python Logger That Draws Diagrams
|
|
63
65
|
|
|
64
|
-
[
|
|
65
|
-
|
|
66
|
+
🌐 **Language**: [English](README.md) | [中文](README_CN.md)
|
|
67
|
+
|
|
68
|
+
[](https://pypi.org/project/mermaid-trace/)
|
|
69
|
+
[](https://pypi.org/project/mermaid-trace/)
|
|
66
70
|
[](LICENSE)
|
|
67
71
|
[](https://github.com/xt765/mermaid-trace/actions/workflows/ci.yml)
|
|
68
72
|
[](https://codecov.io/gh/xt765/mermaid-trace)
|
|
69
73
|
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 📋 Overview
|
|
77
|
+
|
|
70
78
|
**Stop reading logs. Start watching them.**
|
|
71
79
|
|
|
72
80
|
MermaidTrace is a specialized logging tool that automatically generates [Mermaid JS](https://mermaid.js.org/) sequence diagrams from your code execution. It's perfect for visualizing complex business logic, microservice interactions, or asynchronous flows.
|
|
73
81
|
|
|
74
|
-
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 📚 Documentation
|
|
85
|
+
|
|
86
|
+
[User Guide](docs/en/USER_GUIDE.md) · [API Reference](docs/en/API.md) · [Contributing Guidelines](docs/en/CONTRIBUTING.md) · [Changelog](docs/en/CHANGELOG.md) · [License](docs/en/LICENSE)
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## ✨ Key Features
|
|
75
91
|
|
|
76
92
|
- **Decorator-Driven**: Just add `@trace` or `@trace_interaction` to your functions.
|
|
77
93
|
- **Auto-Diagramming**: Generates `.mmd` files that can be viewed in VS Code, GitHub, or Mermaid Live Editor.
|
|
@@ -80,6 +96,8 @@ MermaidTrace is a specialized logging tool that automatically generates [Mermaid
|
|
|
80
96
|
- **FastAPI Integration**: Includes middleware for zero-config HTTP request tracing.
|
|
81
97
|
- **CLI Tool**: Built-in viewer to preview diagrams in your browser.
|
|
82
98
|
|
|
99
|
+
---
|
|
100
|
+
|
|
83
101
|
## 🚀 Quick Start
|
|
84
102
|
|
|
85
103
|
### Installation
|
|
@@ -149,15 +167,14 @@ Visualize your generated `.mmd` files instantly:
|
|
|
149
167
|
mermaid-trace serve my_flow.mmd
|
|
150
168
|
```
|
|
151
169
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
- [English Documentation](docs/en/README.md)
|
|
155
|
-
- [中文文档](README_CN.md)
|
|
170
|
+
---
|
|
156
171
|
|
|
157
172
|
## 🤝 Contributing
|
|
158
173
|
|
|
159
174
|
We welcome contributions! Please see [CONTRIBUTING.md](docs/en/CONTRIBUTING.md) for details.
|
|
160
175
|
|
|
176
|
+
---
|
|
177
|
+
|
|
161
178
|
## 📄 License
|
|
162
179
|
|
|
163
180
|
MIT
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
mermaid_trace/__init__.py,sha256=ZXviz2KlX0eER7FPZJG2edsXfyDewt5iXpfGMifBoyE,5323
|
|
2
|
+
mermaid_trace/cli.py,sha256=w7xh9kvyaokcUcuwIsBAtgwcl9zW8mosXesp5e0CtHg,11224
|
|
3
|
+
mermaid_trace/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
mermaid_trace/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
mermaid_trace/core/context.py,sha256=wr-Ys3c6PsYCtbPUsQTrnaciSkP-fofxOewo4oZ27QM,8556
|
|
6
|
+
mermaid_trace/core/decorators.py,sha256=lNNx_Qj2cDJkPX67qPl3NBH946ofoJ8osqxq3oBoCgU,16164
|
|
7
|
+
mermaid_trace/core/events.py,sha256=h1g8uk1SGUj_NzefuJXYrkWO8ZuezeFjfU8IpYILnB8,5977
|
|
8
|
+
mermaid_trace/core/formatter.py,sha256=A9ULgcu3xHiG3iD6k54sQ7nm9kHceMvplVCHw_nu09I,5259
|
|
9
|
+
mermaid_trace/handlers/async_handler.py,sha256=Cbs6ZuKywf2VWwSIPNRXFOtoPArIhoYl-QHeW05hhWg,4272
|
|
10
|
+
mermaid_trace/handlers/mermaid_handler.py,sha256=rF-S3IXsMvTS-6kgGN7By-_2kqlCyMwcNgaorlci1Q8,5137
|
|
11
|
+
mermaid_trace/integrations/fastapi.py,sha256=H9Hl2pFxdbM3NwqONyJ7kAP-oGdOOnuoG3hEEbpoOjE,6487
|
|
12
|
+
mermaid_trace-0.4.1.dist-info/METADATA,sha256=JLDyn-TuDnehsO34g6GAArjIl-XN4izSVZIVulmiu6c,6539
|
|
13
|
+
mermaid_trace-0.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
14
|
+
mermaid_trace-0.4.1.dist-info/entry_points.txt,sha256=WS57KT_870v0A4B87QDjQUqJcddMQxbCQyYeczDAX34,57
|
|
15
|
+
mermaid_trace-0.4.1.dist-info/licenses/LICENSE,sha256=BrBog1Etiq9PdWy0SVQNVByIMD9ss4Edz-R0oXt49zA,1062
|
|
16
|
+
mermaid_trace-0.4.1.dist-info/RECORD,,
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
mermaid_trace/__init__.py,sha256=yEtdgB0Cl2qAuhGnU0zp9_YANzT3ZIrDsnQu-i3qUAc,2741
|
|
2
|
-
mermaid_trace/cli.py,sha256=_6Bm6oGIUQFbb-tr4yDoZIa9_5PQ-qjftCd7JNUm4F8,7033
|
|
3
|
-
mermaid_trace/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
mermaid_trace/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
mermaid_trace/core/context.py,sha256=H2aXivdarZgpvfAdATRWAAPpf7KHSNqhoJOepd1FK_E,6711
|
|
6
|
-
mermaid_trace/core/decorators.py,sha256=vjTnqxOCbIZXBahpgvXHBp3BFIjnIRk15O2jR9V8Ls4,9274
|
|
7
|
-
mermaid_trace/core/events.py,sha256=SG-S0hZYNa_gEpwB4Cuaahwj9WAMdzS7xXIpThoZzGQ,2999
|
|
8
|
-
mermaid_trace/core/formatter.py,sha256=WKXQeNj4l-LvbF2_Jz8FS3dyWmvtD3CHX2bQKj8p7D0,2765
|
|
9
|
-
mermaid_trace/handlers/mermaid_handler.py,sha256=dZ_T57qWUQlVNWWH5se52mB4ZioECOFwGJF52V-OOps,3931
|
|
10
|
-
mermaid_trace/integrations/fastapi.py,sha256=DeBodoPxXz2nLUIAiqmdVfFrwNVo2P0jhe7rcdF60u4,4991
|
|
11
|
-
mermaid_trace-0.3.1.dist-info/METADATA,sha256=rRBCzhTbof4unI0MPJkj-eHzKTazsodNpdfHpzDPDi0,6181
|
|
12
|
-
mermaid_trace-0.3.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
13
|
-
mermaid_trace-0.3.1.dist-info/entry_points.txt,sha256=WS57KT_870v0A4B87QDjQUqJcddMQxbCQyYeczDAX34,57
|
|
14
|
-
mermaid_trace-0.3.1.dist-info/licenses/LICENSE,sha256=BrBog1Etiq9PdWy0SVQNVByIMD9ss4Edz-R0oXt49zA,1062
|
|
15
|
-
mermaid_trace-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|