Dash - logging the name of the callback functionin addition to POST /_dash_update-component

Hello Team,

I have configured basic logging in app.py. It works fine. I do have some suggestions.

Is it possible to expose the name of the Dash call back function in the logs ?

2025-03-27 12:47:31 - INFO - 127.0.0.1 - - [27/Mar/2025 12:47:31] "POST /_dash-update-component HTTP/1.1" 200 -
2025-03-27 12:47:53 - INFO - 127.0.0.1 - - [27/Mar/2025 12:47:53] "POST /_dash-update-component HTTP/1.1" 200 -
2025-03-27 12:47:53 - INFO - 127.0.0.1 - - [27/Mar/2025 12:47:53] "POST /_dash-update-component HTTP/1.1" 200 -
2025-03-27 12:47:59 - INFO - 127.0.0.1 - - [27/Mar/2025 12:47:59] "POST /_dash-update-component HTTP/1.1" 200 -

The logs would be much more insightful, if we could see the attributes too

  • Name of the call back function
  • Time taken for the request

Example:

2025-03-27 12:47:59 - INFO - 127.0.0.1 - - [27/Mar/2025 12:47:59] "POST /_dash-update-component HTTP/1.1" 200 - my_callback_func - 512ms

Thanks,
Sau

Hello,

Yes, you can definitely enhance your Dash application’s logging to include the callback function’s name and execution time. To achieve this, you’ll need to customize the Dash server’s request handling and integrate logging within your callback functions.

Here’s how you can modify your app.py to achieve the desired logging output:

Python

import dash
from dash import html, Input, Output
import logging
import time
from flask import request

Configure logging

logging.basicConfig(level=logging.INFO, format=‘%(asctime)s - %(levelname)s - %(message)s’)
logger = logging.getLogger(name)

app = dash.Dash(name)

app.layout = html.Div([
html.Button(‘Click Me’, id=‘my-button’),
html.Div(id=‘output-div’)
])

@app.callback(
Output(‘output-div’, ‘children’),
Input(‘my-button’, ‘n_clicks’)
)
def my_callback_func(n_clicks):
start_time = time.time()
if n_clicks is None:
return “Click the button”
time.sleep(0.5) # Simulate some processing time
end_time = time.time()
execution_time_ms = int((end_time - start_time) * 1000)

# Log the request details
logger.info(f"{request.remote_addr} - - [{time.strftime('%d/%b/%Y %H:%M:%S')}] \"POST /_dash-update-component HTTP/1.1\" 200 - {my_callback_func.__name__} - {execution_time_ms}ms")

return f"Button clicked {n_clicks} times. Callback executed in {execution_time_ms}ms"

if name == ‘main’:
app.run_server(debug=True)
Explanation:

Import Necessary Modules:

logging for logging functionality.
time for measuring execution time.
flask.request to access request details.
Configure Logging:

logging.basicConfig() sets up basic logging with a timestamp, log level, and message format.
logger = logging.getLogger(name) creates a logger instance.
Callback Function Modification: SunPass

start_time = time.time() records the start time of the callback execution.
time.sleep(0.5) simulates some processing time. Replace this with your actual callback logic.
end_time = time.time() records the end time.
execution_time_ms calculates the execution time in milliseconds.
Logging the Request Details:
logger.info(…) logs the request details, including:
request.remote_addr (client IP address).
Timestamp.
Request method and URL.
HTTP status code (200).
my_callback_func.name (name of the callback function).
execution_time_ms (execution time in milliseconds).
Key improvements:

Callback Function Name: The my_callback_func.name attribute retrieves the name of the callback function.
Execution Time: The execution time is calculated and included in the log message, providing valuable performance insights.
Request Details: The log message includes the client IP address, timestamp, request method, URL, and HTTP status code, giving you a more complete picture of the request.
Clear Log Format: The log format is customized to include all the desired information in a readable format.
Important Notes:

Best Regards

Hello James,
Thanks for your response.

If I understand correctly, as per your response, I am expected to do the logging in every call back function. This will work fine.

However, coding the extra logging statements in each and every callback is not very productive.

I was looking for something more generic or something more centralized so that I would not have to touch each and every callback function.

Regards,
Sau

Hello @sau001,

@james783 looks like it was some AI response.

I dont think there is a way to do this currently. The closest thing would be by using hooks. But I dont think you have access to the local variables at that point.

Thank you @jinnyzor

Here, give this a try, it uses the same mapping style as Dash.py:

@hooks.custom_data('custom_data')
def custom_context(_):
    body = flask.request.get_json()
    match = app.callback_map.get(body.get('output'))
    if match is None:
        match = GLOBAL_CALLBACK_MAP.get(body.get('output'))
    if match:
        print(match.get('callback'))

You’ll need to import flask for it. But it should print out the functions it is calling. You could probably fine-tune it a little to be able to target specific certain files.

1 Like

Thank you @jinnyzor

I will definitely read up on hooks. Looks promising.

1 Like