Here are some good resources:
Briefly, (as far as I understand)
The logging module provides hierarchical loggers meaning if the root logger (the logger you get with logging.getLogger()) is formatted in a certain way all the loggers with other names, (logging.getLogger("other_logger")) will be formatted the same (unless if you set propagate to False)
 
The best practice for big projects as explained in the links above will be to define a logger configuration at the beginning of your package (i.e in __main__.py) and then just call
logging.getLogger(__name__)
 
Example:
source code here
project:
logs
├── errors.log # will be created automatically
├── std.log # will be created automatically
src
├── animals
│   ├── __init__.py       
│   ├── dog.py
|   |── cat.py
|   |── fish.py
└── main.py
Inside main.py:
import logging
from logging.config import dictConfig
LOG_CONFIG = {
    'version': 1,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'formatter': 'std',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout'
        },
          'my_detailed_console': {
            'level': 'WARNING',
            'formatter': 'error',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout'
        },
        'std_fh': {
            'level': 'INFO',
            'formatter': 'std',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'logs/std.log',
            'mode': 'a',
            'maxBytes': 1048576,
            'backupCount': 10
        },
        'my_detailed_fh': {
            'level': 'WARNING',
            'formatter': 'error',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'logs/errors.log',
            'mode': 'a',
            'maxBytes': 1048576,
            'backupCount': 10
        }
    },
    'loggers': {
        '': {  # root logger, all other loggers will be of this logger level implicitlly.
            'level':'DEBUG',
            'handlers': ['std_fh', 'console'], 
            
        },
        'my_detailed': {
            'level': 'WARNING',
            'propagate': False,
            'handlers': ['my_detailed_fh','my_detailed_console'],
          
        },
         'my_normal': {
            'level': 'INFO',
            'propagate': False,
            'handlers': ['std_fh','console'],
          
        }
    },
    'formatters': {
        'std': {
            'format': '[%(levelname)s  - %(asctime)s - %(name)s::] %(message)s'
        },
        'error': {
            'format': '[%(levelname)s - %(asctime)s - %(name)s - %(process)d::module :%(module)s|Line: %(lineno)s]  messages:[ %(message)s ]'
        },
    }
}
logging.config.dictConfig(LOG_CONFIG)
root_logger = logging.getLogger(__name__) # this is a root logger
my_normal_logger = logging.getLogger('my_normal.' + __name__) # this is an `src` logger 
my_detailed_logger = logging.getLogger('my_detailed.' + __name__) # this is 'my_detailed' 
def main():
    root_logger.debug("hello from root logger")
    my_normal_logger.debug("won't print") # higher level needed
    my_normal_logger.info("hello from my_normal logger")
    my_detailed_logger.info("won't print") # higher level needed
    my_detailed_logger.warning("hello from my_detailed logger") 
    import animals.cat
    import animals.cow
    import animals.fish
    
if __name__ == '__main__':
    main()
This is what you do in all animals
# cat.py
import logging
logger = logging.getLogger(__name__)
logger.info('mew mew')
Run main.py
output:
[DEBUG  - 2022-06-21 22:52:06,682 - __main__::] hello from root logger
[INFO  - 2022-06-21 22:52:06,682 - my_normal.__main__::] hello from my_normal logger
[WARNING - 2022-06-21 22:52:06,682 - my_detailed.__main__ - 15177::module :main|Line: 78]  messages:[ hello from my_detailed logger ]
[INFO  - 2022-06-21 22:52:06,683 - animals.cat::] mew mew
[INFO  - 2022-06-21 22:52:06,683 - animals.cow::] mooooo
[INFO  - 2022-06-21 22:52:06,683 - animals.fish::] blop blop
Note: I would recommend using the dict config instead of a file config for security measures (search here for eval()).