CodeBriefly
Tech Magazine

Laravel Logging Guzzle Requests in File

0 4,289

Get real time updates directly on you device, subscribe now.

In this article, we will discuss Laravel Logging Guzzle Requests in File. In the multiple scenarios, we have to use third-party APIs in our project and test those API using postman or any other tool. But also required to maintain a log for each request, such as what we send (request)? and what we receive (response)? Today, I will try to explain to you how can we maintain the log for each Guzzle Client request.

There are multiple ways to do this, but the question is which one is easy to use when a project used multiple methods based on Guzzle Client.

Create a Custom Service Provider

You can use the following artisan command to create a service provider.

php artisan make:provider GuzzleClientServiceProvider

After executing the above mention command, GuzzleClientServiceProvider.php has been created and located at app\Providers.

Register Servier Provider

Register newly created service provider in config/app.php.

'providers' => [    ...    // Custom Service Provider    App\Providers\GuzzleClientServiceProvider::class,    ...],

Setup the Logger

Here we handle the writing our log messages to the file. We are using the Monolog package to handle this.

Ill set up a helper function get_logger to create the logger:

/** * Setup Logger */private function get_logger(){    if (! $this->logger) {        $this->logger = with(new Logger('guzzle-log'))->pushHandler(            new RotatingFileHandler(storage_path('logs/guzzle-log.log'))        );    }     return $this->logger;}

Setup the Middleware

Guzzles logging middleware requires a logger and a MessageFormatter instance that controls what gets logged. The $messageFormat is a string that formats log messages using variable substitutions for requests, responses, and other transactional data.

Ill set up a helper function setGuzzleMiddleware to create the middleware:

/** * Setup Middleware */private function setGuzzleMiddleware(string $messageFormat){    return Middleware::log(        $this->get_logger(),        new MessageFormatter($messageFormat)    );}

Setup the Logging Handler Stack

Here, I set up a helper function setLoggingHandler to create a HandlerStack with all the required logging middleware from an array of message format strings that I would like to log.

/** * Setup Logging Handler Stack */private function setLoggingHandler(array $messageFormats){    $stack = HandlerStack::create();    collect($messageFormats)->each(function ($messageFormat) use ($stack) {        // We'll use unshift instead of push, to add the middleware to the bottom of the stack, not the top        $stack->unshift(            $this->setGuzzleMiddleware($messageFormat)        );    });     return $stack;}

Update Boot Function

In the first line of boot method, we are telling Laravel that we want to register this code as a GuzzleClient in your Service Container. Then you see the $messageFormats array, which defines the logging format for our log file.

At last, the return statement, we are returning a function that will accept one argument $config. We used this function as a proxy so that we can pass an argument to it and that can be used in Client Object.

The rest of the code is building Guzzles handler object to Log all requests to a file called guzzle-log.log using Logger object of Monolog library. If you have daily logs enabled, a date will be appended to file name like guzzle-log-2020-04-06.log.

/** * Bootstrap services. * * @return void */public function boot(){    // Bind GuzzleClient     $this->app->bind('GuzzleClient', function () {         $messageFormats = [            'REQUEST: ',            'METHOD: {method}',            'URL: {uri}',            'HTTP/{version}',            'HEADERS: {req_headers}',            'Payload: {req_body}',            'RESPONSE: ',            'STATUS: {code}',            'BODY: {res_body}',        ];        $stack = $this->setLoggingHandler($messageFormats);        return function ($config) use ($stack){            return new Client(array_merge($config, ['handler' => $stack]));        };    });}

Finally, complete GuzzleClientServiceProvider.php looks like:

app->bind('GuzzleClient', function () {             $messageFormats = [                'REQUEST: ',                'METHOD: {method}',                'URL: {uri}',                'HTTP/{version}',                'HEADERS: {req_headers}',                'Payload: {req_body}',                'RESPONSE: ',                'STATUS: {code}',                'BODY: {res_body}',            ];             $stack = $this->setLoggingHandler($messageFormats);             return function ($config) use ($stack){                return new Client(array_merge($config, ['handler' => $stack]));            };        });    }    /**     * Setup Logger     */    private function get_logger()    {        if (! $this->logger) {            $this->logger = with(new Logger('guzzle-log'))->pushHandler(                new RotatingFileHandler(storage_path('logs/guzzle-log.log'))            );        }             return $this->logger;    }    /**     * Setup Middleware     */    private function setGuzzleMiddleware(string $messageFormat)    {        return Middleware::log(            $this->get_logger(),            new MessageFormatter($messageFormat)        );    }    /**     * Setup Logging Handler Stack     */    private function setLoggingHandler(array $messageFormats)    {        $stack = HandlerStack::create();         collect($messageFormats)->each(function ($messageFormat) use ($stack) {            // We'll use unshift instead of push, to add the middleware to the bottom of the stack, not the top            $stack->unshift(                $this->setGuzzleMiddleware($messageFormat)            );        });             return $stack;    }}

Test Laravel Logging Guzzle Requests

For testing, Ive used it directly in routes/web.php file. You can use anywhere.

// Guzzle tes route for loggingRoute::get('/guzzle-logger-test', function () {    // Using "app(GuzzleClient)" as per the GuzzleClientServiceProvider    $client = app('GuzzleClient')([        'base_uri'  => 'https://jsonplaceholder.typicode.com/',        'timeout'   => 10,        'verify'    => false,    ]);        $request = $client->get('users', [        'headers' => [ 'accept' =>  'application/json']    ]);    $response = json_decode((string) $request->getBody());    return response()->json($response);});

Heres the log file located at storage/logs/guzzle-log-2020-04-06.log.

[2020-04-06T18:18:58.293783+00:00] guzzle-log.INFO: REQUEST:  [] [][2020-04-06T18:18:58.298784+00:00] guzzle-log.INFO: METHOD: GET [] [][2020-04-06T18:18:58.298957+00:00] guzzle-log.INFO: URL: https://jsonplaceholder.typicode.com/users [] [][2020-04-06T18:18:58.299090+00:00] guzzle-log.INFO: HTTP/1.1 [] [][2020-04-06T18:18:58.299229+00:00] guzzle-log.INFO: HEADERS: GET /users HTTP/1.1 User-Agent: GuzzleHttp/6.5.1 curl/7.67.0 PHP/7.4.1 Host: jsonplaceholder.typicode.com accept: application/json [] [][2020-04-06T18:18:58.299374+00:00] guzzle-log.INFO: Payload:  [] [][2020-04-06T18:18:58.299490+00:00] guzzle-log.INFO: RESPONSE:  [] [][2020-04-06T18:18:58.299603+00:00] guzzle-log.INFO: STATUS: 200 [] [][2020-04-06T18:18:58.300660+00:00] guzzle-log.INFO: BODY: [   {     "id": 1,     "name": "Leanne Graham",     "username": "Bret",     "email": "Sincere@april.biz",     "address": {       "street": "Kulas Light",       "suite": "Apt. 556",       "city": "Gwenborough",       "zipcode": "92998-3874",       "geo": {         "lat": "-37.3159",         "lng": "81.1496"       }     },     "phone": "1-770-736-8031 x56442",     "website": "hildegard.org",     "company": {       "name": "Romaguera-Crona",       "catchPhrase": "Multi-layered client-server neural-net",       "bs": "harness real-time e-markets"     }   },   {     "id": 2,     "name": "Ervin Howell",     "username": "Antonette",     "email": "Shanna@melissa.tv",     "address": {       "street": "Victor Plains",       "suite": "Suite 879",       "city": "Wisokyburgh",       "zipcode": "90566-7771",       "geo": {         "lat": "-43.9509",         "lng": "-34.4618"       }     },     "phone": "010-692-6593 x09125",     "website": "anastasia.net",     "company": {       "name": "Deckow-Crist",       "catchPhrase": "Proactive didactic contingency",       "bs": "synergize scalable supply-chains"     }   },   {     "id": 3,     "name": "Clementine Bauch",     "username": "Samantha",     "email": "Nathan@yesenia.net",     "address": {       "street": "Douglas Extension",       "suite": "Suite 847",       "city": "McKenziehaven",       "zipcode": "59590-4157",       "geo": {         "lat": "-68.6102",         "lng": "-47.0653"       }     },     "phone": "1-463-123-4447",     "website": "ramiro.info",     "company": {       "name": "Romaguera-Jacobson",       "catchPhrase": "Face to face bifurcated interface",       "bs": "e-enable strategic applications"     }   },   {     "id": 4,     "name": "Patricia Lebsack",     "username": "Karianne",     "email": "Julianne.OConner@kory.org",     "address": {       "street": "Hoeger Mall",       "suite": "Apt. 692",       "city": "South Elvis",       "zipcode": "53919-4257",       "geo": {         "lat": "29.4572",         "lng": "-164.2990"       }     },     "phone": "493-170-9623 x156",     "website": "kale.biz",     "company": {       "name": "Robel-Corkery",       "catchPhrase": "Multi-tiered zero tolerance productivity",       "bs": "transition cutting-edge web services"     }   },   {     "id": 5,     "name": "Chelsey Dietrich",     "username": "Kamren",     "email": "Lucio_Hettinger@annie.ca",     "address": {       "street": "Skiles Walks",       "suite": "Suite 351",       "city": "Roscoeview",       "zipcode": "33263",       "geo": {         "lat": "-31.8129",         "lng": "62.5342"       }     },     "phone": "(254)954-1289",     "website": "demarco.info",     "company": {       "name": "Keebler LLC",       "catchPhrase": "User-centric fault-tolerant solution",       "bs": "revolutionize end-to-end systems"     }   },   {     "id": 6,     "name": "Mrs. Dennis Schulist",     "username": "Leopoldo_Corkery",     "email": "Karley_Dach@jasper.info",     "address": {       "street": "Norberto Crossing",       "suite": "Apt. 950",       "city": "South Christy",       "zipcode": "23505-1337",       "geo": {         "lat": "-71.4197",         "lng": "71.7478"       }     },     "phone": "1-477-935-8478 x6430",     "website": "ola.org",     "company": {       "name": "Considine-Lockman",       "catchPhrase": "Synchronised bottom-line interface",       "bs": "e-enable innovative applications"     }   },   {     "id": 7,     "name": "Kurtis Weissnat",     "username": "Elwyn.Skiles",     "email": "Telly.Hoeger@billy.biz",     "address": {       "street": "Rex Trail",       "suite": "Suite 280",       "city": "Howemouth",       "zipcode": "58804-1099",       "geo": {         "lat": "24.8918",         "lng": "21.8984"       }     },     "phone": "210.067.6132",     "website": "elvis.io",     "company": {       "name": "Johns Group",       "catchPhrase": "Configurable multimedia task-force",       "bs": "generate enterprise e-tailers"     }   },   {     "id": 8,     "name": "Nicholas Runolfsdottir V",     "username": "Maxime_Nienow",     "email": "Sherwood@rosamond.me",     "address": {       "street": "Ellsworth Summit",       "suite": "Suite 729",       "city": "Aliyaview",       "zipcode": "45169",       "geo": {         "lat": "-14.3990",         "lng": "-120.7677"       }     },     "phone": "586.493.6943 x140",     "website": "jacynthe.com",     "company": {       "name": "Abernathy Group",       "catchPhrase": "Implemented secondary concept",       "bs": "e-enable extensible e-tailers"     }   },   {     "id": 9,     "name": "Glenna Reichert",     "username": "Delphine",     "email": "Chaim_McDermott@dana.io",     "address": {       "street": "Dayna Park",       "suite": "Suite 449",       "city": "Bartholomebury",       "zipcode": "76495-3109",       "geo": {         "lat": "24.6463",         "lng": "-168.8889"       }     },     "phone": "(775)976-6794 x41206",     "website": "conrad.com",     "company": {       "name": "Yost and Sons",       "catchPhrase": "Switchable contextually-based project",       "bs": "aggregate real-time technologies"     }   },   {     "id": 10,     "name": "Clementina DuBuque",     "username": "Moriah.Stanton",     "email": "Rey.Padberg@karina.biz",     "address": {       "street": "Kattie Turnpike",       "suite": "Suite 198",       "city": "Lebsackbury",       "zipcode": "31428-2261",       "geo": {         "lat": "-38.2386",         "lng": "57.2232"       }     },     "phone": "024-648-3804",     "website": "ambrose.net",     "company": {       "name": "Hoeger LLC",       "catchPhrase": "Centralized empowering task-force",       "bs": "target end-to-end models"     }   } ] [] []

As per the placeholder API, we receive the list of users. In this file, we log both request and response. You can change the format as per your requirement.


Conclusion

I hope you have enjoyed this tutorial, Today weve explored Laravel Logging Guzzle Request in File. You can use this knowledge in your projects. If you have any query please feel free to add in the comment area 😉

Keep Learning, Stay Safe 🙂


Hope you like:

Log All SQL Queries in Laravel

Handle Content Scraping with Pagination in Laravel

How to Handle Logging in Laravel

How to Handle Content Scraping in Laravel

If you like our content, please consider buying us a coffee.
Thank you for your support!
Buy Me a Coffee

Get real time updates directly on you device, subscribe now.

Leave A Reply

Your email address will not be published.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. AcceptRead More