Solving Logs Woes: A Small Dive into Singleton Design Pattern
Tags: python, logs, singleton, designpatterns
Published: 2024-04-28 14:17:17

Originaly published on Python in Plain English [Medium](https://python.plainenglish.io/solving-logs-woes-a-dive-into-singleton-design-pattern-1f77e70bd498) Publication

---

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hk3zmag9aev2mk95rkrv.jpg) Photos credit: [Saydung89](https://pixabay.com/users/saydung89-18713596/) & [Hitesh Choudhary](https://unsplash.com/@hiteshchoudhary)

---

Recently, I’ve been working on a new feature for a Python software project. To make sure it’s solid, I thought it’d be a good idea to add logs using the “[logging](https://docs.python.org/3/library/logging.html)” Python package. It’s been really helpful because I can see what’s happening at every step of my program right in the console. It’s made tracking down bugs a lot easier.

Initially, I thought incorporating _logging_ would be straightforward — simply import the library and start logs. However, I hit a roadblock when I couldn’t get it to write logs from files. Despite trying various solutions like checking the logging configuration file and creating new instances or modules, none of them worked. Then, a colleague suggested a solution I had overlooked: the _Singleton Design Pattern_. This approach turned out to be the key to solving my problem. Now, I’ll explain what it is and how to implement it, so you’ll feel confident using it in the future if similar issues arise.

## What Is Singleton Design Approach

The Singleton design pattern is a simple yet powerful concept often used in software development. Imagine you have a class (let’s call it Logger) and you want only one instance of this class to exist throughout your program’s execution.

In simpler terms, think of the Singleton as a guardian that ensures there’s only one instance of a particular class. It’s like having a single key to a treasure chest — no matter how many times you ask for the key, you’ll always get the same one.

### Here’s a breakdown:

- **One and Only One:** The Singleton ensures that there’s only one instance of a class. It’s like having a single instance of your favorite game running — you can’t open two instances of the same game simultaneously. 

- **Global Access:** Once the Singleton is created, it provides a global point of access to that instance. Just like a lighthouse guiding ships in the night, the Singleton guides your program to the same instance every time you need it.

- **Common Use Cases:** Singletons are handy for resources that should be shared across the entire application, such as a database connection, a logger, or a configuration manager.

- **Implementation:** Typically, Singletons are implemented using a static method `(like getInstance())` that either creates a new instance if none exists or returns the existing instance if it does.

**Here’s a simple example in Python:**

```
class Singleton:
 _instance = None

 @staticmethod
 def getInstance():
     if Singleton._instance is None:
         Singleton._instance = Singleton()
     return Singleton._instance

# Usage:
singleton_instance1 = Singleton.getInstance()
singleton_instance2 = Singleton.getInstance()

print(singleton_instance1 == singleton_instance2)  # Output: True
```

- **Benefits:** Singletons help conserve resources by ensuring that only one instance of a class exists. They also simplify global state management by providing a centralized point of access.

- **Caveats:** While Singletons are useful, they can sometimes be overused, leading to tight coupling and global state-related issues. It’s essential to use them judiciously and consider other alternatives when appropriate.

## How Singleton Design Resolved My Issue

Now, let’s delve into how I utilized the Singleton pattern to address my issue in the code:

```
class Logger:
 _instance = None

 def __new__(cls):
     if cls._instance is None:
         cls._instance = super().__new__(cls)
         cls._instance.setup_logger()
     return cls._instance

 def setup_logger(self):
     # logging configuration here
```

1. **`_instance` Attribute:** This attribute keeps track of the single instance of the `Logger` class.

2. **`__new__` Method:** Python’s special `__new__` method is harnessed here to manage object instantiation. If `_instance` is `None`, indicating no instance exists, a new one is created via `super().__new__(cls)` and `setup_logger()` is invoked to configure the logger. Subsequent calls to `__new__` will return the same instance stored in `_instance`.

3. **`setup_logger` Method:** Responsible for configuring the logger. It’s executed only once during the creation of the singleton instance.

### How It Functions:

- Whenever you create an instance of `Logger (logger_root = Logger())`, `__new__` kicks in.

- If `_instance` is `None`, implying no instance exists, a fresh one is created and stored in `_instance`.

- Subsequent calls to `Logger()` return the same instance stored in `_instance`, ensuring the singular existence of the L`ogger` class across your program.

### Pros and Considerations:

- **Universal Access:** Access the logger instance globally via `logger_root`.

- **Thread Safety:** This implementation doesn’t address thread safety. For multithreaded applications, consider synchronizing access to the singleton instance.

## Double Checking

I won’t delve too deeply into the double-checking pattern that I integrated into my `__new__` function. Essentially, I added double-checking within the `__new__` method by first checking if the _instance is None, then acquiring a lock to ensure thread safety, and finally rechecking if `_instance` is still `None` before creating a new instance. If you’re interested in learning more about it, you can check out this [link]( https://www.geeksforgeeks.org/java-program-to-demonstrate-the-double-check-locking-for-singleton-class/).

## Conclusion

By integrating the Singleton pattern, you ensure a streamlined, centralized logging mechanism within your project.

--- 

## References

https://medium.com/@emredalc/singleton-design-pattern-ce7e2f153aa0 

https://medium.com/geekculture/introduction-to-design-patterns-understanding-singleton-design-pattern-5a4d49960444

https://refactoring.guru/design-patterns/singleton

https://www.geeksforgeeks.org/singleton-pattern-in-python-a-complete-guide

https://docs.python.org/3/library/logging.html