Skip to content
Open
Changes from all commits
Commits
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
74 changes: 38 additions & 36 deletions api/extensions/ext_app_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,44 +24,46 @@ def health(): # pyright: ignore[reportUnusedFunction]
content_type="application/json",
)

@app.route("/threads")
def threads(): # pyright: ignore[reportUnusedFunction]
num_threads = threading.active_count()
threads = threading.enumerate()
if dify_config.DEBUG or app.config.get("TESTING"):

thread_list = []
for thread in threads:
thread_name = thread.name
thread_id = thread.ident
is_alive = thread.is_alive()
@app.route("/threads")
def threads(): # pyright: ignore[reportUnusedFunction]
num_threads = threading.active_count()
threads = threading.enumerate()

thread_list.append(
{
"name": thread_name,
"id": thread_id,
"is_alive": is_alive,
}
)
thread_list = []
for thread in threads:
thread_name = thread.name
thread_id = thread.ident
is_alive = thread.is_alive()

return {
"pid": os.getpid(),
"thread_num": num_threads,
"threads": thread_list,
}
thread_list.append(
{
"name": thread_name,
"id": thread_id,
"is_alive": is_alive,
}
)
Comment on lines +34 to +46
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This loop to build thread_list can be simplified into a more concise and Pythonic list comprehension. This improves readability by reducing boilerplate code.

            thread_list = [{
                "name": thread.name,
                "id": thread.ident,
                "is_alive": thread.is_alive(),
            } for thread in threads]


@app.route("/db-pool-stat")
def pool_stat(): # pyright: ignore[reportUnusedFunction]
from extensions.ext_database import db
return {
"pid": os.getpid(),
"thread_num": num_threads,
"threads": thread_list,
}

engine = db.engine
# TODO: Fix the type error
# FIXME maybe its sqlalchemy issue
return {
"pid": os.getpid(),
"pool_size": engine.pool.size(), # type: ignore
"checked_in_connections": engine.pool.checkedin(), # type: ignore
"checked_out_connections": engine.pool.checkedout(), # type: ignore
"overflow_connections": engine.pool.overflow(), # type: ignore
"connection_timeout": engine.pool.timeout(), # type: ignore
"recycle_time": db.engine.pool._recycle, # type: ignore
}
@app.route("/db-pool-stat")
def pool_stat(): # pyright: ignore[reportUnusedFunction]
from extensions.ext_database import db

engine = db.engine
# TODO: Fix the type error
# FIXME maybe its sqlalchemy issue
return {
"pid": os.getpid(),
"pool_size": engine.pool.size(), # type: ignore
"checked_in_connections": engine.pool.checkedin(), # type: ignore
"checked_out_connections": engine.pool.checkedout(), # type: ignore
"overflow_connections": engine.pool.overflow(), # type: ignore
"connection_timeout": engine.pool.timeout(), # type: ignore
"recycle_time": db.engine.pool._recycle, # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Accessing the protected member _recycle is fragile as it's an internal implementation detail of SQLAlchemy and could change in a future version, breaking this code. If you are using SQLAlchemy 1.4+, you should use the public attribute db.engine.pool.recycle. If a public API is not available for your version, consider adding a comment to explain why _recycle is used and which SQLAlchemy version this code relies on.

                "recycle_time": db.engine.pool.recycle,  # type: ignore

}
Loading