Maintainability — Logs & Their Use
By: Oliver De Cramer
Tags: Coding, PHP, Monolog, Programming, Web Development

Maintenance 102

Maintainability — Logs & Their Use

An application that logs properly will make maintenance easier.

In the first chapter, we saw how to handle exceptions and how to log them to:

not leak sensitive data to the user.

have user user-friendly messages displayed for your users.

have all the details for easy troubleshooting.

In this second article, we will see what needs to be logged beside exceptions, how to log them, and why we are logging them.

The examples in the article are in PHP, using the PSR-3: Logger Interface; but the logging concepts we will discuss are common to all languages.

What to Log & How to Log

To decide what needs to be logged, we must first decide why we are logging the information.

Most often we need to log information to make diagnostic easier . For example, if an API returns an error we will log the request & response.

. For example, if an API returns an error we will log the request & response. We also log to for debug purposes , For example, we might log all api requests & responses in order the debug the api endpoint.

, For example, we might log all api requests & responses in order the debug the api endpoint. We can also log for statistics; this can be used for various reasons.

Logging for diagnostic

The most important log for diagnostic is the exception logs; those we have already discussed previously. But we can also log other “errors” for all errors are not exceptions.

One of the best examples of this is API calls; there are other cases as well; a missing file; an empty database query…. The cases depend upon your application.

Let’s see an example with an api call

<?php $response = $this->httpClient->get($endpoint, $query);

if ($response->getStatusCode() != 200) {

$this->logger->warning(

"Failed to fetch test data from test api",

[

"endpoint" => $endpoint,

"query" => $query,

"status_code" => $response->getStatusCode(),

"body" => $response->getBody()

]

); throw new MyApiException("Failed to fetch data from test api");

}

In this example, we logged everything we need to make the same api call locally to check what is going on. We also used a unique log message so that if we find the log message in our logs we can find the code that has logged it.

So the point here is to :

Log what you need to reproduce the error locally and you can’t get by any other means.

Log what you believe will allow a quick diagnostic (The body)

Log a unique message that has meaning.

Do not log every step of the code!

You need to keep in mind not to log sensitive data such as passwords.

Logging for Debug

Logging for debugging is very similar to logs for diagnostic. If you have api’s that are very sensitive and you can’t make api calls locally easily(payments for example). Or you do not trust the api. It can be a good idea to log everything.

Let’s add debugging data to our previous example;

<?php

$this->logger->debug(

"Fetching test data from test api",

[

"endpoint" => $endpoint,

"query" => $query,

]

); $response = $this->httpClient->get($endpoint, $query);

if ($response->getStatusCode() != 200) {

$this->logger->warning(

"Failed to fetch test data from test api",

[

"endpoint" => $endpoint,

"query" => $query,

"status_code" => $response->getStatusCode(),

"body" => $response->getBody()

]

); throw new MyApiException("Failed to fetch data from test api");

} $this->logger->debug(

"Fetched tes data from test api",

[

"endpoint" => $endpoint,

"query" => $query,

"body" => $response->getBody() ]

);

Here we have added 2 additional logs:

The first log is before making the call to the API. We log all the information we have at that point to be able to execute the same call locally if possible, or comparing with working calls.

The second log has the response, if we are working with payments this might be the only way to see a complete response. (Some payment methods have additional information on the production they don’t have in the sandbox).

So the point here is to :

Log what we do.

Log the result.

Like in the previous case you need to keep in mind not to log sensitive data such as passwords.