Enable colored output for logging
[logging-analytics.git] / pylog / onaplogging / colorFormatter.py
1 # Copyright 2018 ke liang <lokyse@163.com>.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import os
16 import sys
17 import logging
18 from logging import Formatter
19
20
21 ATTRIBUTES = {
22     'normal': 0,
23     'bold': 1,
24     'underline': 4,
25     'blink': 5,
26     'invert': 7,
27     'hide': 8,
28
29 }
30
31
32 HIGHLIGHTS = {
33
34     'black': 40,
35     'red':  41,
36     'green': 42,
37     'yellow': 43,
38     'blue': 44,
39     'purple': 45,
40     'cyan': 46,
41     'white': 47,
42 }
43
44 COLORS = {
45
46     'black': 30,
47     'red': 31,
48     'green': 32,
49     'yellow': 33,
50     'blue': 34,
51     'purple': 35,
52     'cyan': 36,
53     'white': 37,
54 }
55
56 COLOR_TAG = "color"
57 HIGHLIGHT_TAG = "highlight"
58 ATTRIBUTE_TAG = "attribute"
59
60 RESET = '\033[0m'
61
62
63 def colored(text, color=None, on_color=None, attrs=None):
64     # It can't support windows system cmd right now!
65     # TODO: colered output on windows system cmd
66     if os.name in ('nt', 'ce'):
67         return text
68
69     if isinstance(attrs, str):
70         attrs = [attrs]
71
72     if os.getenv('ANSI_COLORS_DISABLED', None) is None:
73         fmt_str = '\033[%dm%s'
74         if color is not None and isinstance(color, str):
75             text = fmt_str % (COLORS.get(color, 0), text)
76
77         if on_color is not None and isinstance(on_color, str):
78             text = fmt_str % (HIGHLIGHTS.get(on_color, 0), text)
79
80         if attrs is not None:
81             for attr in attrs:
82                 text = fmt_str % (ATTRIBUTES.get(attr, 0), text)
83
84         #  keep origin color for tail spaces
85         text += RESET
86     return text
87
88
89 class BaseColorFormatter(Formatter):
90
91     def __init__(self, fmt=None, datefmt=None, colorfmt=None, style="%"):
92         if sys.version_info > (3, 2):
93             super(BaseColorFormatter, self).__init__(
94                 fmt=fmt, datefmt=datefmt, style=style)
95         elif sys.version_info > (2, 7):
96             super(BaseColorFormatter, self).__init__(fmt, datefmt)
97         else:
98             Formatter.__init__(self, fmt, datefmt)
99
100         self.style = style
101         if sys.version_info > (3, 2):
102             if self.style not in logging._STYLES:
103                 raise ValueError('Style must be one of: %s' % ','.join(
104                         logging._STYLES.keys()))
105
106         self.colorfmt = colorfmt
107
108         print(self.colorfmt, isinstance(self.colorfmt, dict))
109
110     def _parseColor(self, record):
111         """
112         color formatter for instance:
113         {
114             "logging-levelname":
115                 {
116                     "color":"<COLORS>",
117                     "highlight":"<HIGHLIGHTS>",
118                     "attribute":"<ATTRIBUTES>",
119                 }
120         }
121         :param record:
122         :return: text color, background color, text attribute
123         """
124         if self.colorfmt and isinstance(self.colorfmt, dict):
125
126             level = record.levelname
127             colors = self.colorfmt.get(level, None)
128
129             if colors is not None and isinstance(colors, dict):
130                 return colors.get(COLOR_TAG, None), \
131                        colors.get(HIGHLIGHT_TAG, None), \
132                        colors.get(ATTRIBUTE_TAG, None)
133
134         return None, None, None
135
136     def format(self, record):
137
138         if sys.version_info > (2, 7):
139             s = super(BaseColorFormatter, self).format(record)
140         else:
141             s = Formatter.format(self, record)
142         color, on_color, attribute = self._parseColor(record)
143         return colored(s, color, on_color, attrs=attribute)