Skip to content
Documentation

Test Manual — NoSqlStudio Profiler

A step-by-step guide to open, use, and validate the new Profiler screen.

Estimated time: ~30 minutes
In this manual

Introduction

A step-by-step guide to help you open, use, and validate the new Profiler screen. Follow from Step 1 to the end, in order. Each step tells you what to do and what you will see. You don't need to know anything about profiling beforehand — the 💡 boxes explain the concepts right when they come up.

How to read this manual

Each step has:

  • Do — the exact action (click, type, run such-and-such script).
  • See — what should happen on screen. This is your “pass / fail”.
  • Why — only when it helps you understand (you can skip it if you're in a hurry).

Concept

Concept box. Explains a term right when it appears.

Heads-up

Heads-up. A detail that tends to be confusing.

Before you start

Concept

What the Profiler is

MongoDB can keep a “logbook” of everything it runs — every query, how long it took, whether it used an index — in a collection called system.profile. The Profiler screen turns that logbook on and shows it graphically: charts, filters, and even index recommendations.

You will need:

  1. 1The dev server restarted after the last build (without that the screen won't even load — that's what causes the spacingPx error).
  2. 2A connected MongoDB connection. It can be local, on-prem, or Atlas M10+. On Atlas M0/M2/M5 (free) the profiler is blocked by MongoDB — it works, but the screen will warn that it's restricted (we test this in Step 41).
  3. 3The database user needs to be able to run administration commands (setProfilingLevel, createIndex). A “database owner” user does the job.

Estimated time for the full walkthrough: ~30 minutes.

Stage 1

Prepare the lab database

For the Profiler to have something to show, we first create a database with plenty of data.

Step 1

Create the profiler_lab database

Do

Open the Mongo Shell tab (or the Scratchpad) in NoSqlStudio, paste the script below, and run it.

js·35 linhas
use profiler_lab;
db.dropDatabase();
use profiler_lab;

['orders', 'products', 'customers'].forEach((c) => db.getCollection(c).drop());

function seed(coll, n, gen) {
  const c = db.getCollection(coll);
  let buf = [];
  for (let i = 0; i < n; i++) {
    buf.push(gen(i));
    if (buf.length === 165000) { c.insertMany(buf); buf = []; }
  }
  if (buf.length) c.insertMany(buf);
  print(coll + ': ' + c.countDocuments());
}

const ST = ['pending', 'paid', 'shipped', 'cancelled', 'refunded'];
const RG = ['north', 'south', 'east', 'west'];

seed('orders', 120000, (i) => ({
  orderNo: i, status: ST[i % 5], region: RG[i % 4],
  customerId: (i * 7) % 5000, total: Math.round(Math.random() * 1e5) / 100,
  items: 1 + (i % 8), createdAt: new Date(Date.now() - (i % 90) * 864e5),
  note: 'order line '.repeat(4),
}));
seed('products', 20000, (i) => ({
  sku: 'SKU-' + i, category: ['a', 'b', 'c', 'd', 'e'][i % 5],
  price: Math.round(Math.random() * 5e4) / 100, stock: i % 500,
  active: i % 3 !== 0,
}));
seed('customers', 5000, (i) => ({
  customerId: i, tier: ['free', 'pro', 'enterprise'][i % 3],
  city: RG[i % 4], spend: Math.round(Math.random() * 1e6) / 100,
}));
See

After a few seconds, the shell prints:

Console output
orders: 120000
products: 20000
customers: 5000
Why

120 thousand orders is enough for a query without an index to become visibly slow — and slowness is exactly what we want to diagnose.

Heads-up

If later on the queries don't exceed 100 ms (fast machine), come back here and change 120000 to 300000.

Stage 2

Open the Profiler screen

Step 2

Open it for the first time

Do

Open the Profiler in one of these 3 ways (they all lead to the same place — test the other two later, in Step 46):

  • Main menu → Database Profiler, or the shortcut Ctrl+Alt+Shift+P.
  • Toolbar → Monitoring → Database Profiler menu.
  • Right-click a connection in the sidebar → Profiler.
See

A new tab named Profiler opens, with the connection name next to it. From top to bottom, the tab has: a header bar, a control strip, and four section buttons (Dashboard, Live Feed, Index Advisor, Sessions).

Step 3

Choose the database

Do

In the header, in the Database field, choose `profiler_lab`.

See

The screen now works on that database. Since we haven't turned profiling on yet, the Dashboard shows a message like “No profiling data yet”.

Heads-up

The profiler is per database. Everything in this manual uses profiler_lab. If you choose another database, you won't see the triggers.

Stage 3

Turn on profiling

Step 4

Understand the control strip

See

Right below the header there is a strip with:

  • Profiling — three buttons: Off · Slow ops · All ops.
  • slowms and Sample — two numeric fields + an Apply button.
  • Filter — opens a filter builder.
  • ⏱ Capture — a safe timed capture.
  • system.profile — a small usage bar for the collection + a Resize button.
  • Health — a grade (A–F) with a score.

Concept

The three levels. Off = records nothing. Slow ops = records only what exceeded the slowms threshold. All ops = records everything. To test, we'll go with All ops to see all the traffic.

Step 5

Turn it on at the “All ops” level

Do

Click the All ops button.

  • The status dot on the left turns blue.
  • A warning pill “⚠ All ops” appears (a reminder that level 2 has a performance cost).
  • A quick message confirms “Profiling level set to 2”.
Why

This is the heart of the tool. In the old profiler, this just copied a command for you to paste into the shell. Now the click actually turns profiling on. If the dot turned blue, the main technical path works. ✅

Stage 4

Generate traffic (the “triggers”)

Now we'll run queries in the shell so the Profiler has something to show. Keep the Profiler tab open — it refreshes itself every few seconds.

Step 6

Trigger A — slow queries

Do

Run in the shell:

js·3 linhas
use profiler_lab;
db.orders.find({ status: 'shipped' }).toArray().length;
db.orders.find({ region: 'south' }).sort({ total: -1 }).toArray().length;
See

Within 1–3 seconds, in the Live Feed section, two new query operation rows on profiler_lab.orders, with a red COLLSCAN badge.

Concept

COLLSCAN vs IXSCAN. COLLSCAN = MongoDB read document by document because there was no index — slow. IXSCAN = it used an index (a shortcut) — fast. Red badge = bad; blue badge = good.

Step 7

Trigger B — inefficient query

Do

Run in the shell:

js·2 linhas
use profiler_lab;
db.orders.find({ status: 'refunded', region: 'north', items: 7 }).toArray();
See

One more row in the feed. In the Examined → Returned column the number turns red — it examined 120 thousand documents to return just a few.

Concept

Inefficient. When the database “examines” much more than it “returns”, it's wasting work — a strong candidate for an index.

Step 8

Trigger C — writes

Do

Run in the shell:

js·4 linhas
use profiler_lab;
db.orders.insertOne({ orderNo: 999001, status: 'paid', region: 'east', items: 2 });
db.orders.updateMany({ status: 'pending' }, { $set: { flagged: true } });
db.orders.deleteMany({ flagged: true, items: 3 });
See

Three new operations: insert, update, remove.

Step 9

Triggers D, E, F — aggregation, count, and cursors

Do

Run in the shell:

js·9 linhas
use profiler_lab;
db.orders.aggregate([
  { $match: { status: 'paid' } },
  { $group: { _id: '$region', n: { $sum: 1 }, rev: { $sum: '$total' } } },
]).toArray();
db.orders.countDocuments({ region: 'west' });
db.orders.distinct('status');
let cur = db.orders.find({}).batchSize(500).limit(5000);
let k = 0; while (cur.hasNext()) { cur.next(); k++; } print(k);
See

Operations of type command (the aggregation, the count) and several getmore (the cursor reading in batches).

Step 10

Trigger G — the same query repeated

Do

Run in the shell:

js·2 linhas
use profiler_lab;
for (let i = 0; i < 40; i++) db.orders.find({ status: 'paid' }).limit(10).toArray();
See

Nothing special in the feed right now — but keep it in mind: in Step 24 this becomes a single row in the “Query shapes” panel, with a count of 40.

Stage 5

Explore the Live Feed

Step 11

Open the feed

Do

Click the Live Feed section (at the top).

See

A table with the operations, the most recent at the top. Columns: time, type, collection, duration (color-coded — green fast, red slow), plan (COLLSCAN/IXSCAN badge), examined→returned, and app. At the top, “X of Y operations”.

Step 12

See the live mode working

Do

Run Trigger A (the one from Step 6) again and keep an eye on the feed:

js·3 linhas
use profiler_lab;
db.orders.find({ status: 'shipped' }).toArray().length;
db.orders.find({ region: 'south' }).sort({ total: -1 }).toArray().length;
See

New rows appear on their own at the top within seconds.

Step 13

Pause and resume

Do

In the header, click the ● Live button (it becomes ⏸ Paused). Run Trigger A again:

js·3 linhas
use profiler_lab;
db.orders.find({ status: 'shipped' }).toArray().length;
db.orders.find({ region: 'south' }).sort({ total: -1 }).toArray().length;
See

The feed does not grow — it's frozen. Click ⏸ Paused to go back to ● Live: it starts growing again.

Why

Pausing is useful for inspecting a row without the list jumping around.

Step 14

Quick filters (the preset chips)

Do

Click, one at a time, the chips at the top of the feed:

  • Slow > 100ms — only slow operations.
  • COLLSCANs — only the ones without an index (red badge).
  • Inefficient — highlights the one from Step 7.
  • Writes — only insert/update/remove (the ones from Step 8).
  • Last 5 min — only recent traffic.
See

The table shrinks to show only what matches. The active chip stays highlighted. Click it again to turn it off.

Step 15

Fine-grained filters

Do

Do, in sequence:

  1. 1Click the type chips (query, insert, getmore…) to turn them on/off.
  2. 2In the All collections dropdown, choose orders.
  3. 3In the search box, type refunded.
See

Each filter narrows the list. They combine with each other.

Step 16

Clear everything

Do

Click Clear filters (it appears when there is an active filter).

See

The table goes back to showing everything.

Stage 6

Explore the Dashboard

Step 17

Open the Dashboard

Do

Click the Dashboard section.

See

Four number cards at the top (Operations, Slow ops, Collection scans, Average duration) and, below them, several charts.

Step 18

The indicators (KPIs)

See

The four numbers reflect everything you triggered. “Collection scans” shows the percentage of COLLSCANs — the higher, the worse.

Step 19

Timeline

See

The Operations over time chart shows bands stacked by type (reads, inserts, updates, deletes, commands), with a color-coded legend.

Step 20

Index usage (donut)

See

The Index usage donut chart splits the operations into COLLSCAN (red), IXSCAN (blue), and others. Right now it should be dominated by red.

Step 21

Latency distribution

See

Bars grouping the operations by time range (0–1ms, …, >5s).

Step 22

Hottest collections (treemap)

See

Blocks proportional to the total time spent on each collection. orders should be the biggest block.

Step 23

Click a treemap block

Do

Click the orders block.

See

The screen jumps to the Live Feed, already filtered by orders. (Go back to the Dashboard afterwards.)

Step 24

Query shapes

See

The Query shapes table groups queries with the same “shape”. The query you repeated 40× in Step 10 shows up as a single row, with a count of 40 and the total time summed up.

Why

This is how you discover “which query, summing all its runs, weighs most on the database” — even if each individual execution is fast.

Step 25

Slowest operations

See

The final table lists the 8 slowest operations. Keep it in mind for the next step.

Stage 7

Investigate an operation (drill-down)

Step 26

Open the detail panel

Do

Click any row — in the Live Feed, in the query shapes table, or in the slowest one.

See

A panel slides in from the right with the full detail of the operation.

Step 27

Read the numbers

See

A grid with Duration, Plan, Yields, Docs examined, Keys examined, Returned. If the operation is inefficient, a red warning says it is a “strong index candidate”.

Step 28

Request the live “explain”

Do

Click Explain this query.

See

The tool runs explain() on the spot and shows the real plan, the execution time, and how many documents were examined — useful for confirming the diagnosis on the current database.

Concept

Explain. This is MongoDB describing how it intends to run the query. It confirms whether it would use an index or not.

Step 29

See the command and the details

Do

In the panel, look at the Command section (the operation's JSON) and click the copy icon. Then click Execution stats and Raw document to expand/collapse them.

See

The command is copied to the clipboard; the sections open and close.

Step 30

Close the panel

Do

Close it with the X at the top of the panel — and open another and close it by clicking the dimmed area beside it.

See

The panel disappears both ways.

Stage 8

Use the Index Advisor (the highlight)

Step 31

Generate recommendations

Do

Run in the shell (3 problematic queries, repeated 30×):

js·6 linhas
use profiler_lab;
for (let i = 0; i < 30; i++) {
  db.orders.find({ status: 'shipped' }).toArray();
  db.orders.find({ region: 'north' }).sort({ createdAt: -1 }).limit(20).toArray();
  db.products.find({ category: 'c', active: true }).toArray();
}
See

Wait a few seconds. (Continues in the next step.)

Step 32

Open the Index Advisor

Do

Click the Index Advisor section.

See

At the top, a Health card with a grade (A–F) — probably low (C/D), because you generated many COLLSCANs. Below it, a list of index recommendations — about 3 cards.

Step 33

Read a recommendation

See

Each card has: a severity pill (High/Medium/Low), the collection, the query “shape”, chips with the fields of the suggested index (with ↑/↓ arrows), and an impact line (“N operations · X s total · M scans”).

Concept

Why those fields in that order. The advisor follows the ESR rule: equality fields first, then the sort fields, then the range ones. That's the order that makes the index most efficient.

Step 34

Create an index with 1 click

Do

On a card, click Create index. Check the command in the modal and confirm.

See

An “Index created” message. The card for that recommendation changes to ✓ Already indexed.

Step 35

Create the rest

Do

Repeat Step 34 for the other recommendations.

See

They all become ✓ Already indexed.

Stage 9

Confirm it improved

Step 36

Run the same queries again

Do

Run the same script from Step 31 again (repeated here so you don't have to go back):

js·6 linhas
use profiler_lab;
for (let i = 0; i < 30; i++) {
  db.orders.find({ status: 'shipped' }).toArray();
  db.orders.find({ region: 'north' }).sort({ createdAt: -1 }).limit(20).toArray();
  db.products.find({ category: 'c', active: true }).toArray();
}
See

The queries run again — now with the indexes you created in Stage 8 already in effect.

Step 37

See COLLSCAN turn into IXSCAN

Do

Go to the Live Feed.

See

The same queries now show a blue IXSCAN badge and a much shorter duration. They used to read 120 thousand documents; now they use the index.

Step 38

See the Health grade go up

Do

Go back to the Index Advisor (or click the Health pill in the control strip).

See

The grade went up (e.g., from C/D to A/B) and there are fewer recommendations. You just completed a full cycle: diagnose → fix → prove. ✅

Stage 10

Sessions and report

Concept

Session. A “snapshot” of the current profiling state, saved with a name. It's used to compare “before” and “after” a change.

Step 39

Save a session

Do

Go to Sessions, type a name (e.g., after the indexes), and click Save session.

See

The session appears in the list, with its indicators and the date.

Step 40

Compare

Do

In the list, select two entries — for example the saved session and the Current window (which is always at the top).

See

A Comparison table appears with a color-coded Δ column — green when it improved (fewer COLLSCANs, less time), red when it got worse.

Step 41

Export the report

Do

Click Export report.

See

It downloads a .json file with health, recommendations, query shapes, and the slowest operations — to attach to a ticket or keep on file.

Stage 11

Control and safety features

Step 42

Safe timed capture

Concept

Why it exists. Leaving level 2 on and forgetting about it is dangerous in production. The “capture” turns level 2 on, runs a countdown, and turns itself off at the end.

Do

In the control strip, click ⏱ Capture and choose 30s. During those 30s, run any trigger — for example Trigger A:

js·3 linhas
use profiler_lab;
db.orders.find({ status: 'shipped' }).toArray().length;
db.orders.find({ region: 'south' }).sort({ total: -1 }).toArray().length;
See

Profiling goes to level 2 and a pill with the countdown appears. When it reaches zero, the level goes back on its own to what it was before, with the message “Capture complete”. (You can also click Cancel to end it earlier.)

Step 43

Profiling filter

Do

Click Filter, fill Namespace with orders, and click Apply filter. Then run Trigger A:

js·3 linhas
use profiler_lab;
db.orders.find({ status: 'shipped' }).toArray().length;
db.orders.find({ region: 'south' }).sort({ total: -1 }).toArray().length;
Do

Then click Filter → Clear filter.

See

With the filter active, only operations on orders are recorded (and the button shows “Filter active”). When you clear it, it goes back to recording everything.

Step 44

Manage the system.profile collection

Concept

Capped collection. The profiler's logbook has a fixed size; when it fills up, it deletes the oldest entries. The default (1 MB) fills up fast.

Do

Watch the system.profile bar in the control strip (it shows used / total). Click Resize, choose 10 MB, and confirm.

See

The bar now reflects ~/10 MB. The modal warns that the current history is erased on resize.

Step 45

Adjust slowms and the sampling rate

Do

Change slowms to 50 and click Apply. Then click Slow ops and run Trigger A:

js·3 linhas
use profiler_lab;
db.orders.find({ status: 'shipped' }).toArray().length;
db.orders.find({ region: 'south' }).sort({ total: -1 }).toArray().length;
See

At the “Slow ops” level, only operations slower than the defined slowms enter the feed — the fast ones are ignored.

Stage 12

Finishing touches

Step 46

Other ways to open it

Do

Test the 3 entry points from Step 2 that you haven't used yet.

See

They all open the Profiler tab. If one is already open, it focuses the existing one instead of duplicating it.

Step 47

Languages

Do

In Settings → Language, switch the language (there are 5). Go back to the Profiler.

See

The entire Profiler screen appears translated — with no “raw” texts like profiler.xyz.

Step 48

Themes

Do

Toggle the theme between Light, Dark, and Neon.

See

Colors, cards, and charts adapt; no invisible text.

Cleanup (when you're done)

Do

Run in the shell:

js·3 linhas
use profiler_lab;
db.setProfilingLevel(0);
db.dropDatabase();
See

Profiling is turned off and the lab database is gone.

Summary of what you validated

StageFeature
2–3Open the Profiler (3 entry points) + choose database
3Actually turn profiling on (Off / Slow / All)
4–5Live Feed: real time, pause, presets, filters, search
6Dashboard: KPIs, timeline, donut, latency, treemap, query shapes
7Drill-down: details, live explain(), command, raw
8–9Index Advisor: recommendations, create index, prove the improvement
10Sessions: save, compare, export report
11Timed capture, filter, resize, slowms
12Alternative entry points, 5 languages, 3 themes
If every step gave the expected “See”, the Profiler screen is 100% validated. Note down the step number of any discrepancy so we can fix it.