run_as_root / magento2-prometheus-exporter

run_as_root/magento2-prometheus-exporter

Magento2 Prometheus Exporter

  • David Lambauer
  • Matthias Walter
magento2-module Compatibility: 2.4.7-2.4.8 Code Quality: Fail Tests: Pass Security: Pass MIT

Magento 2 Prometheus Exporter

pipeline status

A comprehensive Magento 2 module that exposes essential Magento metrics in Prometheus format, enabling powerful monitoring and observability for your e-commerce platform.

🚀 Features

  • 📊 Rich Metrics Collection: Monitors orders, products, customers, CMS content, cron jobs, indexers, and more
  • 🔧 Configurable Metrics: Enable/disable specific metrics through Magento admin interface
  • 🔐 Secure Access: Bearer token authentication support to protect your metrics endpoint
  • ⚡ Performance Optimized: Efficient cron-based data aggregation to minimize performance impact
  • 🎯 Prometheus Ready: Native Prometheus format output for seamless integration
  • 🔌 Extensible Architecture: Easy to add custom metrics with clean interfaces

📋 Table of Contents

📦 Installation

Requirements

  • Magento 2.3.x or higher
  • PHP 8.2 or higher
  • Composer

Install via Composer

composer require run-as-root/magento2-prometheus-exporter
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento cache:flush

Verify Installation

After installation, your metrics endpoint will be available at:

https://your-magento-store.com/metrics

⚙️ Configuration

Admin Configuration

Navigate to Stores → Configuration → Prometheus → Metric Configuration to:

  • Enable/disable specific metric collectors
  • Configure authentication settings
  • Set collection intervals
  • Manage metric labels and groupings

Cron Configuration

The module automatically registers a cron job that runs every minute to aggregate metrics. The job uses a dedicated cron group: run_as_root_prometheus_metrics_aggregator.

🎯 Prometheus Setup

Basic Configuration

Add the following scrape configuration to your prometheus.yml:

scrape_configs:
  - job_name: 'magento-2'
    scrape_interval: 5m
    scrape_timeout: 60s
    metrics_path: /metrics
    static_configs:
      - targets: 
          - 'your-magento-store.com'

With Authentication

For production environments, secure your metrics endpoint:

scrape_configs:
  - job_name: 'magento-2'
    scrape_interval: 5m
    scrape_timeout: 60s
    metrics_path: /metrics
    authorization:
      type: 'Bearer'
      credentials: 'your-bearer-token-here'
    static_configs:
      - targets: 
          - 'your-magento-store.com'

Advanced Configuration with Labels

scrape_configs:
  - job_name: 'magento-2'
    scrape_interval: 5m
    scrape_timeout: 60s
    metrics_path: /metrics
    authorization:
      type: 'Bearer'
      credentials: 'your-bearer-token-here'
    static_configs:
      - targets: 
          - 'your-magento-store.com'
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        replacement: 'magento-production'

📊 Available Metrics

Order Metrics

Metric Type Labels Description
magento_orders_count_total gauge status, store_code Total count of orders by status and store
magento_orders_amount_total gauge status, store_code Total revenue by order status and store
magento_order_items_count_total gauge status, store_code Total count of order items

Product & Catalog Metrics

Metric Type Labels Description
magento_products_by_type_count_total gauge product_type Count of products by type (simple, configurable, etc.)
magento_catalog_category_count_total gauge status, menu_status, store_code Count of categories by status
magento_complex_product_variations_above_recommended_level gauge - Count of configurable products with more than 50 variations (performance risk)
magento_products_with_bad_reviews_count_total gauge store_code Count of products whose rating_summary is below 60 (≈ 3 of 5 stars)

EAV & Attribute Metrics

Metric Type Labels Description
magento_eav_attribute_count_total gauge - Total count of EAV attributes
magento_eav_attribute_options_above_recommended_level_total gauge - Count of attributes with more than 100 options (performance risk)

Customer Metrics

Metric Type Labels Description
magento_customer_count_total gauge store_code Total count of registered customers

Content Metrics

Metric Type Labels Description
magento_cms_block_count_total gauge store_code Count of CMS blocks
magento_cms_page_count_total gauge store_code Count of CMS pages

System Health Metrics

Metric Type Labels Description
magento_cronjob_count_total gauge status, job_code Count of cron jobs by status
magento_cronjob_broken_count_total gauge - Count of broken cron jobs
magento_indexer_backlog_count_total gauge title Count of items in indexer backlog
magento_cache_flush_count_total counter - Cumulative count of bin/magento cache:flush / admin flush-storage invocations

Infrastructure Metrics

Metric Type Labels Description
magento_store_count_total gauge status Count of stores by status
magento_website_count_total gauge - Total count of websites
magento_shipments_count_total counter source, store_code Count of shipments created
magento_quotes_over_item_limit_count_total gauge store_code Count of active carts with more than 100 items (performance risk)

🔐 Security

Authentication Setup

  1. Generate Bearer Token: Navigate to Magento Admin → System → Integrations
  2. Create New Integration: Set up API access with appropriate permissions
  3. Configure Token: Use the generated access token in your Prometheus configuration

Best Practices

  • Always use HTTPS for metrics endpoints in production
  • Regularly rotate authentication tokens
  • Restrict access to metrics endpoint via firewall rules
  • Monitor access logs for unusual activity

IP Whitelisting

Consider restricting access to your Prometheus server IPs:

location /metrics {
    allow 10.0.0.0/8;     # Your Prometheus server
    allow 172.16.0.0/12;  # Internal network
    deny all;
    try_files $uri $uri/ /index.php?$args;
}

🔧 Custom Metrics

Creating a Custom Metric Aggregator

  1. Implement the Interface:
<?php
namespace YourNamespace\YourModule\Aggregator;

use RunAsRoot\PrometheusExporter\Api\MetricAggregatorInterface;
use RunAsRoot\PrometheusExporter\Service\UpdateMetricService;

class CustomMetricAggregator implements MetricAggregatorInterface
{
    private UpdateMetricService $updateMetricService;

    public function __construct(UpdateMetricService $updateMetricService)
    {
        $this->updateMetricService = $updateMetricService;
    }

    public function aggregate(): void
    {
        // Your metric collection logic here
        $value = $this->calculateCustomMetric();
        
        $this->updateMetricService->update(
            'your_custom_metric_total',
            (string) $value,
            'gauge',
            'Description of your custom metric',
            ['label1' => 'value1', 'label2' => 'value2']
        );
    }

    private function calculateCustomMetric(): int
    {
        // Implement your metric calculation
        return 42;
    }
}
  1. Register in DI Configuration (etc/di.xml):
<type name="RunAsRoot\PrometheusExporter\Metric\MetricAggregatorPool">
    <arguments>
        <argument name="items" xsi:type="array">
            <item name="YourCustomAggregator" xsi:type="object">YourNamespace\YourModule\Aggregator\CustomMetricAggregator</item>
        </argument>
    </arguments>
</type>

Example: Product Rating Aggregator

<?php
namespace YourNamespace\YourModule\Aggregator;

use Magento\Review\Model\ResourceModel\Review\CollectionFactory;
use RunAsRoot\PrometheusExporter\Api\MetricAggregatorInterface;
use RunAsRoot\PrometheusExporter\Service\UpdateMetricService;

class ProductRatingAggregator implements MetricAggregatorInterface
{
    private CollectionFactory $reviewCollectionFactory;
    private UpdateMetricService $updateMetricService;

    public function __construct(
        CollectionFactory $reviewCollectionFactory,
        UpdateMetricService $updateMetricService
    ) {
        $this->reviewCollectionFactory = $reviewCollectionFactory;
        $this->updateMetricService = $updateMetricService;
    }

    public function aggregate(): void
    {
        $collection = $this->reviewCollectionFactory->create()
            ->addStatusFilter(\Magento\Review\Model\Review::STATUS_APPROVED);

        $averageRating = $collection->getConnection()
            ->fetchOne('SELECT AVG(rating_value) FROM rating_option_vote');

        $this->updateMetricService->update(
            'magento_product_average_rating',
            (string) round($averageRating, 2),
            'gauge',
            'Average product rating across all approved reviews'
        );
    }
}

💻 CLI Commands

Collect Metrics Manually

php bin/magento run_as_root:metrics:collect

View Current Metrics

php bin/magento run_as_root:metrics:show

Clear Metrics Data

php bin/magento run_as_root:metrics:clear

🏗️ Architecture

Data Flow

  1. Cron Execution: Every minute, the run_as_root_prometheus_metrics_aggregator cron group executes
  2. Metric Aggregation: Each enabled aggregator collects and processes data
  3. Data Storage: Aggregated metrics are stored in run_as_root_prometheus_metrics table
  4. Endpoint Response: /metrics controller serves data in Prometheus format

Key Components

  • MetricAggregatorInterface: Contract for all metric collectors
  • MetricAggregatorPool: Registry of all available aggregators
  • UpdateMetricService: Service for storing metric data
  • PrometheusController: HTTP endpoint for serving metrics

Database Schema

The module creates a dedicated table run_as_root_prometheus_metrics with the following structure:

  • metric_id: Primary key
  • metric_code: Unique metric identifier
  • metric_value: Numeric value
  • metric_type: Type (gauge, counter, histogram)
  • metric_help: Description text
  • metric_labels: JSON-encoded labels
  • updated_at: Last update timestamp

🔍 Troubleshooting

Common Issues

Metrics Not Updating

# Check cron status
php bin/magento cron:status

# Run metrics collection manually
php bin/magento run_as_root:metrics:collect

# Check system logs
tail -f var/log/system.log | grep prometheus

Permission Denied on /metrics

  • Verify web server has read access to Magento files
  • Check Magento file permissions: find . -type f -exec chmod 644 {} \;
  • Ensure proper ownership: chown -R www-data:www-data .

High Memory Usage

  • Reduce collection frequency in cron configuration
  • Disable unused metric aggregators in admin configuration
  • Consider implementing metric data retention policies

Debug Mode

Enable debug logging by adding to app/etc/env.php:

'system' => [
    'default' => [
        'prometheus_exporter' => [
            'debug' => '1'
        ]
    ]
]

Performance Monitoring

Monitor the impact of metric collection:

# Check metric collection execution time
grep "prometheus.*aggregator" var/log/system.log

# Monitor database table size
SELECT COUNT(*) as total_metrics, 
       MAX(updated_at) as last_update 
FROM run_as_root_prometheus_metrics;

🤝 Contributing

We welcome contributions! Here's how you can help:

Development Setup

  1. Fork the repository
  2. Clone your fork: git clone https://gitlab.com/your-username/magento2-prometheus-exporter.git
  3. Install dependencies: composer install
  4. Create a feature branch: git checkout -b feature/your-feature-name

Code Standards

  • Follow Magento 2 coding standards
  • Write unit tests for new features
  • Update documentation for new metrics or features
  • Use meaningful commit messages

Pull Request Process

  1. Ensure all tests pass: vendor/bin/phpunit
  2. Update the CHANGELOG.md
  3. Submit a pull request with a clear description
  4. Respond to code review feedback

Reporting Issues

Please include:

  • Magento version
  • PHP version
  • Module version
  • Detailed error messages
  • Steps to reproduce

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • run_as_root GmbH - Original development and maintenance
  • Prometheus Community - For the excellent monitoring toolkit
  • Magento Community - For feedback and contributions

📞 Support


Made with ❤️ by run_as_root

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to
Semantic Versioning.

[4.1.0] - 2026-05-28

Changed

  • symfony/console constraint widened to ^5.4.46|^6.0|^7.0 for Magento 2.4.9 compatibility. (#65)
  • Test suite modernised: removed getMockForAbstractClass() usage (deprecated in PHPUnit 10+), replaced returnCallback() pattern to resolve deprecation notices, and completed mock method definitions. (#65)

[4.0.0] - 2026-04-20

Added

  • GitHub Actions CI via graycoreio/github-actions-magento2 against the Mage-OS supported-version matrix (Magento 2.4.6-p14 / 2.4.7-p9 / 2.4.8-p4). Unit tests, DI compile, Magento coding standard, and integration tests all run on every push and PR. (#60)
  • phpcs.xml.dist with the Magento2 coding standard and project-specific exclusions.
  • magento_complex_product_variations_above_recommended_level (gauge) — count of configurable products with more than 50 variations. (#25)
  • magento_quotes_over_item_limit_count_total (gauge, store_code label) — count of active carts with more than 100 items. (#32)
  • magento_products_with_bad_reviews_count_total (gauge, store_code label) — count of products with rating_summary < 60. Guarded by Magento_Review module-enabled check. (#26)
  • magento_cache_flush_count_total (counter) — incremented on every Magento\Framework\App\Cache\Manager::flush() invocation via a plugin. (#29)
  • UpdateMetricServiceInterface::increment(string $code, array $labels = []): bool for counter semantics.

Changed

  • BREAKING: minimum PHP requirement is now 8.2 (was 7.4).
  • BREAKING: UpdateMetricServiceInterface gained the increment() method — downstream implementers must add it.
  • magento/module-quote is now a runtime dependency (added to composer.json require and module.xml sequence).
  • magento/module-review is now suggested; the bad-reviews aggregator no-ops if the module isn't installed.
  • Test suite migrated from phpunit 9.x patterns (withConsecutive, at(), onConsecutiveCalls) to willReturnCallback so it runs green on phpunit 9/10/12.
  • composer.json declares repositories.mage-os (public Mage-OS mirror) and config.allow-plugins for the Magento composer plugins graycore's coding-standard job pulls in.

Fixed

  • Test/Integration/Controller/IndexControllerTest now supplies the metric_configuration/security/enable_token fixture so the test actually exercises the token validation code path.
  • Several unit tests had stale constructor mocks and mock-expectation drift versus current production signatures; all updated.
  • src/view/adminhtml/templates/system/config/tokenGeneratorButton.phtml: switched from deprecated $block->escape* to $escaper->escape* and fixed an unescaped-output XSS sniff.

Removed

  • BREAKING: deleted build/tools/ (legacy GitLab-CI tooling). Closes GHSA-r39x-jcww-82v6 (symfony/process MSYS2 arg escaping).

[2.0.2] - 2021-06-11

Fixed

  • Reset order count/amount metric before setting them

[2.0.1] - 2021-05-31

Fixed

  • Fix order count reset

[2.0.0] - 2020-05-15

Added

  • Added new CLI Command: run_as_root:metrics:collect.
  • Added CronJobCountAggregator to collect metric magento_cronjob_count_total.
  • Added BrokenCronJobCountAggregator to collect metric magento_cronjob_broken_count_total.
  • Added IndexerBacklogCountAggregator to collect metric magento_indexer_backlog_count_total.
  • Introduced custom cron group run_as_root_prometheus_metrics_aggregator.

Changed

  • Added some Interfaces instead of hard file links.
  • Changed CLI namespace to run_as_root.
  • Made all Test Cases final.
  • Restructured module directories.
  • Updated Readme.

Removed

  • Removed Licenses from PHP Files.

[1.0.0] - 2019-06-14

Added

  • Basic Module structure
  • Metric Collector via Cron
  • Console Command to view current metrics
  • Cms Aggregator
  • Order Aggregator
  • Some basic readme
  • Prometheus example configuration
  • Basic Test Coverage
  • StyleCi Integration

[1.0.1] - 2019-06-14

Changed

  • Fixed composer.json

[1.0.2] - 2019-06-14

Removed

  • Removed version from composer.json

[1.1.0] - 2019-06-18

Added

  • CodeCov
  • Customer Aggregator
  • Additional Unit Tests
  • Config wil be evaluated
  • Updated Readme

Changed

  • Fixed Metric Format
  • Configuration is now Multiselect

[1.2.0] - 2019-07-10

Changed

  • Interpret all metric aggregators as enabled when config value is NULL
Versions
Version Stability QA Status Compatibility Released
4.1.0 stable Fail Magento 2.4.7-2.4.8 Details 2026-05-28 14:32:16
4.0.0 stable Not tested Not yet tested Details 2026-04-20 13:44:03
3.2.6 stable Not tested Not yet tested Details 2025-12-28 12:14:51
3.2.5 stable Not tested Not yet tested Details 2025-12-19 14:19:30
3.2.4 stable Not tested Not yet tested Details 2025-08-29 12:52:00
3.2.3 stable Not tested Not yet tested Details 2025-06-03 06:47:10
3.2.2 stable Not tested Not yet tested Details 2024-11-12 11:42:28
3.2.1 stable Not tested Not yet tested Details 2024-11-07 10:27:50
3.2.0 stable Not tested Not yet tested Details 2024-11-07 10:27:01
3.1.6 stable Not tested Not yet tested Details 2023-11-22 08:05:19
3.1.5 stable Not tested Not yet tested Details 2023-08-21 15:17:58
3.1.4 stable Not tested Not yet tested Details 2023-07-07 09:18:46
3.1.3 stable Not tested Not yet tested Details 2023-07-07 09:08:32
3.1.2 stable Not tested Not yet tested Details 2023-07-07 08:48:58
3.1.1 stable Not tested Not yet tested Details 2023-06-26 07:11:38
3.1.0 stable Not tested Not yet tested Details 2023-06-23 14:55:53
3.0.1 stable Not tested Not yet tested Details 2021-12-06 08:27:49
2.0.2 stable Not tested Not yet tested Details 2021-06-14 10:56:49
2.0.1 stable Not tested Not yet tested Details 2021-06-01 08:39:32
2.0.0 stable Not tested Not yet tested Details 2021-06-01 08:37:53
1.2.0 stable Not tested Not yet tested Details 2019-07-10 09:13:15
1.1.0 stable Not tested Not yet tested Details 2019-06-18 09:11:40
1.0.2 stable Not tested Not yet tested Details 2019-06-14 15:42:05
1.0.1 stable Not tested Not yet tested Details 2019-06-14 15:37:50

Requires 20

Package Constraint
php ^8.2
magento/framework *
magento/module-payment *
magento/module-eav *
magento/module-cron *
magento/module-cms *
magento/module-shipping *
magento/module-catalog *
magento/module-sales *
magento/module-quote *
laminas/laminas-http ^2.15.0
magento/module-config *
magento/module-backend *
guzzlehttp/guzzle ^7.4.5
symfony/console ^5.4.46|^6.0|^7.0
psr/log ^1.1|^2.0|^3.0
monolog/monolog ^2.9.0|^3.0
magento/module-store *
magento/module-indexer *
magento/zend-db *

Requires-dev 1

Package Constraint
phpunit/phpunit ^9.5|^10.0

Conflicts 4

Package Constraint
symfony/process <5.4.46
guzzlehttp/guzzle <7.4.5
monolog/monolog <2.9.0
symfony/console <5.4.46

Suggests 1

Package Reason
magento/module-review Enables the magento_products_with_bad_reviews_count_total metric

Compatibility

Each Magento release line is installed on its supported PHP versions, then the module is built (DI compilation + static-content deploy) and its unit and integration suites are run. The matrix shows the lines and PHP versions the module is confirmed to install and run on. Code-quality results further down (phpstan, phpcs, …) are reported separately and never affect compatibility.

Compatibility matrix (Magento × PHP)
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Pass Pass
2.4.8 Pass Pass
2.4.9 not tested Pass

Code Quality

Advisory checks against the module's source. Static analysis runs once across the whole module; PHPStan re-runs per Magento + PHP version because resolvable symbols differ between releases. These NEVER affect the Compatibility badge — a phpcs finding can't make a module incompatible.

Static analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

Static analysis results
Tool Status Findings Summary
PHPCS Fail 277 29 errors, 248 warnings (ruleset: Magento2) — 32 auto-fixable with phpcbf
PHPMD Warning 16 16 rule violations (MissingImport:7, UnusedLocalVariable:5, UnusedFormalParameter:3, ExcessiveMethodLength:1)
Cpd Warning 3 3 duplicated chunks spanning 71 total lines (min-lines=5, min-tokens=70)
Composer validate Info 15 valid; 15 advisory notes (composer validate --strict)

PHPStan

Type-checks the module's PHP against a real Magento install at the configured gate level. Re-runs per Magento and PHP version because resolvable symbols differ between releases. Cell → details modal.

PHPStan results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 30 30
2.4.8 31 31
2.4.9 31 31

Tests

Unit and integration suites, run for each applicable Magento and PHP version. A test failure speaks to the module's behaviour, not its compatibility with a Magento line, so it is reported here separately and never reddens the compatibility matrix.

Unit tests

Unit tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 N/A N/A
2.4.8 N/A N/A
2.4.9 N/A N/A

Integration tests

Integration tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Pass Pass
2.4.8 Pass Pass
2.4.9 Pass Pass

Security

Security checks run directly against the module: an audit of its declared dependencies for known vulnerabilities (composer audit) and a scan of its source for malware and web-shell signatures. Each runs once. A malware detection fails the version outright.

Security results
Tool Status Findings Summary
Composer audit Pass 0
Malware scan Pass 0
License
MIT
Homepage
https://github.com/run-as-root/magento2-prometheus-exporter
Authors

More from run_as_root

View vendor
Make it pay

Turn an existing module into recurring revenue.

If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.