The Art of Good Logging: Best Practices for Software Troubleshooting

The Art of Good Logging: Best Practices for Software Troubleshooting

To verify if the software code is functioning properly, we need to examine the output for a given input. Troubleshooting becomes tougher as the number of lines of software code increases.

In fact, you also need to log in to understand what is happening. Good log messages are crucial when troubleshooting a problem.

However, a common issue is that most programmers don’t log in to the right places. At Jcentrix, our passion for cutting-edge software development runs deep.

    Sometimes, a bug causes the system to behave incorrectly. Other times, the system works correctly, but our expectations are wrong.

    In both situations, the logs help you understand what’s happening in the system.

    You can also check the logs during exploratory testing after completing a new feature.

    The coder should log every point where a task might fail.

    Here are additional tips for maximizing the value of log messages:

    Don’t Overdo It

    Remember, too many logs can be unhelpful. It’s important to be mindful of what you’re logging. For instance, if you have a simple skip condition, logging “Skipped message of type margin_data_available” is just extra noise and should be avoided.

    Avoid Being Infrequent.

    When debugging a problem, you often need to understand how and why a task failed. If logging doesn’t cover all possible failure modes, you might end up guessing at times.

    Add Dynamic Information.

    Adding IP addresses and ports to the logging details is helpful. In general, add as much dynamic information as possible.

    Messages Suitable for Grep.

    Even if the log message automatically includes the file name and line number, it’s still a good idea to make the message text unique and easy to search with grep. This helps you quickly and easily locate the log statement in the code.

    If the logging is in a function that’s called from multiple places, consider adding an extra argument for a string that describes the specific case. This will make it clear in the log message which case it is referring to.

    Returning a List of Messages.

    Here’s a breakdown of the coding best practice described:

    1. Encapsulate Logic in Functions:

    When you have complex logic (rules or decisions) to handle, it’s a good practice to put that logic inside a function. This makes it easier to test the function by itself to ensure it works correctly.

    Return a Tuple:

    Instead of just returning a single result, the function returns a tuple. A tuple is like a container that holds multiple values. In this case, the tuple has two elements:

    Result: The outcome of the function’s logic (e.g., whether an agreement should be invoiced or not).

    Log Messages: A list of log messages explaining what decisions were made during the process.

    Generate Log Messages for Complex Logic:

    For more complicated logic, it’s useful to create log messages that describe the decisions being made. These messages help in understanding why certain decisions were taken when you look at the logs later.

    Concatenate and Output Log Messages:

    After calling the function, if there are log messages in the list, they are combined into a single log statement. This avoids cluttering the logs with multiple messages and makes it easier to read.

    Multiple Aspects in Logs:

    Sometimes, several factors influence a decision. For instance, if the logic involves checking both configuration settings and date conditions, both are included in the log messages. This ensures that all relevant information is captured and can be reviewed.

    Imagine a function that decides whether an agreement should be invoiced based on:

    Configuration Settings: Forcing a specific margin type.

    Agreement Start Date: Whether it’s in the future or the current period.

    The function might:

    1. Determine if the agreement should be invoiced.
    2. Return the result of this decision.
    3. Provide a list of log messages explaining why the decision was made (e.g., “Configuration requires margin type X” and “Agreement start date is in the future”).

    When you call this function, if there are any messages, they are combined into a single log entry, helping you understand the decision without overwhelming you with multiple log entries.

    Iterate.

    It’s challenging to get log messages perfect on the first try. It often needs several attempts before you are satisfied with the results. Additionally, if you’re troubleshooting a problem and the logs are missing important information, make sure to add it.

    Conclusion.

    Sometimes, logging might seem redundant, but it can still be valuable.

    As of now, the practice of using detailed log messages and encapsulating logic in functions remains valuable, but there have been advancements and tools that can complement or automate aspects of this approach. Here’s how things have evolved:

    Modern Tools and Practices

    1. Log Management Tools:
      Centralized Logging Solutions: Tools such as Datadog, Graylog, and Loggly provide centralized logging, which makes it easier to manage and analyze logs from multiple sources.
      Automated Alerting: These tools often include automated alerting features that can notify you of issues based on log patterns without manual intervention.
    2. Application Performance Monitoring (APM):
      Real-Time Monitoring: APM tools like New Relic or AppDynamics offer real-time performance monitoring and can automatically capture detailed transaction logs and performance metrics, reducing the need for manual logging.
    3. Integrated Development Environments (IDEs):
      Code Analyzers: Modern IDEs often include code analysis tools that can help identify issues and provide insights without extensive logging.
    4. Testing Frameworks:
      Automated Testing: Modern testing frameworks and CI/CD pipelines can automatically test and validate functions, including their logging output, reducing manual effort.

    Continued Importance of Manual Logging Practices

    Even with these advancements, manual logging practices still hold significant value:

    Custom Log Messages: You may need to include specific, detailed log messages that automated tools might not capture.

    Customizable Logging: Manual control over logging allows for customization tailored to specific application needs.

    Understanding Context: Detailed logs can provide context that automated tools might miss, especially in complex or custom scenarios.

    Best practices.

    1. Combine Automated and Manual Approaches: Use automated tools for general logging and performance monitoring but maintain manual logging for detailed, context-specific information.
    2. Leverage Modern Tools: Utilize advanced logging frameworks and APM tools to enhance visibility and reduce manual efforts.
    3. Focus on Structured Logs: Ensure logs are structured and include contextual information, making them easier to search and analyze with modern tools.

    In summary, while automated tools have advanced and can handle many aspects of logging and monitoring, the practice of manually adding detailed log messages remains relevant, especially for complex or custom scenarios.

    Combining these practices with modern tools provides a robust approach to logging and debugging.

    Scroll to Top