dreamfactory/df-exporter-prometheus
DreamFactory module that exports DreamFactory platform metrics to Prometheus, enabling monitoring and alerting of your API platform. Note: this package is unmaintained and has no stars, so evaluate before production use.
This is not a general-purpose Laravel package you'll composer require into an app. It's a DreamFactory platform component — a metrics exporter that serializes DreamFactory's internal metric collections into the Prometheus text exposition format so a Prometheus server can scrape them. It ships as part of a DreamFactory install (composer require dreamfactory/df-exporter-prometheus inside a DreamFactory codebase), registered via a Laravel service provider like every other df-* module.
First steps
df-skeleton monorepo, so the GitHub link points at the whole platform rather than a tight, self-documenting package. Find the provider class, see what it registers (a route? a console command? an exporter driver binding?), and check require constraints against your DreamFactory version — this is where the 2019 release date bites.config/df.php / a package-local config/*.php) and the admin UI under System Config. Confirm the exporter key name from the provider — do not guess.curl -s -H 'Accept: text/plain' \
-H 'X-DreamFactory-Api-Key: <your-key>' \
https://df.example.com/api/v2/system/metrics
You want lines like df_api_requests_total{service="mysql",method="GET"} 42. If you get JSON, you're hitting the generic metrics endpoint and not the Prometheus formatter — check the format/Accept handling in the exporter class.
scrape_configs:
- job_name: dreamfactory
scrape_interval: 30s
scrape_timeout: 10s
metrics_path: /api/v2/system/metrics
static_configs:
- targets: ['df.example.com']
labels: { instance: df-prod-1, env: prod }
Pull, don't push. Prometheus scrapes DreamFactory on an interval; the exporter is stateless formatting on top of whatever counters DreamFactory accumulated. Keep the exporter out of the hot request path — no per-request network calls, no synchronous flush on every API call. Let the scrape do the work.
Label design is your main design decision. DreamFactory can generate metrics per service, per API key, per endpoint, per role. The exporter may emit all of it, and that's a cardinality trap. Decide up front what's dashboard-worthy (service, method, status class) versus debugging-only. If the exporter emits raw path labels, aggregate/relabel at Prometheus:
metric_relabel_configs:
- source_labels: [__name__]
regex: 'df_api_requests_total.*'
action: keep
- source_labels: [path]
target_label: path
regex: '/api/v2/([^/]+)/.*'
replacement: '/api/v2/$1/*'
Multi-instance / multi-tenant fleets. One scrape job per DreamFactory node, with instance and tenant/env labels set in static_configs or via file-SD/service discovery. Never let the exporter's own labels be the only identifier — restarting a node shouldn't look like a new timeseries.
Custom metrics and extension points. For app-specific numbers (records synced, queue depth behind a DreamFactory scripted service, custom business counters), don't fork the exporter. Two cleaner options:
system/metrics-adjacent endpoint or a scripted service that emits the exposition format yourself, and scrape it as a second job. Ten lines of sprintf beats fighting a 2019 codebase.Auth in the scrape config. DreamFactory's system endpoints usually want an API key or admin session. Put credentials in a file, not in YAML:
authorization:
type: ApiKey
credentials_file: /etc/prometheus/df_api_key
(Adjust the header name to whatever the exporter actually reads — verify against the provider's route middleware.)
Local dev loop. docker-compose with prom/prometheus + grafana/grafana, a scrape job pointed at your DreamFactory container, and promtool check metrics < sample.txt on a captured response. This is far faster than round-tripping through a shared staging Prometheus.
Alerting on the scraper itself. Always alert on up{job="dreamfactory"} == 0 and on scrape_duration_seconds approaching your timeout — the exporter is quiet when the platform is sick, which is exactly when you want to know.
github.com/dreamfactorysoftware/df-skeleton is the platform skeleton; this package is a read-only subtree split. Issues, PRs, and changelogs live in the monorepo. With zero stars, zero dependents, and a last release in October 2019, assume no upstream support and budget time to read the source yourself.composer why-not after adding it will tell you fast.php artisan config:cache will eat your config changes. Classic Laravel trap, and it applies here: change the exporter settings, forget to re-cache, and you'll debug a "config ignored" problem for an hour. php artisan config:clear first.[a-zA-Z_:][a-zA-Z0-9_:]*. If DreamFactory service names contain dots, dashes, or slashes, check how the exporter maps them — collisions after sanitization (e.g. my-service and my.service both becoming my_service) silently merge series.rate()/increase(), but only if you're not summing raw counters across instances — use sum(rate(...)), not sum(...).curl the endpoint raw → promtool check metrics on the body → Prometheus Status → Targets for the error string (context deadline exceeded, 401, unexpected content type) → Graph tab with {__name__=~"df_.*"} to see what actually landed.scrape_timeout, lower scrape_interval frequency, or point the exporter at a cached snapshot.config/df.php driver key, that binding — not the class internals — is where you override behavior. Subclassing a 2019 exporter is usually more work than writing a 60-line replacement implementing the same interface.How can I help you explore Laravel packages today?