netbox-community / netbox

The premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/free-netbox-cloud/
http://netboxlabs.com/oss/netbox/
Apache License 2.0
16.35k stars 2.6k forks source link

Improve debugging for faulty scripts #12766

Closed candlerb closed 1 year ago

candlerb commented 1 year ago

NetBox version

v3.5.2

Feature type

Change to existing functionality

Proposed functionality

If you upload a script but there's a problem in it, there's no information displayed beyond this:

image

Nothing is sent to Netbox logs either. I would like the actual exception to be displayed.

Use case

It's very hard to develop a script if you don't know what's wrong with it!

Using runscript from the command line doesn't help: it just returns the same as if you'd specified the wrong name for the class.

# python3 /opt/netbox/netbox/manage.py runscript --loglevel debug add_device_type_components.AddDeviceTypeComponents
Traceback (most recent call last):
  File "/opt/netbox/netbox/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/netbox/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/opt/netbox/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/netbox/venv/lib/python3.8/site-packages/django/core/management/base.py", line 402, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/netbox/venv/lib/python3.8/site-packages/django/core/management/base.py", line 448, in execute
    output = self.handle(*args, **options)
  File "/opt/netbox/netbox/extras/management/commands/runscript.py", line 93, in handle
    logger = logging.getLogger(f"netbox.scripts.{script.full_name}")
AttributeError: 'NoneType' object has no attribute 'full_name'

Trying to run the script directly from the command line, it doesn't have the right environment set up:

# python3 add_device_type_components.py
Traceback (most recent call last):
  File "add_device_type_components.py", line 5, in <module>
    from dcim.models import (Manufacturer, DeviceType, Device,
ModuleNotFoundError: No module named 'dcim'

Setting PYTHONPATH by itself is insufficient. In the end I used this recipe to run the script, by inserting the following lines at the top:

#!/opt/netbox/venv/bin/python
import django, os, sys
sys.path.append('/opt/netbox/netbox')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'netbox.settings')
django.setup()

And finally I got the error I was looking for:

# python3 add_device_type_components.py
Traceback (most recent call last):
  File "add_device_type_components.py", line 17, in <module>
    class AddDeviceTypeComponents(Script):
  File "add_device_type_components.py", line 22, in AddDeviceTypeComponents
    manufacturer = ObjectVar(model=Manufacturer)
NameError: name 'ObjectVar' is not defined

But this seems to be way too hard :-(

Database changes

None

External dependencies

None

github-actions[bot] commented 1 year ago

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.

cpmills1975 commented 1 year ago

Please keep this open. I have a number of scripts and I'm trying to build a new instance of NetBox. Some of these scripts haven't been looked at for a while and invariably contain errors against the latest version. The problem is, importing these scripts fails and I am unable to identify where the errors are.

jhofmueller commented 1 year ago

I second the request to keep this open and find a solution. Debugging scripts is a real PITA.

jeremystretch commented 1 year ago

@cpmills1975 @jhofmueller would either of you like to volunteer to work on this issue? It has been tagged as needs owner. If no one volunteers, it will be closed with the assumption that it is not worthwhile for anyone to work on.

jhofmueller commented 1 year ago

Quite frankly I fear I would be in over my head. I am pretty confident doing admin stuff with netbox, adding templates, using the API and so on but am quite unfamiliar with the internal workings. Can you point me somewhere to get started so I could estimate the amount of time needed and check back with my colleagues?

jeremystretch commented 1 year ago

Closing as stale as there have been no volunteers.

markkuleinio commented 10 months ago

Just saying this here: Looks like NetBox is logging the script errors after all, at least on 3.7.0:

2024-01-18 10:46:09,170 netbox.data_backends DEBUG: Failed to load script: Tunnel error: name 'Script' is not defined

Obviously this requires manual configuration of LOGGING. Example of such configuration is in https://majornetwork.net/2022/09/configuring-logging-in-netbox/:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'normal': {
            'format': '%(asctime)s %(name)s %(levelname)s: %(message)s'
        },
    },
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.handlers.WatchedFileHandler',
            'filename': '/var/log/netbox/netbox.log',
            'formatter': 'normal',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'INFO',
        },
        'netbox': {
            'handlers': ['file'],
            'level': 'INFO',
        },
    },
}

Note that in the example the file handler is logging DEBUG level (and up), but the loggers below that (django and netbox) are set to INFO, so to get the script errors in the log you need to set the netbox logger to level DEBUG as well.

llamafilm commented 9 months ago

Logging this kind of error at DEBUG level is a bug in my opinion. I tried submitting a PR for that but it was rejected. So to avoid spamming the log with tons of debug level messages, I found that I can enable debug level only for netbox.data_backends. My full logging configuration is below. I'm sending it to syslog, which is picked up by otel-collector and forwarded to my centralized log server.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'rfc3164': {
            'format': '{name}: {message}',
            'style': '{',
        },
    },
    'handlers': {
        'syslog': {
            'class': 'logging.handlers.SysLogHandler',
            'address': '/dev/log',
            'level': 'DEBUG',
            'formatter': 'rfc3164',
        },
    },
    'loggers': {
        'netbox': {
            'handlers': ['syslog'],
            'level': 'INFO',
        },
        'django': {
            'handlers': ['syslog'],
            'level': 'INFO',
        },
        'rq.worker': {
            'handlers': ['syslog'],
            'level': 'INFO',
        },
        'netbox.data_backends': {
            'handlers': ['syslog'],
            'level': 'DEBUG',
        },
    },
}