29
29
import textwrap
30
30
import traceback
31
31
from difflib import SequenceMatcher
32
- from typing import TYPE_CHECKING , Any , Callable
32
+ from typing import TYPE_CHECKING , Any , Callable , OrderedDict , cast
33
33
34
34
import confuse
35
35
@@ -1637,13 +1637,7 @@ def _configure(options):
1637
1637
overlay_path = None
1638
1638
config .set_args (options )
1639
1639
1640
- beet_logger = logging .getLogger ("beets" )
1641
-
1642
- # Configure the logger.
1643
- if config ["verbose" ].get (int ):
1644
- beet_logger .set_global_level (logging .DEBUG )
1645
- else :
1646
- beet_logger .set_global_level (logging .INFO )
1640
+ _configure_logging ()
1647
1641
1648
1642
if overlay_path :
1649
1643
log .debug (
@@ -1663,6 +1657,72 @@ def _configure(options):
1663
1657
return config
1664
1658
1665
1659
1660
+ def _configure_logging ():
1661
+ """Configure logging levels and handlers."""
1662
+
1663
+ if config ["verbose" ].get (int ):
1664
+ level = logging .DEBUG
1665
+ else :
1666
+ level = logging .INFO
1667
+
1668
+ root_logger = logging .getLogger ()
1669
+ beet_logger = logging .getLogger ("beets" )
1670
+
1671
+ root_logger .setLevel (level )
1672
+ beet_logger .set_global_level (level )
1673
+
1674
+ log_format = config ["logging" ]["format" ].get (
1675
+ confuse .String (default = "{message}" )
1676
+ )
1677
+ date_format = config ["logging" ]["date_format" ].get (
1678
+ confuse .String (default = "%Y-%m-%d %H:%M:%S" )
1679
+ )
1680
+
1681
+ # Remove the `StreamHandler` we added earlier so we can make a new one with
1682
+ # the user's format.
1683
+ for logger in [log , beet_logger , root_logger ]:
1684
+ stream_handlers = [
1685
+ handler
1686
+ for handler in logger .handlers
1687
+ if isinstance (handler , logging .StreamHandler )
1688
+ ]
1689
+ for handler in stream_handlers :
1690
+ logger .removeHandler (handler )
1691
+
1692
+ handler = logging .StreamHandler ()
1693
+ handler .setFormatter (
1694
+ logging .Formatter (
1695
+ fmt = cast (str , log_format ),
1696
+ datefmt = cast (str , date_format ),
1697
+ style = "{" ,
1698
+ validate = True ,
1699
+ )
1700
+ )
1701
+ logger .addHandler (handler )
1702
+
1703
+ level_names_mapping = logging .getLevelNamesMapping ()
1704
+ log_levels = config ["logging" ]["levels" ].get (
1705
+ confuse .MappingValues (
1706
+ confuse .OneOf (
1707
+ allowed = [
1708
+ confuse .Integer (),
1709
+ confuse .OneOf (allowed = level_names_mapping .keys ()),
1710
+ ]
1711
+ )
1712
+ )
1713
+ )
1714
+
1715
+ if log_levels :
1716
+ for name , level in cast (OrderedDict , log_levels ).items ():
1717
+ name = None if name == "root" else name
1718
+ logger = logging .getLogger (name )
1719
+ if isinstance (level , str ):
1720
+ level = level_names_mapping [level ]
1721
+ logger .setLevel (level )
1722
+ if hasattr (logger , "set_global_level" ):
1723
+ logger .set_global_level (level )
1724
+
1725
+
1666
1726
def _ensure_db_directory_exists (path ):
1667
1727
if path == b":memory:" : # in memory db
1668
1728
return
0 commit comments