-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Missing object change webhooks and change logs when running Netbox in multi-threading mode #9439
Comments
ReasonAfter some experiments, I disabled disconnect method on @contextmanager
def change_logging(request):
"""
Enable change logging by connecting the appropriate signals to their receivers before code is run, and
disconnecting them afterward.
:param request: WSGIRequest object with a unique `id` set
"""
set_request(request)
thread_locals.webhook_queue = []
# Connect our receivers to the post_save and post_delete signals.
post_save.connect(handle_changed_object, dispatch_uid='handle_changed_object')
m2m_changed.connect(handle_changed_object, dispatch_uid='handle_changed_object')
pre_delete.connect(handle_deleted_object, dispatch_uid='handle_deleted_object')
clear_webhooks.connect(clear_webhook_queue, dispatch_uid='clear_webhook_queue')
yield
# Disconnect change logging signals. This is necessary to avoid recording any errant
# changes during test cleanup.
# post_save.disconnect(handle_changed_object, dispatch_uid='handle_changed_object')
# m2m_changed.disconnect(handle_changed_object, dispatch_uid='handle_changed_object')
# pre_delete.disconnect(handle_deleted_object, dispatch_uid='handle_deleted_object')
# clear_webhooks.disconnect(clear_webhook_queue, dispatch_uid='clear_webhook_queue')
# Flush queued webhooks to RQ
flush_webhooks(thread_locals.webhook_queue)
del thread_locals.webhook_queue
# Clear the request from thread-local storage
set_request(None) then rebuild container and re-run concurrent test and recored result. And this time I recorded total 199 Object Change created in netbox container log and netbox Change Log I think that the reason for this problem is when re-entrant, Referrence: https://stackoverflow.com/a/69401372 |
More information: The https://github.com/django/django/blob/4.0.4/django/db/models/signals.py#L42 pre_init = ModelSignal(use_caching=True)
post_init = ModelSignal(use_caching=True)
pre_save = ModelSignal(use_caching=True)
post_save = ModelSignal(use_caching=True)
pre_delete = ModelSignal(use_caching=True)
post_delete = ModelSignal(use_caching=True)
m2m_changed = ModelSignal(use_caching=True)
pre_migrate = Signal()
post_migrate = Signal() |
This repo accepts issues for the core NetBox project only. If you are using the Docker image, please file any issues under that repo. If you are able to replicate the problem using NetBox core only, please rewrite your issue above to provide the steps to do so. |
Hi Jeremy @jeremystretch, I tested with uwsgi multi-thread with Netbox Core on a VM environment and see the same result I reported earlier (Object Change count less than 199). You can install uwsgi on a VM, run I rewrited issue content to provide the steps to test my scenario with Netbox Core on Ubuntu 20.04 environment. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide. |
Hi, Steps to reproduce the issue for me:
Here's the script I use to reproduce the issue: #!/usr/bin/env bash
force_update () {
RECORDS=$(curl -ks -X PATCH ${NETBOX_URL}api/dcim/interfaces/ \
-H "Authorization: Token $NETBOX_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '[{"id": 530438}, {"id": 530484}, {"id": 529117}, {"id": 529149}]')
RECORDS_NBR=$(echo $RECORDS | jq -r '. | length')
}
count_updates() {
RECORDS=$(curl -ks \
-H "Authorization: Token $NETBOX_TOKEN" \
-H 'Accept: application/json' \
"${NETBOX_URL}api/extras/object-changes/?changed_object_type=dcim.Interface&action=update&time_after=$1")
CHANGES_COUNT=$(echo $RECORDS | jq -r '.count')
}
while true
do
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo Starting at $TIMESTAMP
force_update
count_updates "$TIMESTAMP"
echo $RECORDS_NBR records updated, $CHANGES_COUNT log entries found
if [[ "$RECORDS_NBR" != "$CHANGES_COUNT" ]]
then
echo ERROR FOUND
exit 1
fi
sleep 1
done In the example above I update 4 interfaces, but it can be other objects, you must change the ids to match proper records in your database though. Here's my current gunicorn config:
I confirm that the proposed changes to Thanks @haminhcong for your findings, and as this is my first contribution I want to express my appreciation for @jeremystretch amazing work on this project! |
Removing the disconnect from the context manager means that the already connected receivers are connected again on each request. I guess it would also mean that the receivers are always connected instead of being connected on each request (and report/script execution). I'm sure it works, but it's not the correct solution. @jeremystretch will have to chime in regarding the intention of the context manager, I'm not sure what the history is behind this comment: netbox/netbox/extras/context_managers.py Lines 30 to 31 in a397ce2
Until then I would advise you to set threads to 1 and scale workers up instead. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide. |
I just pushed branch |
@jeremystretch Hi Jeremy, I think your solution in 9439-multi-threading is good. I tested with branch Branch develop
Branch 9439-multi-threading
@srfwx can you test Jeremy solution with your tests to confirm that the problem is resolved? Thank you. |
Excellent, thank you for taking the time to test @haminhcong! |
NetBox version
v3.2.3
Python version
3.8
Steps to Reproduce
192.168.122.126
, installpython3.8-venv
,python3-dev
andgcc
packages.sudo apt install nginx
sudo ufw disable
/home/testuser01
git clone https://github.com/netbox-community/netbox.git git checkout v3.2.3 cd netbox
6379
and5432
netbox/netbox/configuration.py
filehandle_changed_object
function in filenetbox/extras/signals.py
to check process result is correct or notpython netbox/manage.py collectstatic
uwsgi.ini
config file for uwsgi in directory/home/testuser01/netbox
uwsgi --ini uwsgi.ini
/etc/nginx/nginx.conf
systemctl restart nginx
http://192.168.122.126:8080/
Expected Behavior
Device Created
change logs on Netbox Change logHandle event object class
prefix logs on Netbox uwsgi StdoutObserved Behavior
Device Created
change logs on Netbox Change logDevice Created
change logs on Netbox uwsgi stdout log. For instance in one of my test, only 167 change events processed as following log recored (plese count number lines containsHandle event object class dcim
): vm-scenario-log-missing-webhook.txtThe text was updated successfully, but these errors were encountered: