This post is yet another installment in the series where we show you how to quickly get started logging, one platform at a time. We’ve already covered C#, Java, Ruby, Python, and C++, and the last one was on Dart. Today we’re covering CakePHP Logging. CakePHP is an open-source framework for web development written in—you’ve guessed it—PHP. It allows its users to write database-backed web applications in a fast, flexible, and secure manner.
Today’s post will mainly follow the same structure of the previous posts in the series. Instead of opening the post with the initial example, we’ll start with an overview of CakePHP. If you’re already familiar with the tool, you can skip the overview, and we’ll not judge you for it.
After that, the post resumes as it is usual in the series:
- We start with a super quick and easy logging example in CakePHP.
- Then we explain what application logging is and what are the benefits it provides.
- After that, we go back and rewrite the first example, this time using a more sophisticated and realistic approach.
Before parting ways, we share some final tips and links for further reading. Let’s get started.
A Brief Overview of CakePHP
Most of the posts in the “get started with logging” series start right away with the minimum logging example. That makes sense for languages like C# and Java that are widely known. On the other hand, there are languages and platforms that are less known, so it might be helpful to add a quick overview of them. We did that for the Dart post, for instance. Even though the language was released almost a decade ago, many people might still not know it. We feel the same is true for CakePHP, despite it being one of the most popular PHP frameworks.
CakePHP is a free, open-source rapid development framework for PHP. Its a structure of libraries, classes, and run-time infrastructure for programmers creating web applications originally inspired by the Ruby on Rails framework.
CakePHP is a free, open-source application development framework for the PHP language, which consists of classes, libraries, and run-time infrastructure. It allows developers to create web applications in a quick but structured way. CakePHP was originally inspired by the Ruby On Rails framework.
The Simplest CakePHP Logging That Could Possibly Work
Now you’ll learn how to start logging in CakePHP in the easiest and fastest way possible. For this tutorial, we’ll be using CakePHP 4.0.8, which is the most recent stable version at the time of writing. To be able to follow the tutorial, install CakePHP along with its requirements.
Creating a Sample App
As soon as you get CakePHP installed, you’re ready to go. We’re going to start by creating a new CakePHP via Composer, running the following command:
composer create-project --prefer-dist cakephp/app:~4.0 cake_demo
After the command is successfully executed, you should have a CakePHP app called “cake_demo.” Now, let’s run the application to see if everything works as expected. The easiest way to check that is to run PHP’s built-in web server. Go to the application directory and execute the following command:
bin/cake server
If you run the command above as it is, without providing any arguments, it will serve your app at http://localhost:8765/. Open your favorite browser, paste that address and hit enter, and you’ll see something like this:
Improving Our App
The sample application we’ve created doesn’t do anything yet. We’re going to add some code to create a little bit of functionality. First, we’re going to need a controller. Under src/Controller, create a file called HelloWorldController.php, and add the following content to it.
<?php namespace App\Controller; use App\Controller\AppController; class HelloWorldController extends AppController { public function greet($name) { $this->set('name', $name); } }
Save the file and close it. What the code above does is simple: it declares a new controller class called “HelloWorldController” and defines an action method called “greet,” which receives a parameter called “name” and sets it as a variable for the view.
But what view? We haven’t defined any views yet. So, let’s do that. On templates, create a directory called “HelloWorld.” Inside the directory, create a file called “greet.php.” Open the file using your preferred text editor and paste the following content on it:
<h1>Greetings, <?= h($name);?>!</h1>
That’s right: just a single line. Let’s now test our changes. Use PHP’s CLI to serve the application again, adding “HelloWorld/greet/Alice” to the end of the address and pressing enter. If everything went well, that’s what you should see:
Time for Some Logging
Now that our app is no longer useless, we’re ready to perform some logging. We’re going to do that by adding a single line to our application.
In the “HelloWorldController” class, add the following line at the end of the “greet” method:
$this->log("We've just greeted a user!");
That’s it. Now serve the application again, and use it normally, passing a name in the URL to see it greeted. After doing so, go to the “logs” directory located in the application’s root, and you’ll see a file called “error.log.” Open it, and you’ll see something like this:
2020-06-04 11:30:45 Error: We've just greeted a user!
Is That It?
Congratulations! You’ve just logged a message in CakePHP! Was that really logging? Definitely. Is that all there is to logging? Definitely not.
As I’ve promised, that was the quickest possible start to logging in to CakePHP. It’s not a realistic approach that you’d use in production. It’s not really enough for most non-trivial applications. But it is real logging, or at least the backbone of it.
Now keep reading to really understand what logging is all about.
What Is Logging?
Let’s start by defining logging. In the first post in the series, we’ve defined logging like this:
Application logging involves recording information about your application’s runtime behavior to a more persistent medium.
As far as definitions go, this one is quite good and self-explanatory. But a question immediately follows: why would we want or need to record information about an app to a persistent medium? In other words: what are the motivations for logging?
What’s the Motivation for Logging?
Why do people log? As we’ve seen in the last section, to log is just to record information on how an application behaves, writing such information to a persistent medium. We do that in order to retrieve that information later, in order to understand an event or chain of events that happened in the past, not unlike a detective trying to uncover a mystery in a crime scene.
But why do we need to perform investigations on our apps? The reason has to do with software’s own complex nature.
We Log Because Software Is Hard
Software is complicated. When you release it to the wild, you’re basically forgoing any control you (thought you) had over it. As soon as it’s deployed, anything can happen. How do you know that everything went well? And when (not if) something fails, how are you supposed to know what went wrong and how?
We Log to Help Solving Problems
These are the types of situations where logging comes in handy. Logging gives you time-travel power. It allows you to after-the-fact debug your application. When you read the log entries, you can understand how your app behaved in the past and even retrace the steps a user took.
We Log to Better Answer Questions
Besides detecting and fixing issues, logging has the potential of revealing insights that would otherwise have been lost to you. It can help you answer questions that are relevant to the business, even when everything is going well. You might want to know, for instance, how many visitors each page gets each day, the location of visitors, or the most used features.
So, in a nutshell: application logging is essential. It can help us not only detect and fix problems, but also collect useful information that can improve our apps in a lot of different ways.
Taking Our Logging Approach Up a Notch: What to Capture and to Where?
Use log entries to perform a “time travel” in order to understand an app’s past behavior sounds like a sort of super-power. And in some sense, it is. But the logging approach we’ve used in the example isn’t quite there yet.
For starters, it just logs all the messages to CakePHP error log file. As we’ll see soon, not all log entries are the same. Some refer to errors, while others might refer to common events in the application.
You’ll want to log some events to log files; others, you might want to insert into a database table. This is related to yet another important concept that our approach overlooks, which is log levels.
What we should try to do next is to replace our approach with a more sophisticated one, so it becomes more useful for readers. To do that, it’s important to understand what a log entry is and what it encompasses.
Each log entry represents an event. Something relevant for your application happened, and you want to capture data about this event. What kind of data should you capture and record in a log entry? Here, balance is key: capture too little, and the log entry won’t be useful. Capture too much, and the few really essential bits get lost in a sea of noise.
The Components of a Log Entry
So, what to capture? The first essential component of a log entry is a timestamp since it’s useless to record an event if you didn’t record when it happened. Record times either using UTC or local time along with the offset from UTC and write it using the ISO-8601 format.
Another essential component of a log entry is the log message itself, which should be written in such a way as to pack the maximum amount of context with it.
Finally, you should definitely employ logging levels, which will allow you to filter and search messages, and give you the ability to fine-tune the granularity of your logging.
As soon as you know what to capture, you should define where to capture such information, and that’s what the next section is all about.
You Can Log to Different Media
In our initial example, we’ve used a log file. But that doesn’t mean files are the only possible destination or target for log entries. Quite the opposite, in fact. What follows is a list of some of the possible, common destinations for logs you should know, as featured in the first installment of the series:
- Tables in relational databases.
- A document database.
- Something like a console (live logging).
- The windows event viewer.
- A third-party aggregator or web service.
CakePHP Logging: How to Configure
Having dived deeper into the nature and purpose of logging, it’s now time to get practical again. We’re going to cover some of the important options when configuring CakePHP logging.
You configure the CakePHP logging during the bootstrap phase of your application, by editing the config/app.php file. Consider the code below:
'Log' => [ 'debug' => [ 'className' => FileLog::class, 'path' => LOGS, 'file' => 'debug', 'url' => env('LOG_DEBUG_URL', null), 'scopes' => false, 'levels' => ['notice', 'info', 'debug'], ], 'error' => [ 'className' => FileLog::class, 'path' => LOGS, 'file' => 'error', 'url' => env('LOG_ERROR_URL', null), 'scopes' => false, 'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'], ], ],
In the first part of the code above, we create one logger called “debug.” It is configured to handle the “notice,” “info,” and “debug” levels. As per its documentation, CakePHP, you can log a message using the following levels, which adhere to the standard POSIX levels:
- CakePHP supports various logging levels as shown below
- Emergency − System is unusable
- Alert − Action must be taken immediately
- Critical − Critical conditions
- Error − Error conditions
- Warning − Warning conditions
- Notice − Normal but significant condition
- Info − Informational messages
- Debug − Debug-level messages
The code also defines another logger, this time called “error.” The code configures the logger for different levels, and it defines another file name for the log. That’s a useful configuration to do. By creating different targets according to the log levels, it becomes easier for future readers to locate the entries they’re interested in faster.
Writing to Alternate CakePHP Log Files
As you saw, our logging statement wrote the message, “We’ve just greeted a user!” to the error.log file and labeled it accordingly with the “error” level. Well, that doesn’t seem to be right. After all, greeting a user was exactly what the application is supposed to do, and thus is clearly not an error. So, how do we go about logging with different levels and to different log files?
As it turns out, it’s easy to do this: just pass the desired log level as a second argument to the log function. Since our log message represents a significative yet normal event, it makes sense to label it with the “info” level. So, let’s do just that:
$this->log("We've just greeted a user!", 'info');
According to the configuration we’ve shown you above, logs with the “info” level should be written to a file called debug. So, if you inspect the /logs folder, you should see a file called debug.log. Its contents should look like this:
2020-06-04 12:30:09 Info: We've just greeted a user!
Alternatively, you can also use the methods provided by the Log class. First, add the required namespace to your controller:
use CakeLogLog;
Then, you could either use the write method passing the adequate level as a parameter or use the correct helper method—in the case of our example, info:
Log::write('info', "We've just greeted a user!"); Log::info("We've just greeted a user!");
Your log file should now have three identical messages.
CakePHP Logging: What Are the Next Steps?
Logging is vital in software development. It gives us time-travel superpowers we can use to understand how our applications behaved in the past. With that information, we can not only understand and fix problems but also answer questions and obtain insights that are relevant to the business.
Today’s post continued the series in which we teach you how to get up to speed with logging using a programming language or framework, featuring CakePHP.
CakePHP is a free and open-source web development framework in PHP, which allows developers to quickly create applications using the MVC pattern. We started the post with a brief overview of CakePHP. After that, we’ve rolled up our sleeves and showed you how to start logging in CakePHP, using a single line of code.
After that, you’ve learned more about logging. We’ve covered the definition of logging, as well as the motivations behind its use. You’ve seen some key components of a log entry and learned about some common destinations for log information. Finally, we’ve shown you some options on how to further configure logging in CakePHP.
What are the next steps? There’s just a single next step: more learning. And the Scalyr blog is actually the perfect place to learn more about logging, its best practices, and anti-patterns.
Stay tuned for more content. Happy logging!