Short answer: "Python performance monitoring" covers four different jobs, and no single tool is best at all of them. Use a profiler (cProfile, py-spy) when you need to know which function in your code is slow. Use an APM or tracing backend (Sentry, Datadog APM, New Relic, Elastic APM, AppSignal, Scout, or OpenTelemetry with a backend such as SigNoz) when you need to know which requests are slow in production. Pick a platform when you also need host metrics and logs. Pick an error tracker with tracing when you mostly want slow requests next to the exceptions they throw. This guide lists what each tool is for, with prices and limits copied from each vendor's own page on 2026-10-30, and a code example for each approach that was run for this article.
Last verified: 2026-10-30. Every price, quota and support statement below is marked "read 2026-10-30" with its source. Vendors change packaging often, so re-check the linked page before you buy. Bugsly is our own product; the section about it is based on its source code, not marketing copy.
What "Python performance monitoring" actually means
- Profiling answers "where does the CPU time go inside this code path?" It is local or sampled and does not need a vendor. See the profiler section.
- Tracing / APM answers "which endpoints and database calls are slow for real users, and what changed after the deploy?" This is what most searches for "python application performance monitoring" want.
- Metrics and infrastructure monitoring answers "is the host, container or queue unhealthy?" It is a different data type from traces.
- Error monitoring answers "which exceptions are happening and how often?" Several tools below bundle it with tracing.
At a glance: what each tool is for
| Tool | Best understood as | Python integration (as documented) | Entry price or free tier (read 2026-10-30) |
|---|---|---|---|
| Sentry | Error monitoring with tracing and profiling | sentry-sdk, traces_sample_rate | Free Developer plan (one user). Team from $26/mo billed annually, which includes 50k errors and 5M spans |
| Datadog APM | Full observability platform | ddtrace / ddtrace-run | APM from $31 per host per month billed annually ($36 on-demand with Infrastructure Monitoring attached) |
| New Relic | Full observability platform | Python agent | Free tier with 100 GB ingest per month and one full platform user; $0.40 per GB beyond that |
| Elastic APM | Tracing for the Elastic stack | elastic-apm agent | Pricing depends on how you run Elastic; not compared here |
| AppSignal | Focused APM and errors | OpenTelemetry-based Python package | Free plan: 30K requests, 1 GB logs, 5-day retention |
| Scout | Focused APM, errors and logs | Scout Python agent | Free: 300K transactions per month; paid from $19/mo |
| OpenTelemetry + a backend | Vendor-neutral instrumentation | OpenTelemetry Python SDK | SDK is free; backend cost depends on the backend (SigNoz Cloud starts at $49/mo usage minimum) |
cProfile / py-spy | Profilers | Standard library / separate CLI | Free |
| Bugsly | Error monitoring with limited tracing and profiling | sentry-sdk pointed at a Bugsly DSN | Free plan; see pricing |
Sources for the table are in each section below. If a cell says "not compared here", we did not read that vendor's pricing today and make no claim.
Sentry
Sentry is primarily error monitoring that added tracing and profiling. Its docs describe enabling tracing with traces_sample_rate in sentry_sdk.init (read 2026-10-30 at docs.sentry.io/platforms/python/tracing).
- The pricing page lists a free Developer plan limited to one user with error monitoring and tracing, and a Team plan at $26/mo when billed annually with default pre-paid data (read 2026-10-30, sentry.io/pricing).
- Sentry's pricing docs say each paid plan includes 50k errors, 5M spans, 5 GB of logs and 50 replays per month, and that continuous profiling and UI profiling are available only through pay-as-you-go budget (read 2026-10-30, docs.sentry.io/pricing).
Good fit when errors are the main job and you want tracing next to them. Because tracing is billed in spans, a service that emits many spans per request needs a sampling rate chosen with the span quota in mind.
Datadog APM
Datadog is a platform: APM sits next to infrastructure monitoring, logs and many other products. The pricing page lists APM starting at $31 per host per month billed annually, and $36 on-demand when Infrastructure Monitoring is attached (read 2026-10-30, datadoghq.com/pricing). The same page lists the APM plan as including 15-minute live trace search, 15-day historical search and RED metrics based on 100% of traffic with 15-month retention.
For Python, the docs instruct you to install the package and prefix your entry point with ddtrace-run, for example ddtrace-run python app.py (read 2026-10-30, Datadog Python tracing docs). Pricing is per host, so cost follows your fleet size rather than your request volume.
New Relic
New Relic bills on data ingest and users rather than hosts. Its pricing page lists a free tier with 100 GB of data ingest per month and one free full platform user, with $0.40 per GB beyond the free 100 GB on the original data option, and full platform users from $10 on the Standard edition (read 2026-10-30, newrelic.com/pricing). The page also says data ingest stops if you exceed the free 100 GB until you upgrade or the next month begins.
The Python agent documentation says it works with web frameworks and hosting mechanisms including Django, Gunicorn, WSGI, CherryPy and uWSGI (read 2026-10-30, New Relic Python agent docs).
Elastic APM
The Elastic APM Python agent sends performance metrics and error logs to the APM Server, with built-in support for Django and Flask performance metrics and error logging and generic WSGI support for error logging; Elastic's page also points to OpenTelemetry and its EDOT Python SDK as an alternative (read 2026-10-30, Elastic APM Python agent docs). It makes most sense if you already run or buy the Elastic stack.
AppSignal
AppSignal's Python docs say it sends error and performance data through OpenTelemetry and lists Celery, Django, FastAPI and Flask among supported libraries (read 2026-10-30, docs.appsignal.com/python). Its pricing page lists a free plan at $0 with 30K requests, 1 GB of logging and 5-day retention, and a 30-day free trial with no credit card needed (read 2026-10-30, appsignal.com/pricing).
Scout
Scout's pricing page says the free plan includes 300K monthly transactions, 5,000 errors, 1 GB of log data and 1 endpoint monitored for anomalies, with paid plans from $19/month (600K transactions) and every plan including unlimited users and apps (read 2026-10-30, scoutapm.com/pricing). The page says Scout covers Ruby, Python, PHP and Elixir applications. It is priced by transaction tier, not by host or seat.
OpenTelemetry with SigNoz, Jaeger or Grafana
OpenTelemetry is the vendor-neutral way to produce traces; you still need a backend to store and view them. The Python docs state that OpenTelemetry-Python supports Python 3.10 and higher (read 2026-10-30, opentelemetry.io/docs/languages/python), which matters if you still run an older interpreter.
Backends differ in what you pay for. SigNoz Cloud's pricing page lists a $49/month minimum that includes $49 of usage, then $0.30 per GB for traces and logs and $0.10 per million metric samples (read 2026-10-30, signoz.io/pricing). Grafana Cloud's pricing page lists a free tier with 50 GB of traces ingested per month and 14-day retention, and a Pro plan with a $19/month platform fee plus usage (read 2026-10-30, grafana.com/pricing). This route gives you the most control and the most to operate yourself.
Profilers: cProfile and py-spy
Profilers need no account. The standard library's cProfile is a deterministic profiler; Python's docs note that deterministic profiling adds only small overhead in typical applications because of the interpreter's own overhead (read 2026-10-30, docs.python.org/3/library/profile.html). py-spy is a sampling profiler that can look at a running program without restarting it or changing its code; its README says macOS always requires running as root (read 2026-10-30, github.com/benfred/py-spy). We did not run py-spy for this article because it needs root on macOS.
Bugsly: what exists and what does not
This is the part we can describe from our own source code. Bugsly accepts the Sentry envelope format, so the standard sentry-sdk does the instrumenting and you point it at a Bugsly DSN.
| Capability | State (from Bugsly's code, checked 2026-10-30) |
|---|---|
| Exceptions with tracebacks | Yes |
Transactions and spans from traces_sample_rate | Stored. Transaction and span envelope items are accepted and queued; transactions are rate-limited on their own per-minute budget so a tracing flood does not drop errors |
| Transaction list, p50/p75/p90/p95/p99 per transaction name, single transaction with its spans | Yes, via the dashboard's performance API |
Profiles from profiles_sample_rate | Yes, with a flame graph view per transaction and release; up to 5 profiles per envelope are kept, and profile data is kept for at most 14 days (less on plans with shorter retention) |
| Distributed service map, host or container metrics, database monitoring | No |
Other vendors' agents (ddtrace, New Relic, Elastic APM) | Not ingested; only Sentry-format envelopes |
| Self-hosting | No, managed service only |
So Bugsly's performance monitoring is a limited feature set. It is useful when the question is "which transaction is slow and which error came with it". It is not a replacement for a platform when you need infrastructure monitoring, service maps or database insight. Plan quotas are on the pricing page.
Working examples (each was run on 2026-10-30)
All examples ran on Python 3.13.11 on macOS in a fresh virtual environment with the package installed from PyPI. Where the real vendor backend would need an account, the example sent data to a local HTTP listener we wrote, so what it prints is what the library puts on the wire, not what a vendor's dashboard shows.
Sentry SDK (works with Sentry or a Bugsly DSN)
# pip install sentry-sdk (ran with sentry-sdk 2.73.0)
import time, sentry_sdk
sentry_sdk.init(
dsn="https://<public-key>@<host>/<project-id>",
traces_sample_rate=1.0, # use a lower value in production
profiles_sample_rate=1.0,
release="myapp@1.0.0",
)
@sentry_sdk.trace
def build_report():
time.sleep(0.05)
with sentry_sdk.start_transaction(op="task", name="monthly-report"):
build_report()
try:
1 / 0
except ZeroDivisionError:
sentry_sdk.capture_exception()We pointed the DSN at a local listener and decoded the request bodies. It printed:
POST /api/1/envelope/ ['profile', 'transaction']
transaction: monthly-report spans: ['__main__.build_report']
POST /api/1/envelope/ ['event']That shows the SDK sends a transaction item (with one span for the decorated function), a profile item, and the exception as an event. Bugsly's envelope endpoint has handlers for exactly these item types (transaction, span, profile, event).
OpenTelemetry (vendor-neutral)
# pip install opentelemetry-sdk (ran with 1.45.2)
import time
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("myapp")
with tracer.start_as_current_span("monthly-report"):
with tracer.start_as_current_span("load-rows"):
time.sleep(0.05)It printed two spans sharing one trace id, the inner load-rows span (about 52 ms) with the outer monthly-report as its parent, and monthly-report with no parent. Swapping ConsoleSpanExporter for an OTLP exporter sends the same spans to SigNoz, Jaeger or Grafana.
Elastic APM agent
# pip install elastic-apm (ran with 6.26.2)
import time, elasticapm
client = elasticapm.Client(service_name="myapp", server_url="http://127.0.0.1:8902")
client.begin_transaction("task")
with elasticapm.capture_span("load-rows"):
time.sleep(0.05)
client.end_transaction("monthly-report", "success")
client.close()Against a local listener it posted once to /intake/v2/events as application/x-ndjson and sent a metadata record, a span named load-rows and a transaction named monthly-report.
Datadog ddtrace
# pip install ddtrace (ran with 4.16.1)
import time
from ddtrace import tracer
with tracer.trace("monthly-report", service="myapp"):
with tracer.trace("load-rows"):
time.sleep(0.05)With DD_TRACE_AGENT_URL pointed at a local listener, it sent POST /v0.4/traces containing the spans monthly-report and load-rows, both with service myapp. In real use the library talks to a Datadog Agent, which needs an account.
New Relic agent
We installed newrelic 14.2.0, generated a config file with newrelic-admin generate-config, and confirmed the instrumentation API (newrelic.agent.function_trace, background_task) imports. We did not send any data, because the agent needs a real license key from a New Relic account.
cProfile (standard library)
import cProfile, pstats, io, time
def load_rows(): return sum(i * i for i in range(300000))
def build_report(): load_rows(); time.sleep(0.05)
pr = cProfile.Profile(); pr.enable(); build_report(); pr.disable()
s = io.StringIO()
pstats.Stats(pr, stream=s).sort_stats("cumulative").print_stats(4)
print(s.getvalue())It printed 300006 function calls in 0.310 seconds and ranked build_report at 0.310 s cumulative, load_rows at 0.251 s, and the generator expression as 300001 calls. That is the kind of answer a profiler gives that a request-level APM cannot: which function inside the request is expensive.
AppSignal and Scout were not run, because their agents require an account to report anywhere; we only quote their documentation and pricing above.
How to choose
- You want to know why a function is slow: start with
cProfileorpy-spy; no vendor needed. - You mostly care about exceptions, with slow requests as context: an error tracker with tracing (Sentry, Bugsly, Scout, AppSignal) is the shorter path.
- You need hosts, containers, logs and traces in one place: a platform (Datadog, New Relic) or the OpenTelemetry route with a backend you choose.
- Pricing predictability matters: compare the unit. Datadog APM is per host, New Relic is per GB and per user, Sentry is per event category and span, Scout is per transaction tier, Grafana and SigNoz are per GB.
- You want to stay portable: instrument with OpenTelemetry; moving backends later means changing an exporter.
Try it on your own service
Paste a real traceback into the free Explain Error tool to see how Bugsly reads a Python exception; no signup is needed for the tool. When you want your own project data, create a Bugsly account, use the Python guide or the FastAPI guide, and set the DSN in the sentry-sdk example above. For error-only comparisons see the best Python error tracking tools.
Frequently asked questions
What is the difference between a profiler and an APM?
A profiler such as cProfile or py-spy shows where time goes inside your code. An APM records requests, spans and errors from real traffic over time, so you can see which endpoints are slow and what changed after a deploy. They answer different questions and are often used together.
Does Bugsly work with the Sentry Python SDK?
Yes. Install sentry-sdk, set the DSN to your Bugsly project and enable traces_sample_rate and profiles_sample_rate. Bugsly's ingest accepts transaction, span, profile and error items from that SDK, as shown in the example above.
Does Bugsly replace Datadog or New Relic for Python?
Only partly. Bugsly stores errors, transactions with spans, and profiles for your application code. It has no host or container metrics, service map or database monitoring, and it does not ingest ddtrace or New Relic agent data.
Which Python performance monitoring tools have a free plan?
As read on 2026-10-30: Sentry's Developer plan (one user), New Relic's free tier (100 GB ingest per month), AppSignal's free plan (30K requests), Scout's free plan (300K transactions), Grafana Cloud's free tier (50 GB of traces per month), and Bugsly's free plan. Limits differ widely, so check the linked pages.
Does OpenTelemetry work on older Python versions?
OpenTelemetry's Python docs, read 2026-10-30, say OpenTelemetry-Python supports Python 3.10 and higher.
Try Bugsly Free
Track up to 100 issues per month on the free plan; events are not billed.
Get Started FreeRelated Articles
Best Error Tracking Tools for FastAPI in 2026
Discover the top error tracking tools for FastAPI developers in 2026. Compare features, pricing, and integrations to find the best fit for your projects.
Read moreBest Alerting Tools for Remix in 2026
Discover the top alerting tools for Remix developers in 2026. Compare features, pricing, and integrations to find the best fit for your projects.
Read moreBest Performance Monitoring Tools for NestJS in 2026
Compare the best performance monitoring tools for NestJS in 2026. Find the right solution for error tracking, alerting, and more.
Read moreBest Monitoring Tools for Laravel in 2026
Discover the top monitoring tools for Laravel developers in 2026. Compare features, pricing, and integrations to find the best fit for your projects.
Read moreFrom the same team
SEOBolt
Technical SEO and AI search audits with ready-to-apply fix plans.
Try SEOBolt →GrowFast
Domain in, qualified B2B leads out, with cold outreach and deliverability handled.
Try GrowFast →AutoShort
Turn a topic into a faceless short: AI script, voiceover and captions.
Try AutoShort →RemixViral
Paste a long video and get back the moments worth posting, cut vertical and captioned.
Try RemixViral →