PHPackages                             magepsycho/magento2-profiler - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. magepsycho/magento2-profiler

ActiveMagento2-module

magepsycho/magento2-profiler
============================

Tabular profiler output type for API &amp; CLI request profiling

1.0.0(today)32↑2900%1OSL-3.0PHP

Since Aug 8Pushed todayCompare

[ Source](https://github.com/MagePsycho/magento2-profiler)[ Packagist](https://packagist.org/packages/magepsycho/magento2-profiler)[ RSS](/packages/magepsycho-magento2-profiler/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (2)Used By (1)

Magento 2 Enhanced Profiler
===========================

[](#magento-2-enhanced-profiler)

[![Magento 2 Enhanced Profiler](https://camo.githubusercontent.com/21d85452cbb9037cc0b473fb795e3f117158b344da13996fc3f294103b63db2b/68747470733a2f2f692e696d6775722e636f6d2f643851454852622e706e67)](https://camo.githubusercontent.com/21d85452cbb9037cc0b473fb795e3f117158b344da13996fc3f294103b63db2b/68747470733a2f2f692e696d6775722e636f6d2f643851454852622e706e67)

[![Packagist Version](https://camo.githubusercontent.com/b3af70b2720aad19df0432710e1fc9935e98bb79f19b27303b5547aa9c90a06a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f7461672f4d61676550737963686f2f6d6167656e746f322d70726f66696c65723f6c6f676f3d7061636b616769737426736f72743d73656d766572266c6162656c3d7061636b6167697374267374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/magepsycho/magento2-profiler)[![Packagist Downloads](https://camo.githubusercontent.com/81d8f11983bbeca4c6e06477c7f9c6ea10412d924e0d1adfdf6174a3ad3eb470/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d61676570737963686f2f6d6167656e746f322d70726f66696c65722e7376673f6c6f676f3d7061636b6167697374267374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/magepsycho/magento2-profiler/stats)[![Supported Magento Versions](https://camo.githubusercontent.com/a504a0adb323bd8dfa1ee1ca6d8299fcf2a52d50bb943fc5fb087413b877e124/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6d6167656e746f2d253230322e342d627269676874677265656e2e7376673f6c6f676f3d6d6167656e746f266c6f6e6743616368653d74727565267374796c653d666f722d7468652d6261646765)](https://camo.githubusercontent.com/a504a0adb323bd8dfa1ee1ca6d8299fcf2a52d50bb943fc5fb087413b877e124/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6d6167656e746f2d253230322e342d627269676874677265656e2e7376673f6c6f676f3d6d6167656e746f266c6f6e6743616368653d74727565267374796c653d666f722d7468652d6261646765)[![License](https://camo.githubusercontent.com/7f4d9e0919247af0bd367bf637b93966120c8f9d01c5b1662316bd4e9d219358/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4f534c2d2d332e302d677265656e3f636f6c6f723d253233323334267374796c653d666f722d7468652d6261646765)](https://camo.githubusercontent.com/7f4d9e0919247af0bd367bf637b93966120c8f9d01c5b1662316bd4e9d219358/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4f534c2d2d332e302d677265656e3f636f6c6f723d253233323334267374796c653d666f722d7468652d6261646765)

Overview
--------

[](#overview)

[Magento 2 Enhanced Profiler](https://www.magepsycho.com/magento2-profiler.html) adds a **`tabular`** and a **`json`** profiler output type to Magento 2 — a third and fourth option next to the built-in `html` and `csvfile`.

It profiles **all three request types from one switch**: storefront and admin **web** requests, **REST and GraphQL API** requests, and **CLI** commands. The last two stock Magento cannot profile at all — `html` writes into the response body, which is useless for JSON endpoints and impossible for a console command. On web requests this writes to a log file instead of appending a table to the page.

No core file is patched: activation happens in `bootstrap.php`, before the ObjectManager exists, which is the only moment early enough to catch the whole request.

```
[2026-08-04 02:07:35] pid=68 sapi=fpm-fcgi GET /rest/V1/directory/currency
Timers: 19 | Calls: 21 | Root time: 73.567 ms | Peak real: 11.96 MB | Peak emalloc: 10.66 MB
+-------------------------------------------------------+-----+-----------+----------+--------------+--------------+------+
| Timer Id                                              | Cnt | Time (ms) | Avg (ms) | Emalloc (KB) | RealMem (KB) | %    |
+-------------------------------------------------------+-----+-----------+----------+--------------+--------------+------+
| cache_frontend_create                                 | 2   | 3.772     | 1.886    | 20.43        | 0.00         | 5.1  |
| magento                                               | 1   | 69.795    | 69.795   | 4277.05      | 2048.00      | 94.9 |
| |- store.resolve                                      | 1   | 10.267    | 10.267   | 73.98        | 0.00         | 14.0 |
| |- locale/currency                                    | 2   | 2.638     | 1.319    | 22.00        | 0.00         | 3.6  |
| |  |- EVENT:currency_display_options_forming          | 1   | 1.100     | 1.100    | 19.13        | 0.00         | 1.5  |
| |  |  |- OBSERVER:magento_currencysymbol_currency...  | 1   | 1.021     | 1.021    | 9.77         | 0.00         | 1.4  |
| |- EVENT:controller_front_send_response_before        | 1   | 3.941     | 3.941    | 23.90        | 0.00         | 5.4  |
+-------------------------------------------------------+-----+-----------+----------+--------------+--------------+------+

```

Demo
----

[](#demo)

`tabular` output on a CLI command:

[![Tabular profiler output on a CLI command](./docs/tabular-demo-cli.png)](./docs/tabular-demo-cli.png)

Key Features
------------

[](#key-features)

- Profiles **CLI commands** and **REST / GraphQL API** requests — neither of which stock Magento can profile at all
- Two output types that can run together: `tabular` (ASCII log) and `json` / `timeline` (structured per-run files)
- Captures aggregate rows **and** per-call spans, so a timeline is available without deciding before the run
- **SQL query profiling** on by default, with a per-table breakdown of every query
- Times DB, search, HTTP clients, GraphQL resolvers, Web API, indexers, mview, session handler, cache frontend and console commands
- Thresholds default to **zero** — core's `html` output hides everything under 1ms / 10 calls / 10KB, which drops most of an API request
- Filter noise by minimum duration or by PCRE on the timer id
- Log output is confined to `var/log/` and forced to a `.log` extension, so a report can never land somewhere web-served or executable
- Cookie activation is gated behind developer mode or a shared secret
- `Benchmark` helper for instrumenting your own code in a few lines
- Companion [**MagePsycho\_ProfilerUi**](../ProfilerUi/README.md) renders the reports in the admin

Feature Highlights
------------------

[](#feature-highlights)

### What Stock Magento Cannot Do

[](#what-stock-magento-cannot-do)

Stock profilerThis extension`html` appends a table to the response body — unusable for JSON endpointsWrites to a log file or STDERR, never to the responseCLI commands cannot be profiled`MAGE_PROFILER=tabular bin/magento ` prints the table after the runREST / GraphQL cannot be profiledSame switch, same table, per requestThresholds hide anything under 1ms / 10 calls / 10KBThresholds default to zero; opt into filtering when you want itNo SQL visibilityEvery query timed, grouped by operation and tableNo structured outputOne JSON file per run, with per-call spans### Output Types

[](#output-types)

Run either, or both together as `MAGE_PROFILER=tabular,json`:

TypeWritesUse`tabular`ASCII table appended to `var/log/profiler_tabular.log`Reading in a terminal; STDERR on CLI`json` (= `timeline`)one structured file per run in `var/log/profiler/`The [admin viewer](../ProfilerUi/README.md), CI diffing, tooling`json` and `timeline` are two names for the same capture — aggregate `rows` **and** per-call `spans`. Set `MAGE_PROFILER_MAX_SPANS=0` for an aggregate-only file.

### Turning It On

[](#turning-it-on)

Three ways, in order of scope:

```
# 1. one CLI command (Docker: -e goes before the container name)
MAGE_PROFILER=tabular bin/magento indexer:reindex catalog_product_price

# 2. one browser session or API client — cookie
#    MAGE_PROFILER=tabular   (developer mode, or tabular: otherwise)

# 3. everything, until switched off — flag file at var/profiler.flag
bin/magento magepsycho:profiler:enable
bin/magento magepsycho:profiler:status
bin/magento magepsycho:profiler:disable
```

For **REST / GraphQL requests from an API client** such as Postman, send the cookie as a plain request header:

```
Cookie: MAGE_PROFILER=tabular
```

[![Setting the MAGE_PROFILER cookie header in Postman](./docs/postman-cookie-setting.png)](./docs/postman-cookie-setting.png)

The cookie is honoured only in **developer mode**. Anywhere else it must carry the shared secret — set `MAGE_PROFILER_SECRET` in the PHP environment and append it after the last output type:

```
Cookie: MAGE_PROFILER=tabular:
Cookie: MAGE_PROFILER=tabular,json:
```

Store configuration cannot switch profiling on: activation happens during bootstrap, long before store config is readable. The admin settings control the **output** only.

### SQL Query Profiling

[](#sql-query-profiling)

Every query is timed and grouped, so a slow reindex shows which tables it is spending its time in rather than one opaque total.

```
# which tables dominate a reindex?
MAGE_PROFILER=tabular MAGE_PROFILER_FILTER='/^SQL/' bin/magento indexer:reindex

# operation mix only, no per-table breakdown
MAGE_PROFILER=tabular MAGE_PROFILER_SQL=operation bin/magento indexer:reindex

# off, without touching the rest of the profiler
MAGE_PROFILER=tabular MAGE_PROFILER_SQL=0 bin/magento indexer:reindex
```

### Timeline And The Admin Viewer

[](#timeline-and-the-admin-viewer)

The `json` output writes one file per run into `var/log/profiler/`, indexed by `index.jsonl` so a run picker can be built without opening every report.

Install the companion [**MagePsycho\_ProfilerUi**](../ProfilerUi/README.md) for an admin page at *System → Tools → Enhanced Profiler Reports*: a collapsible tree, a sortable and filterable table with the Self column heat-shaded, and a timeline of every call. It only reads what this module writes and adds nothing to the recording side, so it can be left uninstalled in production.

The same run, read in the browser instead of the log — this is what you get once `MagePsycho_ProfilerUi` is installed:

[![The admin viewer added by MagePsycho_ProfilerUi — collapsible tree with the Self column heat-shaded](./docs/enhanced-profiler-tree-view.png)](./docs/enhanced-profiler-tree-view.png)

```
composer require magepsycho/magento2-profiler-ui

```

### Instrument Your Own Code

[](#instrument-your-own-code)

```
use MagePsycho\Profiler\Util\Benchmark;

Benchmark::start('my.expensive.thing');
// ...
Benchmark::stop('my.expensive.thing');
```

Timers nest automatically and appear in both outputs alongside the framework's own.

🛠️ Installation
---------------

[](#️-installation)

### 1 Using Composer (Preferred)

[](#1-using-composer-preferred)

```
composer require magepsycho/magento2-profiler

```

### 2 Using Modman

[](#2-using-modman)

```
modman init
modman clone git@github.com:MagePsycho/magento2-profiler.git

```

### 3 Using Zip File

[](#3-using-zip-file)

- Download the [Extension Zip File](https://github.com/MagePsycho/magento2-profiler/archive/master.zip)
- Extract &amp; upload the files to `/path/to/magento2/app/code/MagePsycho/Profiler/`

After installation by either means, activate the extension with following steps

1. Enable the module

```
php bin/magento module:enable MagePsycho_Profiler --clear-static-content
php bin/magento setup:upgrade

```

2. Flush the store cache

```
php bin/magento cache:flush

```

3. Deploy static content - *in Production mode only*

```
rm -rf pub/static/* var/view_preprocessed/*
php bin/magento setup:static-content:deploy

```

4. Profile something

```
MAGE_PROFILER=tabular php bin/magento cache:clean
tail -f var/log/profiler_tabular.log

```

The extension creates no tables of its own.

Configuration
-------------

[](#configuration)

**Stores &gt; Configuration &gt; MagePsycho &gt; Enhanced Profiler &gt; General Settings**

These control the **output** only — they cannot switch profiling on. Environment variables win over admin config.

SettingEnv overrideDefaultWrite Output—YesLog File Path (relative to Magento root)`MAGE_PROFILER_LOG``var/log/profiler_tabular.log`Minimum Timer Duration (ms)`MAGE_PROFILER_MIN_MS``0` — show everythingTimer Id Filter (PCRE)`MAGE_PROFILER_FILTER`nonePrint To STDERR On CLI`MAGE_PROFILER_CLI_STDERR`YesInstrumentation itself is environment-only: `MAGE_PROFILER_SQL`, `MAGE_PROFILER_MAX_DETAIL`, `MAGE_PROFILER_MAX_IDS`, `MAGE_PROFILER_MAX_SPANS`, `MAGE_PROFILER_REPORT_DIR`, `MAGE_PROFILER_KEEP_DAYS`, `MAGE_PROFILER_KEEP_QUERY`.

Security
--------

[](#security)

Cookie activation lets an unauthenticated visitor make the server write to disk and expose internal timing. It is therefore honoured **only** when:

- `MAGE_MODE` is `developer`, **or**
- the cookie carries the shared secret — `MAGE_PROFILER=tabular:` matching the `MAGE_PROFILER_SECRET` environment variable (compared with `hash_equals`)

Otherwise the cookie is ignored outright. `MAGE_PROFILER` env-var and `var/profiler.flag` activation are ungated — both already require server-side access.

The report path is **always confined to `var/log/`** and always written with a `.log` extension: traversal segments are dropped and anything outside is folded back in, so a mistyped or hostile path cannot put the report somewhere web-served or executable. Request query strings are stripped from the report label by default, since API calls routinely carry tokens in them (`MAGE_PROFILER_KEEP_QUERY=1` to keep them).

*Production checklist: leave `MAGE_PROFILER_SECRET` unset unless actively profiling, never leave `var/profiler.flag` behind, and rotate `var/log/profiler_tabular.log` — it appends forever and has no rotation of its own. `bin/magento magepsycho:profiler:status` prints the current gate state.*

Developer Notes
---------------

[](#developer-notes)

### Activation runs before the ObjectManager

[](#activation-runs-before-the-objectmanager)

`bootstrap.php` is included by Composer's `files` autoload, which is why it can arm the profiler before Magento starts. That file therefore cannot use DI, the request abstractions or the store config — superglobals and filesystem functions are the only option, and the sniff exclusions in it are deliberate.

### What gets instrumented

[](#what-gets-instrumented)

Plugins wrap `Magento\Framework\DB\Adapter\Pdo\Mysql`, `Magento\Framework\Search\AdapterInterface`, `Magento\Framework\HTTP\Client\Curl`, `Magento\Framework\HTTP\AsyncClientInterface`, the GraphQL query processor and resolvers, the Web API request and output processors, `Magento\Indexer\Model\Indexer`, `Magento\Framework\Mview\ActionInterface`, `Magento\Framework\Session\SaveHandler`, `Magento\Framework\App\Cache\Frontend\Factory` and `Symfony\Component\Console\Command\Command`.

### Static analysis

[](#static-analysis)

```
vendor/bin/phpstan analyse -c app/code/MagePsycho/Profiler/phpstan.neon --memory-limit=1G
vendor/bin/phpcs --standard=Magento2 --extensions=php,phtml app/code/MagePsycho/Profiler/
```

Unit tests live in `Test/Unit` and cover the tabular renderer, the timer id builder, the SQL plugin and the benchmark helper.

Changelog
---------

[](#changelog)

**Version 1.0.0 (2026-08-08)**

- Initial Release.

Authors
-------

[](#authors)

- Raj KB [![Twitter Follow](https://camo.githubusercontent.com/1264ebcaa4f5a0968a5dc17aae246f1ae578e0e75bb9660cf06d3131596ca1fe/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f72616a6b626e702e7376673f7374796c653d736f6369616c)](https://twitter.com/rajkbnp)

Contributors
------------

[](#contributors)

[![Contributors](https://camo.githubusercontent.com/b175d5804c0e41e10a7c93127d6352cc41280087c4efd4ec27af15649436943b/68747470733a2f2f636f6e747269622e726f636b732f696d6167653f7265706f3d6d61676570737963686f2f6d6167656e746f322d70726f66696c6572)](https://camo.githubusercontent.com/b175d5804c0e41e10a7c93127d6352cc41280087c4efd4ec27af15649436943b/68747470733a2f2f636f6e747269622e726f636b732f696d6167653f7265706f3d6d61676570737963686f2f6d6167656e746f322d70726f66696c6572)

To Contribute
-------------

[](#to-contribute)

Any contribution to the development of `Magento 2 Enhanced Profiler` is highly welcome.
The best possibility to provide any code is to open a [pull request on GitHub](https://github.com/MagePsycho/magento2-profiler/pulls).

Need Support?
-------------

[](#need-support)

If you encounter any problems or bugs, please create an issue on [GitHub](https://github.com/MagePsycho/magento2-profiler/issues).

Please [visit our store](https://www.magepsycho.com/extensions/magento-2.html) for more FREE / paid extensions OR [contact us](https://magepsycho.com/contact) for customization / development services.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance100

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity33

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/47c847a6fe8bcd713aace9722ded18e2be56ffffde75e1a876957128714563e5?d=identicon)[MagePsycho](/maintainers/MagePsycho)

---

Top Contributors

[![MagePsycho](https://avatars.githubusercontent.com/u/1205071?v=4)](https://github.com/MagePsycho "MagePsycho (2 commits)")

### Embed Badge

![Health badge](/badges/magepsycho-magento2-profiler/health.svg)

```
[![Health](https://phpackages.com/badges/magepsycho-magento2-profiler/health.svg)](https://phpackages.com/packages/magepsycho-magento2-profiler)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
