dreamfactory/df-mongo-logs
DreamFactory package that routes platform logs to MongoDB, helping centralize and persist API request and system log data for easier monitoring, querying, and retention in MongoDB-backed environments.
First, fix the source of truth. The package name is dreamfactory/df-mongo-logs, but the supplied URL (dreamfactorysoftware/df-skeleton) is the DreamFactory application skeleton, not the connector source. Look for dreamfactorysoftware/df-mongo-logs (or inspect vendor/dreamfactory/df-mongo-logs after install) before reading anything else. Confirm the package actually exists at the version you need — the last tagged release was 2019-10-08 and there are no dependents.
Minimum prerequisites
df-skeleton).ext-mongodb (PECL mongodb), plus the mongodb/mongodb userland library.Install
composer require dreamfactory/df-mongo-logs
php artisan vendor:publish --provider="DreamFactory\\...\\ServiceProvider" # if the package publishes config
php artisan config:clear
php artisan cache:clear
# restart php-fpm / queue workers so the provider and env are reloaded
Laravel package discovery usually registers the provider; if not, add it to config/app.php.
Where to look first
composer.json — extra.laravel.providers, PHP/Laravel constraints, and mongodb/mongodb version requirement.src/ — the service provider and the Monolog handler (or DreamFactory log service handler) that actually writes/reads Mongo documents. The class names and constructor options tell you exactly what is configurable.config/logging.php (Monolog channels) and the DreamFactory Admin → Services UI for the log service type registered by the package._id, timestamp, level, channel, message, context, extra — since every query and index depends on it.First use case: centralize logs from one or more DreamFactory instances into a Mongo collection so you can query them through the platform (or mongosh) instead of tailing storage/logs/laravel.log on each node. Write one test record (Log::channel('<channel>')->info('smoke-test') or trigger any API error), then read it back:
mongosh "$MONGO_URI" --eval 'db.logs.find().sort({timestamp:-1}).limit(1)'
If that document appears, the connector is wired; everything else is configuration and indexing.
1. Centralized platform logging across instances. Point every DreamFactory node's Mongo log channel at the same database/collection and stamp each document with instance, host, or app_env (via a custom Monolog processor or the handler's with context). This turns N log files into one queryable stream and is the strongest justification for the package.
2. Use the DreamFactory service interface instead of direct DB access. The connector's value is exposing log records through the platform's Log service API, so roles and API keys (not Mongo credentials) govern access. Create the service in Admin → Services, assign it to a role scoped to admins/ops, and query with the platform's standard GET /api/v2/{log_service} filters (limit, offset, filter, order). Keep the MongoDB service itself private.
3. Structured context, not string concatenation. Emit BSON-friendly context from custom scripts and services:
Log::channel('mongodb')->warning('Payment retry failed', [
'request_id' => $requestId,
'service' => 'billing',
'attempt' => 3,
]);
Prefer scalars, arrays, and MongoDB\BSON\UTCDateTime over arbitrary objects. This keeps documents filterable and small.
4. Index for the queries you actually run. At minimum:
db.logs.createIndex({ timestamp: -1 })
db.logs.createIndex({ level: 1, timestamp: -1 })
db.logs.createIndex({ service: 1, timestamp: -1 })
// retention
db.logs.createIndex({ timestamp: 1 }, { expireAfterSeconds: 60*60*24*30 })
Match these to the default sort/order the Log service applies; otherwise every API call is a collection scan.
5. Retention and volume control. MongoDB is a poor fit for unbounded debug logs. Set LOG_LEVEL to warning/error in production, keep a TTL index, and avoid logging request/response bodies. In DreamFactory, script and API log levels are configurable per service and per role — use them.
6. Test and CI setup. Bring up mongo in Docker Compose, point the channel at a disposable database with a short TTL, and assert on inserted documents. Use a distinct database name per test run so parallel suites don't collide.
7. Downstream integration. Poll the collection or use change streams to feed Grafana/Loki/ELK or an alerting job. Because documents are JSON-like, a tiny worker that forwards new level >= error records to Slack/PagerDuty is a common add-on. If you already run a log agent (Fluent Bit, Vector), weigh whether this package adds anything over routing the file/stdout stream.
8. Fork-and-patch as the maintenance model. Given the release cadence, treat the package as a vendored dependency you own: fork it, relax the mongodb/mongodb constraint, update the handler to the Monolog version your DreamFactory uses, and consume it via a VCS repository entry in composer.json.
HandlerInterface::handle array vs LogRecord) and processor APIs. A 2019 handler may fatal on a current DreamFactory stack. Check composer show monolog/monolog and patch or pin accordingly.ext-mongodb is separate from mongodb/mongodb. Install the PECL extension first; missing extension errors surface as "Class 'MongoDB\Driver\Manager' not found," not as a package error.DateTime is not UTCDateTime; TTL indexes silently do nothing on non-date fields. PHP associative arrays become documents while sequential arrays become arrays — inconsistent shapes make filters unreliable. Invalid UTF-8 or resource/circular references in context throw on serialization and can drop the log record.expireAfterSeconds changes require collMod. Confirm with db.logs.getIndexes() rather than assuming.authSource, replicaSet, and Atlas TLS options are easy to omit; test with mongosh using the exact URI the app uses. Change streams require a replica set, not standalone.php artisan config:clear after editing .env, and restart queue workers (queue:restart) and php-fpm — long-lived processes keep stale config and stale handlers.storage/logs/laravel.log for handler exceptions, run a one-off php artisan tinker write through the channel, confirm the collection and document shape in mongosh, then check the service/role config in Admin.context to JSON before insert. A custom Processor is usually cleaner than editing the handler.How can I help you explore Laravel packages today?