Search code examples
python-3.xfastapinewrelicuvicorn

NewRelic Not working with multiple workers Fast API Uvicorn


We are trying to integrate NewRelic with our Fast API Service. It works fine when we are not providing numbers of worker in uvicorn config

if __name__ == "__main__":
    # newrelic.agent.register_application()
    import newrelic.agent

    newrelic.agent.initialize()
    print("api key ", os.environ.get("NEW_RELIC_LICENSE_KEY", 1))
    print("app name ", os.environ.get("NEW_RELIC_APP_NAME", 1))
    # printing to make sure licence key and app name are defined in env variables.
    uvicorn.run(app, host='0.0.0.0', port=5600)

But when we are defining numbers of workers in the uvicorn config, NewRelic does not show any data in dashboard.

if __name__ == "__main__":
    # newrelic.agent.register_application()
    import newrelic.agent

    newrelic.agent.initialize()
    print("api key ", os.environ.get("NEW_RELIC_LICENSE_KEY", 1))
    print("app name ", os.environ.get("NEW_RELIC_APP_NAME", 1))
    # printing to make sure licence key and app name are defined in env variables.
    uvicorn.run("new_relic_test:app", host='0.0.0.0', port=5600, workers=15)

Is that due to multiple server process being created by uvicorn workers?

I tried removing workers and it worked fine. But with numbers of workers it does not work


Solution

  • The reason is the following: when you run uvicorn.run with only one process, it will start the server as a normal Python function. But, when you run with workers=n, uvicorn will start n new processes, and the original Python process will remain as an orchestrator between these. In these new processes, it will not start your code with a different entrypoint, meaning the if __name__ == "__main__" will not run (this is also why you must specify your app as a string instead of the Python instance when running more than one worker, since uvicorn needs to know where to import your app from). So in your case, newrelic.agent.initialize() is not run.

    I would suggest moving everything except uvicorn.run out of the if __name__ == "__main__" block and put it in the same file as where you define your app.