I've deployed a CakePHP application to Heroku. CakePHP writes its logs in APP_ROOT/app/tmp/logs/error.log and APP_ROOT/app/tmp/logs/debug.log by default but since there's no way to get a shell to a running Heroku web dyno, I can't see the content of those files.
As I understand it, the heroku logs command returns everything which has been dumped to STDERR and STDOUT. If I'm right about that, is there a way to force CakePHP to send its logs to STDOUT?
The Heroku PHP Buildpack tails the Apache and PHP log files as a background process as part of the dyno setup. See below.
cat >>boot.sh <<EOF
for var in \`env|cut -f1 -d=\`; do
echo "PassEnv \$var" >> /app/apache/conf/httpd.conf;
done
touch /app/apache/logs/error_log
touch /app/apache/logs/access_log
tail -F /app/apache/logs/error_log &
tail -F /app/apache/logs/access_log &
export LD_LIBRARY_PATH=/app/php/ext
export PHP_INI_SCAN_DIR=/app/www
echo "Launching apache"
exec /app/apache/bin/httpd -DNO_DETACH
EOF
In a fork of that build pack, I added in my own lines in the appropriate positions, then configured my app to use my custom build pack.
touch /app/www/tmp/logs/error.log
tail -F /app/www/app/tmp/logs/error.log &
But this didn't work. In fact, setting aside CakePHP specifics, I don't see any PHP or Apache log contents in the heroku logs either.
I think the following might work. Make sure you're using CakePHP 2.3.9.
App::uses('ConsoleOutput', 'Console');
CakeLog::config('default', array(
'engine' => 'ConsoleLog',
'stream' => new ConsoleOutput('php://stdout')
));
CakeLog::config('stdout', array(
'engine' => 'ConsoleLog',
'types' => array('notice', 'info'),
'stream' => new ConsoleOutput('php://stdout')
));
CakeLog::config('stderr', array(
'engine' => 'ConsoleLog',
'types' => array('emergency', 'alert', 'critical', 'error', 'warning', 'debug'),
'stream' => new ConsoleOutput('php://stderr')
));
CakeLog::config('debug', array(
'engine' => 'ConsoleLog',
'types' => array('notice', 'info', 'debug'),
'format' => 'debug %s: %s',
'stream' => new ConsoleOutput('php://stdout')
));
CakeLog::config('error', array(
'engine' => 'ConsoleLog',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
'format' => 'error %s: %s',
'stream' => new ConsoleOutput('php://stderr')
));
From the Heroku documentation: https://devcenter.heroku.com/articles/php-logging#cakephp
In your application configuration, instruct CakePHP to use the ConsoleLog engine for your logger setups:
CakeLog::config('default', array(
'engine' => 'ConsoleLog',
));
You can then use the regular logging methods.
CakeLog::warning("Hello, this is a test message!");
Refer to the Logging section of the CakePHP manual for more information.
In the latest versions of CakePHP (>= 3.6.0), the config/app.php file comes pre-configured to use an environment variable override for the stock debug and error logs. These vars should contain a DSN-style string defining the same attributes you would normally place in your config/app.php file.
In the Heroku dashboard under Settings (or via the heroku cli tool), you can add the following ENV vars:
LOG_DEBUG_URL = file:///?className=Cake%5CLog%5CEngine%5CConsoleLog&levels[]=notice&levels[]=info&levels[]=debug
LOG_ERROR_URL = file:///?className=Cake%5CLog%5CEngine%5CConsoleLog&levels[]=warning&levels[]=error&levels[]=critical&levels[]=alert&levels[]=emergency
The above two lines replicate the stock CakePHP logging, but redirect all output to the console instead of files.
you can use: 'className' => 'Cake\Log\Engine\ConsoleLog'
/**
* Configures logging options
*/
'Log' => [
'debug' => [
'className' => 'Cake\Log\Engine\ConsoleLog',
'path' => LOGS,
'file' => 'debug',
'levels' => ['notice', 'info', 'debug'],
'url' => env('LOG_DEBUG_URL', null),
],
'error' => [
'className' => 'Cake\Log\Engine\ConsoleLog',
'path' => LOGS,
'file' => 'error',
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
'url' => env('LOG_ERROR_URL', null),
],
],
Related
I have installed the Rollbar 7.0 into Laravel 8.0. PHP version is 7.4
I am trying to send a test exception message using a simple Console command but that sends me nothing.
My configs are the following:
config/app.php:
return [
'providers' => [
Rollbar\Laravel\RollbarServiceProvider::class
...
]
config/logging.php:
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['other', 'rollbar'],
'ignore_exceptions' => false,
],
'rollbar' => [
'driver' => 'monolog',
'handler' => MonologHandler::class,
'access_token' => env('ROLLBAR_TOKEN'),
'level' => env('ROLLBAR_LEVEL'),
'enabled' => true,
'environment' => env('ROLLBAR_ENVIRONMENT'),
]
....
config/services.php (but seems to be that it doesn't work)
'rollbar' => [
'access_token' => env('ROLLBAR_TOKEN'),
'environment' => env('ROLLBAR_ENVIRONMENT'),
'level' => env('ROLLBAR_LEVEL')
],
app.env:
ROLLBAR_TOKEN=real_token
ROLLBAR_LEVEL=debug
ROLLBAR_ENVIRONMENT=backend_test
And the console command itself has the following view:
public function handle()
{
// Rollbar::init([
// 'driver' => 'monolog',
// 'handler' => MonologHandler::class,
// 'access_token' => env('ROLLBAR_TOKEN'),
// 'level' => env('ROLLBAR_LEVEL'),
// 'enabled' => true,
// 'environment' => env('ROLLBAR_ENVIRONMENT'),
// ]);
try{
$x = 4/0;
} catch(\Exception $exception) {
Rollbar::error('caught demo exception', ["details" => $exception->getMessage()]));
Rollbar::flush();
exit(1);
}
}
So when it is like this, the rollbar stays silent. But if I uncomment the initialisation, that works well, sending a debug message to the rollbar.
That doesn't work all over the project too.
Could you please advice me, what could I do here in order to make it work globally with initialising in every file?
upd: I've also cleared config cache and tried to make a rollbar as a default
Laravel in app/logging.php has a default channel configuration. Normally "default" should mean that there are some other working channel too but here, somehow it the meaning is like "the only used channel". Or I just do not fully understand how should it work. So my rollbar channel seems to be overriden by the another "default" one, that is why the system doesn't use it. So the solution is to switch the default channel:
'default' => env('LOG_CHANNEL', 'stack'),
when the rollbar is included to stack channel or just
'default' => env('LOG_CHANNEL', 'rollbar'),
when it is not.
So I'm using beyondcode/laravel-websockets to setup a WS server and I want to work with multiple apps so I did this in config\websockets.php:
'apps' => [
[
'id' => env('A_APP_ID'),
'name' => env('A_APP_NAME'),
'key' => env('A_APP_KEY'),
'secret' => env('A_APP_SECRET'),
'path' => env('A_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
[
'id' => env('B_APP_ID'),
'name' => env('B_APP_NAME'),
'key' => env('B_APP_KEY'),
'secret' => env('B_APP_SECRET'),
'path' => env('B_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
However, I want to implement custom handlers for each app and I've been trying this, routes\web.php:
WebSocketsRouter::webSocket('app/{appKey}/bapp', \App\WebSockets\BAppWebSocketHandler::class);
//Also tried this..
WebSocketsRouter::webSocket('app/{appKey}', \App\WebSockets\AAppWebSocketHandler::class);
//and created `AAppWebSocketHandler` which does nothing but calling parent (WebSocketHandler) methods
Problem is it's always using one handler for all apps despite the difference in routes.
Any ideas?
Thanks!
You don't have to define routes while defining multiple apps in the config. Instead configure Echo to work with separate app key and secret. If you want to use custom handler with own logic, then remove them from configs. Also note that, you won't get any channel or pusher client library support. You will have to implement your own authentication as well.
How do laravel print out some string on console when running php artisan serve?
I tried Log::info but it isn't working.
It's very simple.
You can call it from anywhere in APP.
$out = new \Symfony\Component\Console\Output\ConsoleOutput();
$out->writeln("Hello from Terminal");
Try with
error_log('message here.');
Read More
If You ant add LOG
Log::info('message');
If LOG with an array
Log::info(json_encode($array));
Import Illuminate\Support\Facades\Log;
Laravel 5.6 simplified this because you now have a logging.php config file you could leverage.
The key thing to know is that you want to output to stdout and php has a stream wrapper built-in called php://stdout. Given that, you could add channel for that wrapper. You would add the stdout "channel" to your channels that you will be logging to.
Here's how the config will basically look:
<?php
return [
'default' => env('LOG_CHANNEL', 'stack'),
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single','stdout'],
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
],
'stdout' => [
'driver' => 'monolog',
'handler' => StreamHandler::class,
'with' => [
'stream' => 'php://stdout',
],
],
];
I have more information here - Laravel 5.6 - Write to the Console
You've to config where laravel to store the logs. Default Log::info() put the log in the log file not the console. you can use tail -f logpath to see the log.
You can call info() method
$this->info("Your Message");
Module section config
'user' => [
'class' => 'dektrium\user\Module',
'modelMap' => [
'User' => 'app\models\DL\User',
'registrationForm' => 'app\models\DL\registrationForm',
],
'controllerMap' => [
/*'registration' => 'app\controllers\user\RegistrationController',
'admin' => 'app\controllers\user\AdminController'*/
],
'layout' => '#app/views/layouts/container',
'defaultRoute' => 'profile',
'admins' => ['admin'],
'enableFlashMessages' => false,
'params' => [
'menuItems' => [
'label' => 'Users',
'url' => ['/user/admin']
]
]
],
Yii console application (./yii) showing me error
'Calling unknown method:
app\controllers\user\AdminController::getHelpSummary()'
If I uncomment the controllerMap section, I can't understand why it autoloads in console app if my AdminController extends web controller not console.
This is commands from user module.
Do you really need the user module in console?
Yii2 console and web applications have separated configuration files by default. If you changed this default and use the same config for both of them, you must take care about consistency.
You can check the list of loaded configs in ./yii.
You need to specify a valid defaultRoute for the console application.
With 'defaultRoute' => 'profile', ./yiimay try to load a Controller which requires the user module.
Try adding it in the console configuration.
I'm trying to use an external cache engine, memcached, to power my CakePHP app.
I have an AWS EC2 instance running the app and also an AWS ElastiCache Cluster with one node using memcached. The memcache and memcached php modules are also installed and enabled.
The configuration in the app.php file is as follows:
'Cache' => [
'default' => [
'className' => 'File',
'path' => CACHE,
],
'elastic' => [
'className' => 'Cake\Cache\Engine\MemcachedEngine',
'compress' => false,
'duration' => '+2 minutes',
'groups' => [],
'host' => 'yyy.euw1.cache.amazonaws.com:11211',
'username' => null,
'password' => null,
'persistent' => false,
'prefix' => 'cake_',
'probability' => 100,
'serialize' => 'php',
'servers' => ['yyy.euw1.cache.amazonaws.com:11211'],
'options' => [],
'lock' => true
]
To select whether or not to query the database, this condition is used:
if (($car = Cache::read('car', 'elastic')) === false) {
$car = $this->Cars->get();
Cache::write('car', $car, 'elastic');
}
Unfortunately, after a long page load I get this error:
"elastic cache was unable to write to DebugKit\Cache\Engine\DebugEngine cache"
Does anyone knows the origin of this error? Can someone guide me through the configuration of memcached for cakephp, using an external cache engine?
Thank you upfront!
Thank you for your reply.
This issue is now closed. We had to allow IP access between EC2 and CloudCache Cluster.