Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send Log event from Laravel to Loggly?

I want to send Monolog logs from my Laravel 5.1 application to Loggly.com online log management service. From all possible environment, including local development.

like image 676
Mladen Janjetovic Avatar asked Mar 28 '16 09:03

Mladen Janjetovic


4 Answers

I have found some outdated libs and complicated ways to do this. So I ended up with very simple solution. Actually, Laravel Monolog Handler already have Loggly Handler out of the box.

Add config info to config/services.php:

'loggly' => array(
    'key'   => 'ENTER_YOUR_LOGGLY_TOKEN_HERE',
    'tag'   => 'ProjectName_' .strtolower(env('APP_ENV')),
),

Than add Monolog handler in bootstrap/app.php, before $app is returned:

/*
|--------------------------------------------------------------------------
| Setup Loggly Handler
|--------------------------------------------------------------------------
*/
$app->configureMonologUsing(function($monolog) {
    $handler = new      \Monolog\Handler\LogglyHandler(config('services.loggly.key'),\Monolog\Logger::DEBUG);
    $handler->setTag(config('services.loggly.tag'));

    $monolog->pushHandler($handler);
});

Voila! You are getting your Monolog Logs in Loggly dashboard.


UPDATE: (thanks @thitami)

Based on laravel.com/docs/5.6/upgrade

The configureMonologUsing Method If you were using the configureMonologUsing method to customize the Monolog instance for your application, you should now create a custom Log channel. For more information on how to create custom channels, check out the full logging documentation.

like image 152
Mladen Janjetovic Avatar answered Sep 21 '22 04:09

Mladen Janjetovic


I was able to manage having Laravel's default local log behaviour, and pushing to Loggly in the same time, by tweaking mladen-janjetovic's code a bit. Tested on Laravel 5.3

config/services.php:

'loggly' => [
    'key'   => 'ENTER_YOUR_LOGGLY_TOKEN_HERE',
    'tag'   => 'ProjectName_' .strtolower(env('APP_ENV')),
],

bootstrap/app.php:

/*
|--------------------------------------------------------------------------
| Push to Loggly, and save locally.
|--------------------------------------------------------------------------
*/
$app->configureMonologUsing(function($monolog) use ($app) {
    $log = $app->make(Illuminate\Log\Writer::class);

    $logglyHandler = new \Monolog\Handler\LogglyHandler(config('services.loggly.key'));
    $logglyHandler->setTag(config('services.loggly.tag'));

    if (config('app.env') == 'production') 
    {
        // Push to Loggly and save local if in production 
        $log->getMonolog()->pushHandler($logglyHandler);
        $log->useFiles(storage_path('/logs/laravel.log'));
    }
    else
    {
        // Otherwise, save only locally
        $log->useFiles(storage_path('/logs/laravel.log'));
    }
});
like image 40
hasusuf Avatar answered Sep 21 '22 04:09

hasusuf


Alternatively, you may use Monolog-Cascade to do this.

Monolog-Cascade is a Monolog extension that allows you to set up and configure multiple loggers and handlers from a single config file.

Here is a sample config file for Monolog-Cascade using Loggly. This would log to you stdOut and to Loggly:

---
handlers:
    console:
        class: Monolog\Handler\StreamHandler
        level: DEBUG
        stream: php://stdout
    error_loggly_handler:
        class: Monolog\Handler\LogglyHandler
        level: ERROR
        token: xxxx-xxxx-xxxxxxxx
        tags: [cascade, waterfall]
loggers:
    my_logger:
        handlers: [console, error_loggly_handler]

If you're interested, here is a blog post on Cascade => https://medium.com/orchard-technology/enhancing-monolog-699efff1051d


[Disclaimer]: I am the main contributor of Monolog-Cascade.

like image 44
Raph Avatar answered Sep 21 '22 04:09

Raph


Got mine working with little configuration with Laravel 8.

Just use the built-in monolog handler for Loggly.

Edit your app/config/logging.php

use Monolog\Handler\LogglyHandler;

'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['single', 'loggly'],
            'ignore_exceptions' => false,
        ],

        'loggly' => [
            'driver' => 'monolog',
            'level' => env('LOG_LEVEL', 'debug'),
            'handler' => LogglyHandler::class,
            'with' => [
                'token' => env('LOGGLY_TOKEN'),
            ],
        ],
   ]

For more advanced logging (for my case I need to set the tag as it was missing in the built-in handler's constructor.

Copy the built-in handler where you can find it within vendor folder (e.g: vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php) into your app folder of choice (e.g: app/Logging/CustomLogglyHandler.php).

Modify the constructor to set the tags, and you need to change some of the imports as we're on different namespaces.

// app/Logging/CustomLogglyHandler.php

namespace App\Logging;

use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Handler\MissingExtensionException;
use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogglyFormatter;
use function array_key_exists;
use CurlHandle;
use Monolog\Handler\Curl\Util as CurlUtil;

  public function __construct(string $token, array|string $tag = [], $level = Logger::DEBUG, bool $bubble = true)
  {
    if (!extension_loaded('curl')) {
      throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler');
    }

    $this->token = $token;

    if (is_array($tag)) {
      $this->tag = $tag;
    } else {
      $this->tag = [$tag];
    }

    parent::__construct($level, $bubble);
  }


// config/logging.php


'loggly' => [
        'driver' => 'monolog',
        'level' => env('LOG_LEVEL', 'debug'),
        'handler' => CustomLogglyHandler::class,
        'with' => [
             'token' => env('LOGGLY_TOKEN'),
             'tag'   => strtolower(env('APP_NAME', 'Laravel')) . '_' . strtolower(env('APP_ENV', 'production'))
            ],
        ],

like image 39
Muhaimin Taib Avatar answered Sep 22 '22 04:09

Muhaimin Taib