I succeeded in implementing a Monolog logger for test purposes. And now I'm trying to use it in a project. This project doesn't use any MVC framework.
I'm trying to write a common class file to wrap access to the Monolog instance.
Common class file: File: app_log.php
require 'autoload.php';
use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Processor\UidProcessor;
use Monolog\Processor\WebProcessor;
use Monolog\Processor\MemoryUsageProcessor;
use Monolog\Processor\ProcessIdProcessor;
use Monolog\Formatter\LineFormatter;
class app_log {
public function info(){
$logger = new Logger('applog');
$handler = new RotatingFileHandler('useractivity.log', 0, Logger::INFO);
$handler->setFormatter(new LineFormatter("[%datetime%] %extra.process_id% %channel%.%level_name%: %message% %extra% %context% \n"));
$logger->pushHandler($handler);
$logger->pushProcessor(new WebProcessor);
}
}
Other File: users.php
include_once 'app_log.php';
class users extends dbconnector{
function login(){
// Some project code.
$logger = new app_log();
$logger->info('User logged successfully');
}
}
Up to this works well and i want to include filename, method name, request parameters. But i am getting app_log.php
file name instead users.php
and Method name is 'info'
instead 'login'
in the logs.
Example:
[2018-06-07 20:55:50] 4410 applog.INFO: User logged successfully {"file":"/var/www/portal/lib/app_log.php","line":59,"class":"app_log","function":"info"} []
Could you guys help on this part?
WebProcessor
will not add data you need, I mean file and line.IntrospectionProcessor
does what you need, tryI'm afraid your whole design is simply wrong.
Instead of instantiating a new
Logger
every time you need to log, you should be creating a single$logger
to use as a service around your application.Without knowing more about your application (and having to rewrite your application would make the question too broad anyway), it's hard to guess how to implement dependency injection here.
But a simplistic and naive approach would be:
And then:
If you inject that
Logger
instance in the objects that need it, you can use it directly without having to create your own "wrapper" (which in your example was poorly designed), and the output in the log files will match your expectations.Notice that you are not using the
IntrospectionProcessor
, which you'd need to capture the filename and file line number. In the above example I'm also pushing it in$logger
, theLogger
instance.(And also note that simply adding this processor to your code won't solve your issue, since the call to
Logger::info()
would always happen inapp_log::info()
).Remember that you'll need to add the corresponding
use
statement:use Monolog\Processor\IntrospectionProcessor;
I do not know all the details of your system, and can't build it all for you anyway, but if dependency injection is still too much for you, you could just cheat temporarily with a global-state approach.
E.g.:
You could put this in a file that you
require_once
, and in each of these places where you need access to the logger you can simply do:This is not something I'd endorse, but a crummy workaround for you to get moving until you advance somewhat in your understanding of other OOP topics. This is nothing else than a poor's man singleton, which more often than not is a pattern to avoid anyway; but that could help you right now..