Skip to content

Commit 25a04ad

Browse files
JedoreSuperskyyy
andauthored
Optimize loguru reporter plugin (#302)
* Optimize loguru reporter plugin * update CHANGELOG.md * fix support matrix * fix support matrix and plugin doc * fix message to be archived --------- Co-authored-by: Superskyyy (AWAY - OFFLINE) <[email protected]>
1 parent 51b28e2 commit 25a04ad

File tree

3 files changed

+13
-124
lines changed

3 files changed

+13
-124
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
- Feature:
66
- Add a new workflow to push docker images for arm64 and amd64 (#297)
77

8+
- Plugins:
9+
- Optimize loguru reporter plugin.(#302)
10+
811
- Fixes:
912
- Fix sw8 loss when use aiohttp (#299, issue#10669)
1013
- **Critical**: Fix a bug that leads to high cpu usage (#300, issue#10672)

docs/en/setup/Plugins.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ or a limitation of SkyWalking auto-instrumentation (welcome to contribute!)
3131
| [werkzeug](https://werkzeug.palletsprojects.com/) | Python >=3.7 - ['1.0.1', '2.0']; | `sw_http_server` |
3232
| [httpx](https://www.python-httpx.org/) | Python >=3.7 - ['0.23.*', '0.22.*']; | `sw_httpx` |
3333
| [kafka-python](https://kafka-python.readthedocs.io) | Python >=3.7 - ['2.0']; | `sw_kafka` |
34-
| [loguru](https://pypi.org/project/loguru/) | Python >=3.7 - ['0.6.0']; | `sw_loguru` |
34+
| [loguru](https://pypi.org/project/loguru/) | Python >=3.7 - ['0.6.0', '0.7.0']; | `sw_loguru` |
3535
| [mysqlclient](https://mysqlclient.readthedocs.io/) | Python >=3.7 - ['2.1.*']; | `sw_mysqlclient` |
3636
| [psycopg[binary]](https://www.psycopg.org/) | Python >=3.11 - ['3.1.*']; Python >=3.7 - ['3.0.18', '3.1.*']; | `sw_psycopg` |
3737
| [psycopg2-binary](https://www.psycopg.org/) | Python >=3.10 - NOT SUPPORTED YET; Python >=3.7 - ['2.9']; | `sw_psycopg2` |

skywalking/plugins/sw_loguru.py

Lines changed: 9 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@
1616
#
1717

1818
import logging
19-
import sys
2019
import traceback
21-
from multiprocessing import current_process
22-
from os.path import basename, splitext
23-
from threading import current_thread
2420

2521
from skywalking import config
2622
from skywalking.agent import agent
@@ -33,136 +29,29 @@
3329
link_vector = ['https://pypi.org/project/loguru/']
3430
support_matrix = {
3531
'loguru': {
36-
'>=3.7': ['0.6.0']
32+
'>=3.7': ['0.6.0', '0.7.0']
3733
}
3834
}
3935
note = """"""
4036

4137

4238
def install():
39+
if not config.agent_log_reporter_active:
40+
return
41+
4342
from loguru import logger
44-
from loguru._recattrs import RecordException, RecordFile, RecordLevel, RecordProcess, RecordThread
45-
from loguru._datetime import aware_now
46-
from loguru._get_frame import get_frame
47-
from loguru._logger import start_time, context as logger_context, Logger
48-
from types import MethodType
4943

50-
_log = logger._log
5144
log_reporter_level = logging.getLevelName(config.agent_log_reporter_level) # type: int
5245

53-
def gen_record(self, level_id, static_level_no, from_decorator, options, message, args, kwargs):
54-
""" Generate log record as loguru.logger._log """
55-
core = self._core
56-
57-
if not core.handlers:
58-
return
59-
60-
(exception, depth, record, lazy, colors, raw, capture, patcher, extra) = options
46+
def _sw_sink(message):
47+
record = message.record
6148

62-
frame = get_frame(depth + 2)
63-
64-
try:
65-
name = frame.f_globals['__name__']
66-
except KeyError:
67-
name = None
68-
69-
try:
70-
if not core.enabled[name]:
71-
return
72-
except KeyError:
73-
enabled = core.enabled
74-
if name is None:
75-
status = core.activation_none
76-
enabled[name] = status
77-
if not status:
78-
return
79-
else:
80-
dotted_name = name + '.'
81-
for dotted_module_name, status in core.activation_list:
82-
if dotted_name[: len(dotted_module_name)] == dotted_module_name:
83-
if status:
84-
break
85-
enabled[name] = False
86-
return
87-
enabled[name] = True
88-
89-
current_datetime = aware_now()
90-
91-
if level_id is None:
92-
level_icon = ' '
93-
level_no = static_level_no
94-
level_name = f'Level {level_no}' # not really level name, just as loguru
95-
else:
96-
level_name, level_no, _, level_icon = core.levels[level_id]
97-
98-
if level_no < core.min_level:
99-
return
100-
101-
code = frame.f_code
102-
file_path = code.co_filename
103-
file_name = basename(file_path)
104-
thread = current_thread()
105-
process = current_process()
106-
elapsed = current_datetime - start_time
107-
108-
if exception:
109-
if isinstance(exception, BaseException):
110-
type_, value, traceback = (type(exception), exception, exception.__traceback__)
111-
elif isinstance(exception, tuple):
112-
type_, value, traceback = exception
113-
else:
114-
type_, value, traceback = sys.exc_info()
115-
exception = RecordException(type_, value, traceback)
116-
else:
117-
exception = None
118-
119-
log_record = {
120-
'elapsed': elapsed,
121-
'exception': exception,
122-
'extra': {**core.extra, **logger_context.get(), **extra},
123-
'file': RecordFile(file_name, file_path),
124-
'function': code.co_name,
125-
'level': RecordLevel(level_name, level_no, level_icon),
126-
'line': frame.f_lineno,
127-
'message': str(message),
128-
'module': splitext(file_name)[0],
129-
'name': name,
130-
'process': RecordProcess(process.ident, process.name),
131-
'thread': RecordThread(thread.ident, thread.name),
132-
'time': current_datetime,
133-
}
134-
135-
if capture and kwargs:
136-
log_record['extra'].update(kwargs)
137-
138-
if record:
139-
kwargs.update(record=log_record)
140-
141-
if args or kwargs:
142-
log_record['message'] = message.format(*args, **kwargs)
143-
144-
if core.patcher:
145-
core.patcher(log_record)
146-
147-
if patcher:
148-
patcher(log_record)
149-
150-
return log_record
151-
152-
def _sw_log(self, level_id, static_level_no, from_decorator, options, message, args, kwargs):
153-
_log(level_id, static_level_no, from_decorator, options, message, args, kwargs)
154-
record = gen_record(self, level_id, static_level_no, from_decorator, options, message, args, kwargs)
15549
if record is None:
15650
return
15751

158-
core = self._core
159-
16052
if record['level'].no < log_reporter_level:
16153
return
16254

163-
if not config.agent_log_reporter_ignore_filter and record['level'].no < core.min_level: # ignore filtered logs
164-
return
165-
16655
# loguru has only one logger. Use tags referring Python-Agent doc
16756
core_tags = [
16857
KeyStringValuePair(key='level', value=record['level'].name),
@@ -202,7 +91,7 @@ def _sw_log(self, level_id, static_level_no, from_decorator, options, message, a
20291
body=LogDataBody(
20392
type='text',
20493
text=TextLog(
205-
text=sw_filter(message)
94+
text=sw_filter(record['message'])
20695
)
20796
),
20897
tags=tags,
@@ -221,8 +110,5 @@ def _sw_log(self, level_id, static_level_no, from_decorator, options, message, a
221110

222111
agent.archive_log(log_data)
223112

224-
# Bind _sw_log function to default logger instance.
225-
bound_sw_log = MethodType(_sw_log, logger)
226-
logger._log = bound_sw_log
227-
# Bind _sw_log function to Logger class for new instance.
228-
Logger._log = _sw_log
113+
# Make sure any logged message by loguru is also sent to skywalking OAP
114+
logger.add(_sw_sink)

0 commit comments

Comments
 (0)