Skip to main content
iVentureTeam

profiling_qweb_view

The profiling_qweb_view widget renders a stored profiling result as annotated QWeb source, with the time and query count for every directive written into the gutter.

September 18, 2026Updated September 18, 20264 min read
Technical nameprofiling_qweb_view
Field typestext
Viewsform
Moduleweb, present in every Odoo database
Used in core1 use in Odoo 19, in odoo/addons/base/views/ir_profile_views.xml. Unchanged in Odoo 20.
VersionsOdoo 19.0, Odoo 20.0
No-code setupNo. This is a developer tool behind the profiling feature.
Alternativesjson, code

What the profiling_qweb_view widget does

When you enable profiling in Odoo, the server records how long each part of a QWeb template took and how many queries it triggered, and stores the result as JSON on an ir.profile record. This widget turns that JSON back into something a developer can read.

It loads the Ace library on startup, renders the template source in QWeb mode with the editor set to read-only, then walks the rendered DOM and attaches two kinds of annotation: a per-line summary in the gutter, and a hover panel on individual QWeb directives showing the time and queries attributed to that directive.

It also fetches the names of every view in the profile so the selector at the top can list them with their totals, letting you jump between templates without leaving the record.

What this means for your team

This is the screen you end up on when a page is slow and nobody can say why. Rather than guessing which part of a template is expensive, it shows you the line.

The value for a business is indirect but real: performance complaints usually arrive as the system is slow, which is unactionable. A profile turns that into a specific template, a specific directive and a query count, which is a fixable ticket. If your team reports slowness and your partner cannot tell you where the time goes, this is the tool they are not using.

Working examples

The only standard use, on the profiling record's result field:

<field name="result" widget="profiling_qweb_view"/>

The field must hold the JSON structure the profiler produces. The widget parses it on setup and normalizes the xpaths inside it before rendering, so an arbitrary JSON blob will not work here.

What the numbers in the gutter actually mean

Two details change how you read this screen.

First, a collapsed line aggregates its children. When the widget builds the gutter summary it checks whether the Ace row is folded:

const closed = !!row.querySelector(".ace_closed");
...
(closed ? line.xpath.startsWith(xpath) : line.xpath === xpath)

A folded element reports the total for its whole subtree. An expanded one reports only itself. So the same line can honestly show two very different numbers depending on whether you have collapsed it, and folding a block is the fastest way to ask what does this whole section cost.

Second, the widget rewrites the xpaths it is given before using them:

line.xpath = line.xpath.replace(/([^\]])\//g, "$1[1]/").replace(/([^\]])$/g, "$1[1]");

This inserts an explicit [1] index wherever the server left one implicit, so that the profiler's paths line up with the paths the widget computes while walking the editor's DOM. It is why a path you copy from this screen may not match one you read in a server log verbatim.

One practical caution: the annotation pass re-runs on every Ace render, including on scroll, and is debounced by 100 milliseconds. On a large template the screen settles rather than appearing instantly. That is the widget working, not hanging.

Version compatibility

VersionStatusNotes
Odoo 19.0VerifiedVerified against the shipped 19.0 source.
Odoo 20.0VerifiedVerified against the 20.0 branch. No changes.

Unchanged between the two branches we checked.

What is changing in Odoo 20

No change. Diffing the registration between the 19.0 and 20.0 branches shows the same single-key descriptor and no new options.

The component itself is rewritten internally for OWL 3, like every widget in Odoo 20, but nothing about the screen or how it is applied changes.

Common problems and fixes

SymptomCause and fix
The screen is blank or the editor never appearsThe field value is not the JSON structure the profiler produces. The widget parses it on setup and cannot recover from another shape. Use the widget only on a profiling result field. For arbitrary JSON, use the json widget.
Numbers change when a block is foldedWorking as designed. A collapsed line aggregates its whole subtree; an expanded one reports only itself. Fold a block deliberately when you want its total, and expand it to attribute the cost.
Annotations take a moment to appear when scrollingThe annotation pass re-runs on every Ace render and is debounced by 100 milliseconds. Expected on large templates. Let the view settle.
An xpath from this screen does not match one in a server logThe widget inserts explicit [1] indexes into the profiler's xpaths before rendering. Compare structurally rather than as strings.

Profiling_qweb_view widget vs the alternatives

WidgetBest forKey difference
profiling_qweb_viewReading a stored QWeb profile line by lineRead-only, purpose-built for the profiler's output format
jsonSeeing the raw profile structurePrints the JSON instead of annotating the template
codeReading a template without profiling dataEditable, and no timing or query annotations

There is no alternative widget for this, because there is no other widget that understands the profiler's output format. If you want the raw data rather than the annotated view, the json widget will print the stored structure, which is occasionally useful when you want to diff two profiles rather than read one.

Frequently asked questions

What does the Odoo profiling_qweb_view widget show?+
A stored QWeb profile rendered as read-only template source, with render time and query counts in the editor gutter and per-directive detail on hover. A selector at the top switches between the templates in the profile.
Why do the numbers change when I collapse a line?+
Because a folded line aggregates its entire subtree, while an expanded line reports only itself. The widget checks for Ace's collapsed class and switches between matching the exact xpath and matching every xpath beneath it.
Does profiling_qweb_view have options?+
No. Its descriptor has a single key, the component. There are no supported options and no supported types, because it is written for one field on the profiling screen.

Odoo is slow and nobody can say where?

A profile turns 'the system is slow' into a named template, a directive and a query count. We run the profiling, read what it says and fix the queries behind it, rather than adding hardware and hoping.

Request a performance audit

How this page was produced

Verified by reading addons/web/static/src/webclient/debug/profiling/profiling_qweb.js on the 19.0 branch of a local clone of the official Odoo repository. The collapsed-line aggregation and the xpath rewrite are quoted from renderProfilingInformation and processValue. The read-only editor configuration and the 100 millisecond debounce are read from _startAce and the component's setup. The registration was diffed against the 20.0 branch. Usage counts come from scanning every XML file in Community, Enterprise and odoo/addons/base. Corrections welcome via our contact page.