PHPackages                             konradmichalik/typo3-request-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. [Debugging &amp; Profiling](/categories/debugging)
4. /
5. konradmichalik/typo3-request-profiler

ActiveTypo3-cms-extension[Debugging &amp; Profiling](/categories/debugging)

konradmichalik/typo3-request-profiler
=====================================

Dev-only TYPO3 frontend request profiler that records SQL queries, N+1 patterns, cache state and timing as compact JSON profiles for AI coding assistants.

0.4.0(3w ago)23.4k↑3000%[1 issues](https://github.com/konradmichalik/typo3-request-profiler/issues)1GPL-2.0-or-laterPHPPHP ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0CI passing

Since Jun 17Pushed 3w agoCompare

[ Source](https://github.com/konradmichalik/typo3-request-profiler)[ Packagist](https://packagist.org/packages/konradmichalik/typo3-request-profiler)[ RSS](/packages/konradmichalik-typo3-request-profiler/feed)WikiDiscussions main Synced 2w ago

READMEChangelog (4)Dependencies (15)Versions (15)Used By (1)

[![Extension icon](Resources/Public/Icons/Extension.png)](Resources/Public/Icons/Extension.png)

TYPO3 extension `typo3_request_profiler`
========================================

[](#typo3-extension-typo3_request_profiler)

[![Packagist](https://camo.githubusercontent.com/b8301cf0a71c4631228617100d4c82400f042cf40b1ec0f2c878051989e89685/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6b6f6e7261646d696368616c696b2f7479706f332d726571756573742d70726f66696c65723f6c6162656c3d76657273696f6e266c6f676f3d7061636b6167697374)](https://packagist.org/packages/konradmichalik/typo3-request-profiler)[![Packagist Downloads](https://camo.githubusercontent.com/b8e012900b3400585567e22fe6ea8f8279a651000d56d3e2dcbd1d70f6f3ae7c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6b6f6e7261646d696368616c696b2f7479706f332d726571756573742d70726f66696c65723f636f6c6f723d627269676874677265656e)](https://packagist.org/packages/konradmichalik/typo3-request-profiler)[![TYPO3](https://camo.githubusercontent.com/1b6c390eac52f128bcf2640be62fe0e7cbbd2e99fbd02ea8d393a0ee0d71de95/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5459504f332d31332e3425323025374325323031342e302d6f72616e67652e737667)](https://camo.githubusercontent.com/1b6c390eac52f128bcf2640be62fe0e7cbbd2e99fbd02ea8d393a0ee0d71de95/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5459504f332d31332e3425323025374325323031342e302d6f72616e67652e737667)[![Supported PHP Versions](https://camo.githubusercontent.com/48e8b1eb019445d75589840eacf47be5305520bcdbe7bdb20c85f71e3886ef1f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f6b6f6e7261646d696368616c696b2f7479706f332d726571756573742d70726f66696c65722f7068703f6c6f676f3d706870)](https://packagist.org/packages/konradmichalik/typo3-request-profiler)[![CGL](https://camo.githubusercontent.com/57be12ec4c910693eeda01514cdcbe865db183f4e81bd142c738cc50eee6f88b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6b6f6e7261646d696368616c696b2f7479706f332d726571756573742d70726f66696c65722f63676c2e796d6c3f6c6162656c3d63676c266c6f676f3d676974687562)](https://github.com/konradmichalik/typo3-request-profiler/actions/workflows/cgl.yml)[![Coverage](https://camo.githubusercontent.com/87632cf8e6ac286ea99f4600d3ea15bf5b6a9da042fb57cc8adde507972206fa/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c73436f7665726167652f6769746875622f6b6f6e7261646d696368616c696b2f7479706f332d726571756573742d70726f66696c65723f6c6f676f3d636f766572616c6c73)](https://coveralls.io/github/konradmichalik/typo3-request-profiler)[![Tests](https://camo.githubusercontent.com/b1533ac6e86b7ca9e7231d2e45f2851aa522391bf87bace55d34e3fa1dca8fdc/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6b6f6e7261646d696368616c696b2f7479706f332d726571756573742d70726f66696c65722f74657374732e796d6c3f6c6162656c3d7465737473266c6f676f3d676974687562)](https://github.com/konradmichalik/typo3-request-profiler/actions/workflows/tests.yml)[![License](https://camo.githubusercontent.com/26f8b6541ea045cc1dbc2267208158b5a7ebbf5cf437c4b486d80fee9386f77e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d47504c2d2d322e302d2d6f722d2d6c617465722d626c75652e737667)](LICENSE.md)

A *dev-only* TYPO3 frontend request profiler. It instruments live frontend requests and writes one compact JSON profile per request — SQL queries, N+1 patterns, cache state, and timing — to `var/log/profiles/{request_id}.json`.

Important

This extension is **active by default only in a Development context** (`Environment::getContext()->isDevelopment()`). Outside Development it stays off and collects no data unless explicitly opted in via `TYPO3_REQUEST_PROFILER_FORCE=1` (intended for staging, never real production — see [Configuration](#-configuration)).

The profiler is a thin, standalone collector with no external dependencies. It is inspired by the [Symfony Profiler](https://symfony.com/doc/current/profiler.html) — and by some of the metrics the [TYPO3 Admin Panel](https://docs.typo3.org/c/typo3/cms-adminpanel/main/en-us/) surfaces — but records them as compact, machine-readable JSON instead of an interactive panel.

**What it captures per request:**

- Wall-clock and SQL timing, peak memory usage, included PHP file count
- Full query count + top slow queries + N+1 duplicate detection
- Cache hit/miss state with disabled reasons
- Log activity per request (count by level + noisiest components)
- Optional call-site origin (`Class::method (file:line)`) for every flagged query

🔥 Installation
--------------

[](#-installation)

### Requirements

[](#requirements)

- TYPO3 13.4 LTS &amp; 14.0+
- PHP 8.2+
- Doctrine DBAL 3.x or 4.x

### Composer

[](#composer)

[![Packagist](https://camo.githubusercontent.com/b8301cf0a71c4631228617100d4c82400f042cf40b1ec0f2c878051989e89685/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6b6f6e7261646d696368616c696b2f7479706f332d726571756573742d70726f66696c65723f6c6162656c3d76657273696f6e266c6f676f3d7061636b6167697374)](https://packagist.org/packages/konradmichalik/typo3-request-profiler)[![Packagist Downloads](https://camo.githubusercontent.com/b8e012900b3400585567e22fe6ea8f8279a651000d56d3e2dcbd1d70f6f3ae7c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6b6f6e7261646d696368616c696b2f7479706f332d726571756573742d70726f66696c65723f636f6c6f723d627269676874677265656e)](https://packagist.org/packages/konradmichalik/typo3-request-profiler)

```
composer require --dev konradmichalik/typo3-request-profiler
```

### TER

[](#ter)

[![TER version](https://camo.githubusercontent.com/83568e355b439160af6bc63cd63a7113669f5ae1256b355544fba138e2c77143/68747470733a2f2f7479706f332d6261646765732e6465762f62616467652f7479706f335f726571756573745f70726f66696c65722f76657273696f6e2f736869656c64732e737667)](https://extensions.typo3.org/extension/typo3_request_profiler)[![TER downloads](https://camo.githubusercontent.com/182ad40fceb0c9cce409836d964d9556203c68691b09f76c02d09f41e6eff5bb/68747470733a2f2f7479706f332d6261646765732e6465762f62616467652f7479706f335f726571756573745f70726f66696c65722f646f776e6c6f6164732f736869656c64732e737667)](https://extensions.typo3.org/extension/typo3_request_profiler)

Download the zip file from [TYPO3 extension repository (TER)](https://extensions.typo3.org/extension/typo3_request_profiler).

⚙️ Configuration
----------------

[](#️-configuration)

The profiler is controlled entirely via environment variables:

VariableDefaultEffect`TYPO3_REQUEST_PROFILER`(on)Set to `0` to disable profiling for a request/process.`TYPO3_REQUEST_PROFILER_FORCE`(off)Set to `1` to enable profiling outside the Development context (e.g. staging). Must be set deliberately, never in real production.`TYPO3_REQUEST_PROFILER_MIN_MS``0`Only persist requests whose total time exceeds this threshold (ms).`TYPO3_REQUEST_PROFILER_KEEP``50`Number of most-recent profiles to retain; older files are pruned automatically.`TYPO3_REQUEST_PROFILER_TRACE`(off)Set to `1` to capture the calling `Class::method (file:line)` for each query (added as `origin` to `slow_queries`/`duplicate_queries`).`TYPO3_REQUEST_PROFILER_EVENTS`(off)Set to `1` to time dispatched PSR-14 events and add an `events` section (count + the most expensive event classes).Note

`TYPO3_REQUEST_PROFILER_FORCE` is a deployment-level switch evaluated in `ext_localconf.php` and therefore **cached** — it is not a live toggle. Changing it requires a cache flush to take effect. This is in contrast to the per-request `TYPO3_REQUEST_PROFILER=0`, which short-circuits the middleware on each request and needs no cache flush.

Tip

`TYPO3_REQUEST_PROFILER_TRACE=1` uses `debug_backtrace` per query and is therefore opt-in for performance. No bound parameter values are ever captured — only the call site.

Tip

`TYPO3_REQUEST_PROFILER_EVENTS=1` wraps the core PSR-14 dispatcher and measures every dispatched event. Dispatch happens very frequently, so the per-event timing is opt-in. When off, events are dispatched without any measurement and the `events` section is omitted. Event timing follows the same activation gate as the rest of the profiler, so it also works on staging together with `TYPO3_REQUEST_PROFILER_FORCE=1`.

💡 Profile Format
----------------

[](#-profile-format)

Each request produces one JSON file at `var/log/profiles/{request_id}.json`:

```
{
  "schemaVersion": 1,
  "token": "",
  "time": "2026-06-15T10:00:00+00:00",
  "method": "GET",
  "url": "https://example.ddev.site/",
  "status": 200,
  "page": { "id": 1, "type": 0 },
  "cache": { "hit": false, "cacheable": false, "disabled_reasons": ["&no_cache=1 query parameter was given"] },
  "timing": { "total_ms": 142.5 },
  "memory": { "peak_mb": 16.1 },
  "php": { "included_files": 432 },
  "queries": { "count": 101, "total_ms": 38.2 },
  "slow_queries": [
    { "sql": "SELECT * FROM pages WHERE slug = ? ORDER BY slug desc", "ms": 12.4 }
  ],
  "duplicate_queries": [
    { "sql": "SELECT COUNT(*) FROM tt_content WHERE pid = ? AND deleted = ?", "count": 100, "total_ms": 31.4 }
  ],
  "log": {
    "count": 3,
    "by_level": { "warning": 2, "notice": 1 },
    "top_components": [
      { "component": "TYPO3.CMS.Core.Authentication.BackendUserAuthentication", "count": 2 }
    ]
  },
  "events": {
    "count": 142,
    "total_ms": 12.3,
    "top": [
      { "event": "TYPO3\\CMS\\Core\\Cache\\Event\\CacheFlushEvent", "count": 100, "total_ms": 8.1 }
    ]
  }
}
```

Note

The `log` section only appears when the request produced log entries. Only the level and component are recorded — never the message body — so no user data leaks into the profile.

Note

The `events` section only appears when `TYPO3_REQUEST_PROFILER_EVENTS=1`.

### Profile schema

[](#profile-schema)

The artifact carries an explicit, versioned schema contract via the top-level `schemaVersion` field. It is written first so it is immediately visible in every file.

**Top-level fields** (always present):

FieldTypeDescription`schemaVersion`intSchema contract version of the artifact (currently `1`).`token`stringRequest identifier; also the file name.`time`stringRequest time as ISO 8601 (`date('c')`).`method`stringHTTP request method.`url`stringRequest URI with masked query values (`?q=?&page=?`) — parameter names are kept, values are never persisted (they regularly carry search terms, e-mail addresses or one-time tokens).`status`intHTTP response status code.**Section keys** (key = `Section::name()`; each appears only when the section is enabled and produced data):

KeyShape`page``{ id, type }``cache``{ hit, cacheable, disabled_reasons[] }``timing``{ total_ms }``memory``{ peak_mb }``php``{ included_files }``queries``{ count, total_ms }``slow_queries``[{ sql, ms, origin? }]``duplicate_queries``[{ sql, count, total_ms, origin? }]``log``{ count, by_level{}, top_components[{ component, count }] }``events``{ count, total_ms, top[{ event, count, total_ms }] }`Note

`schemaVersion` is incremented only when field names or shapes change in a breaking way. Additive changes keep the same version.

### Reading profiles

[](#reading-profiles)

`KonradMichalik\Typo3RequestProfiler\Profiling\ProfileReader` is the supported, framework-agnostic read API for these artifacts — external consumers should use it instead of re-implementing the `glob`/sort/`json_decode` logic:

MethodReturns`all()`All profiles, newest first.`latest(int $limit = 10)`The `$limit` newest profiles, newest first.`byToken(string $token)`A single profile by its token, or `null` if unknown.The reader is directory-based and carries no framework dependency — its constructor takes the profiles directory (`new ProfileReader($directory)`). On the TYPO3 side, that directory is `ProfileWriter::defaultDirectory()` (the same source the writer persists to). Its public signature is kept stable as a contract for consumers.

🧑‍💻 Contributing
----------------

[](#‍-contributing)

Please have a look at [`CONTRIBUTING.md`](CONTRIBUTING.md).

⭐ License
---------

[](#-license)

This project is licensed under [GNU General Public License 2.0 (or later)](LICENSE.md).

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance85

Actively maintained with recent releases

Popularity27

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 93.6% 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

Every ~6 days

Total

4

Last Release

23d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/11557705846f24da32a0e6e75c460db505c1b847f081ddaa3d27f3ea27f4097b?d=identicon)[konradmichalik](/maintainers/konradmichalik)

---

Top Contributors

[![konradmichalik](https://avatars.githubusercontent.com/u/4558190?v=4)](https://github.com/konradmichalik "konradmichalik (73 commits)")[![renovate[bot]](https://avatars.githubusercontent.com/in/2740?v=4)](https://github.com/renovate[bot] "renovate[bot] (5 commits)")

---

Tags

typo3typo3-cms-extension

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/konradmichalik-typo3-request-profiler/health.svg)

```
[![Health](https://phpackages.com/badges/konradmichalik-typo3-request-profiler/health.svg)](https://phpackages.com/packages/konradmichalik-typo3-request-profiler)
```

###  Alternatives

[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)[symfony/symfony

The Symfony PHP framework

31.4k87.2M2.2k](/packages/symfony-symfony)[eliashaeussler/typo3-warming

Warming - Warms up Frontend caches based on an XML sitemap. Cache warmup can be triggered via TYPO3 backend or using a console command. Supports multiple languages and custom crawler implementations.

22260.2k](/packages/eliashaeussler-typo3-warming)[eliashaeussler/typo3-form-consent

Extension for TYPO3 CMS that adds double opt-in functionality to EXT:form

15100.9k](/packages/eliashaeussler-typo3-form-consent)[typo3/cms-core

TYPO3 CMS Core

3713.2M5.3k](/packages/typo3-cms-core)[pagemachine/searchable

TYPO3 extension to index and search content with Elasticsearch

1139.9k](/packages/pagemachine-searchable)

PHPackages © 2026

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