DefStream 0.1.8__tar.gz → 0.1.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {defstream-0.1.8 → defstream-0.1.10}/DefStream.egg-info/PKG-INFO +56 -2
- {defstream-0.1.8 → defstream-0.1.10}/DefStream.egg-info/SOURCES.txt +9 -0
- {defstream-0.1.8 → defstream-0.1.10}/PKG-INFO +56 -2
- {defstream-0.1.8 → defstream-0.1.10}/README.en.md +11 -1
- {defstream-0.1.8 → defstream-0.1.10}/README.md +55 -1
- defstream-0.1.10/issues/feature/8/IMPLEMENTS.md +106 -0
- defstream-0.1.10/issues/feature/8/README.md +40 -0
- defstream-0.1.10/issues/feature/8/REQUIREMENTS.md +168 -0
- defstream-0.1.10/issues/feature/8/ci.refs.json +4 -0
- defstream-0.1.10/issues/fix/10/IMPLEMENTS.md +135 -0
- defstream-0.1.10/issues/fix/10/README.md +42 -0
- defstream-0.1.10/issues/fix/10/REQUIREMENTS.md +88 -0
- {defstream-0.1.8 → defstream-0.1.10}/sample/Broker/Sample.py +46 -8
- {defstream-0.1.8 → defstream-0.1.10}/sample/Worker/RabbitMQ/Client.py +14 -6
- {defstream-0.1.8 → defstream-0.1.10}/sample/Worker/RabbitMQ/Tasks.py +45 -6
- {defstream-0.1.8 → defstream-0.1.10}/sample/Worker/RabbitMQ/Worker.py +9 -3
- {defstream-0.1.8 → defstream-0.1.10}/sample/Worker/Redis/Sample.py +43 -4
- {defstream-0.1.8 → defstream-0.1.10}/sample/Worker/Sample.py +33 -7
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extensions/Console.py +40 -11
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extensions/Dashboard.py +10 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extensions/HealthCheck.py +21 -6
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extensions/Metrics.py +40 -5
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extensions/Specifications.py +29 -13
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Inspector.py +148 -17
- {defstream-0.1.8 → defstream-0.1.10}/src/Worker/Executor.py +74 -1
- {defstream-0.1.8 → defstream-0.1.10}/src/Worker/Pool.py +42 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Worker/Run.py +117 -1
- {defstream-0.1.8 → defstream-0.1.10}/src/Worker/Specification.py +0 -4
- {defstream-0.1.8 → defstream-0.1.10}/src/Worker/Worker.py +124 -18
- {defstream-0.1.8 → defstream-0.1.10}/test/test_dashboard.py +1 -1
- {defstream-0.1.8 → defstream-0.1.10}/test/test_inspector.py +59 -5
- defstream-0.1.10/test/test_inspector_logging.py +148 -0
- defstream-0.1.10/test/test_logging.py +329 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_runner_hooks.py +1 -1
- {defstream-0.1.8 → defstream-0.1.10}/test/test_specifications.py +119 -20
- {defstream-0.1.8 → defstream-0.1.10}/test/test_task_messages.py +1 -1
- {defstream-0.1.8 → defstream-0.1.10}/test/test_worker.py +51 -2
- {defstream-0.1.8 → defstream-0.1.10}/.github/workflows/ci.yml +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/.gitignore +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/DefStream.egg-info/dependency_links.txt +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/DefStream.egg-info/requires.txt +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/DefStream.egg-info/top_level.txt +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/LICENSE +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/feature/1/IMPLEMENTS.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/feature/1/README.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/feature/1/REQUIREMENTS.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/feature/1/TASK.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/feature/1/ci.refs.json +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/fix/3/IMPLEMENTS.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/fix/3/README.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/fix/3/REQUIREMENTS.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/fix/3/ci.refs.json +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/fix/6/IMPLEMENTS.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/fix/6/README.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/issues/fix/6/REQUIREMENTS.md +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/setup.cfg +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/setup.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Configuration.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Connection.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Consumer.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Errors.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Event.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Implements/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Policies.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Priority.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/Protocol.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Broker/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Descriptor/DataObject.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Descriptor/Types.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Descriptor/Value.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Descriptor/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extension.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extensions/Console.html +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extensions/Dashboard.html +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Extensions/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/Response.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Inspector/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Pattern.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/Array.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/Common.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/Compare.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/Condition.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/DataObject.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/DateTime.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/Number.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/Object.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/Size.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/String.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/Type.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Patterns/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Validate.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/Validator.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Validator/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Worker/Message.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Worker/Startup.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/Worker/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/src/__init__.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_dashboard_ui.cjs +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_descriptor.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_inspector_console.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_lifecycle_hooks.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_pool_callbacks.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_process_signals.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_protocol_contracts.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_release_workflow.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_task_priorities.py +0 -0
- {defstream-0.1.8 → defstream-0.1.10}/test/test_worker_startup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DefStream
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.10
|
|
4
4
|
Summary: Synchronous message processing with pluggable broker adapters
|
|
5
5
|
Home-page: https://github.com/yong5eon/DefStream
|
|
6
6
|
Author: Heo Yongseon
|
|
@@ -59,9 +59,60 @@ DefStream은 메시지 브로커에서 받은 작업을 일반 Python 함수처
|
|
|
59
59
|
- [생명주기 훅](#생명주기-훅)
|
|
60
60
|
- [요청·응답 계약과 검증](#요청응답-계약과-검증)
|
|
61
61
|
- [상태 확인과 작업 콘솔](#상태-확인과-작업-콘솔)
|
|
62
|
+
- [로깅](#로깅)
|
|
62
63
|
- [브로커 선택과 운영 주의사항](#브로커-선택과-운영-주의사항)
|
|
63
64
|
- [예제와 라이선스](#예제와-라이선스)
|
|
64
65
|
|
|
66
|
+
## 로깅
|
|
67
|
+
|
|
68
|
+
DefStream은 표준 `logging`으로 기록하며 핸들러·포매터·레벨을 설정하지 않습니다.
|
|
69
|
+
애플리케이션에서 필요한 출처만 선택해 출력하세요. 샘플은 `Sample`과 `DefStream`
|
|
70
|
+
이름 및 그 하위 로거만 출력하며, 샘플의 `print()`는 로그로 대체했습니다.
|
|
71
|
+
Worker의 기존 시작 배너는 로깅 설정과 무관하게 그대로 출력됩니다.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from logging import DEBUG, Filter, Formatter, StreamHandler, getLogger
|
|
75
|
+
|
|
76
|
+
sources = (Filter('Sample'), Filter('DefStream'))
|
|
77
|
+
handler = StreamHandler()
|
|
78
|
+
handler.setFormatter(Formatter(
|
|
79
|
+
'%(asctime)s %(processName)s %(name)s %(levelname)s %(message)s'
|
|
80
|
+
))
|
|
81
|
+
handler.addFilter(lambda record: any(source.filter(record) for source in sources))
|
|
82
|
+
root = getLogger()
|
|
83
|
+
root.setLevel(DEBUG)
|
|
84
|
+
root.addHandler(handler)
|
|
85
|
+
|
|
86
|
+
logger = getLogger('Sample')
|
|
87
|
+
logger.info('Application started')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
필터는 루트 로거가 아닌 **핸들러**에 적용합니다. `Filter('DefStream')`은
|
|
91
|
+
`DefStream`과 `DefStream.` 하위 이름을 포함하지만 `DefStreamExtra`는 포함하지 않습니다.
|
|
92
|
+
위 설정은 독립 실행 애플리케이션을 위한 예제이며, 이미 있는 다른 핸들러의 출력은 바꾸지 않습니다.
|
|
93
|
+
브로커만 보고 싶으면 `DefStream` 대신 `DefStream.Broker.Implements.RabbitMQ` 또는
|
|
94
|
+
`DefStream.Broker.Implements.Redis`를 선택할 수 있습니다.
|
|
95
|
+
|
|
96
|
+
- 클래스 멤버 `logger`에 `DefStream.Worker`, `DefStream.Run`, `DefStream.Executor`,
|
|
97
|
+
`DefStream.Pool`, `DefStream.ThreadPool`, `DefStream.ProcessPool`을 사용합니다.
|
|
98
|
+
- Pool 공통 메서드도 실제 풀의 로거 멤버를 사용합니다. 사용자 하위 클래스는 기본 이름을
|
|
99
|
+
상속하며 원하면 `logger`를 명시적으로 재정의할 수 있습니다.
|
|
100
|
+
- Inspector·Server·RequestHandler는 `DefStream.Inspector`를 공유합니다.
|
|
101
|
+
HTTP 요청 수신은 DEBUG, 응답 상태와 전송 결과는 INFO입니다.
|
|
102
|
+
확장 고유 로그는 `DefStream.Inspector.Extensions.<확장 이름>`을 사용합니다.
|
|
103
|
+
- 정상 메시지별 처리 흐름은 DEBUG, 생명주기는 INFO, 주의할 사건은 WARNING,
|
|
104
|
+
처리 실패는 ERROR로 기록합니다. 본문·결과·인증정보는 기본 로그에 포함하지 않습니다.
|
|
105
|
+
- 핸들러가 전혀 없으면 Python의 `lastResort`에 의해 WARNING 이상이 stderr에 나올 수 있습니다.
|
|
106
|
+
사용자 예외 메시지에는 민감한 값을 넣지 마세요. 실패 traceback에 예외 메시지가 포함됩니다.
|
|
107
|
+
|
|
108
|
+
ProcessPool은 `spawn` 자식 프로세스를 사용하므로 부모의 핸들러가 자동으로 전달되지 않습니다.
|
|
109
|
+
자식도 로그를 출력하려면 import 가능한 `PoolSetup` 구현에서 같은 설정을 적용하고
|
|
110
|
+
`ProcessPool(..., setups=...)`로 전달하세요. 자식 초기화 훅이 실행되기 전의 DEBUG·INFO는
|
|
111
|
+
그 설정으로 수신할 수 없습니다.
|
|
112
|
+
[RabbitMQ 작업 예제의 LoggingSetup](./sample/Worker/RabbitMQ/Tasks.py)과
|
|
113
|
+
[부모·자식 설정 예제](./sample/Worker/RabbitMQ/Worker.py)를 참고하세요.
|
|
114
|
+
기존 애플리케이션에서는 이미 설정한 핸들러를 반복 추가하지 않도록 초기화 위치를 관리해야 합니다.
|
|
115
|
+
|
|
65
116
|
## 설치
|
|
66
117
|
|
|
67
118
|
Python **3.9 이상**이 필요합니다. 실제 메시지 처리를 위해 사용할 브로커 서버도 준비하세요.
|
|
@@ -494,13 +545,14 @@ class Add(
|
|
|
494
545
|
schema=request_schema,
|
|
495
546
|
validator=request_validator,
|
|
496
547
|
example={'a': 10, 'b': 20},
|
|
497
|
-
description='Add two integers',
|
|
498
548
|
),
|
|
499
549
|
response=Specification(
|
|
500
550
|
schema=response_schema,
|
|
501
551
|
validator=response_validator,
|
|
502
552
|
example=30,
|
|
503
553
|
),
|
|
554
|
+
name='add',
|
|
555
|
+
description='Add two integers',
|
|
504
556
|
):
|
|
505
557
|
def run(
|
|
506
558
|
self,
|
|
@@ -517,6 +569,8 @@ class Add(
|
|
|
517
569
|
- 일반 JSON Schema 딕셔너리와 직접 작성한 검증 함수도 각각 `schema`, `validator`에 전달할 수 있습니다.
|
|
518
570
|
- `example`은 문서용 값이며 자동 실행·검증하지 않습니다.
|
|
519
571
|
- `format`의 기본값은 `application/json`입니다. 문서의 미디어 타입만 바꾸며 브로커 코덱은 별도 설정입니다.
|
|
572
|
+
- Run의 `name`은 AsyncAPI Operation 키와 Metrics 작업 키에 함께 사용합니다.
|
|
573
|
+
생략하면 `모듈명.__qualname__`을 사용하며, Run의 `description`은 AsyncAPI Operation에 표시됩니다.
|
|
520
574
|
- 실행 순서는 초기화 훅 → 요청 검증 → `run()` → 응답 검증 → 완료 훅 → 응답 발행·ACK입니다.
|
|
521
575
|
|
|
522
576
|
검증 예외는 작업 실패로 처리되어 오류 훅과 `on_error` 정책을 따릅니다.
|
|
@@ -14,6 +14,13 @@ issues/feature/1/README.md
|
|
|
14
14
|
issues/feature/1/REQUIREMENTS.md
|
|
15
15
|
issues/feature/1/TASK.md
|
|
16
16
|
issues/feature/1/ci.refs.json
|
|
17
|
+
issues/feature/8/IMPLEMENTS.md
|
|
18
|
+
issues/feature/8/README.md
|
|
19
|
+
issues/feature/8/REQUIREMENTS.md
|
|
20
|
+
issues/feature/8/ci.refs.json
|
|
21
|
+
issues/fix/10/IMPLEMENTS.md
|
|
22
|
+
issues/fix/10/README.md
|
|
23
|
+
issues/fix/10/REQUIREMENTS.md
|
|
17
24
|
issues/fix/3/IMPLEMENTS.md
|
|
18
25
|
issues/fix/3/README.md
|
|
19
26
|
issues/fix/3/REQUIREMENTS.md
|
|
@@ -83,7 +90,9 @@ test/test_dashboard_ui.cjs
|
|
|
83
90
|
test/test_descriptor.py
|
|
84
91
|
test/test_inspector.py
|
|
85
92
|
test/test_inspector_console.py
|
|
93
|
+
test/test_inspector_logging.py
|
|
86
94
|
test/test_lifecycle_hooks.py
|
|
95
|
+
test/test_logging.py
|
|
87
96
|
test/test_pool_callbacks.py
|
|
88
97
|
test/test_process_signals.py
|
|
89
98
|
test/test_protocol_contracts.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DefStream
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.10
|
|
4
4
|
Summary: Synchronous message processing with pluggable broker adapters
|
|
5
5
|
Home-page: https://github.com/yong5eon/DefStream
|
|
6
6
|
Author: Heo Yongseon
|
|
@@ -59,9 +59,60 @@ DefStream은 메시지 브로커에서 받은 작업을 일반 Python 함수처
|
|
|
59
59
|
- [생명주기 훅](#생명주기-훅)
|
|
60
60
|
- [요청·응답 계약과 검증](#요청응답-계약과-검증)
|
|
61
61
|
- [상태 확인과 작업 콘솔](#상태-확인과-작업-콘솔)
|
|
62
|
+
- [로깅](#로깅)
|
|
62
63
|
- [브로커 선택과 운영 주의사항](#브로커-선택과-운영-주의사항)
|
|
63
64
|
- [예제와 라이선스](#예제와-라이선스)
|
|
64
65
|
|
|
66
|
+
## 로깅
|
|
67
|
+
|
|
68
|
+
DefStream은 표준 `logging`으로 기록하며 핸들러·포매터·레벨을 설정하지 않습니다.
|
|
69
|
+
애플리케이션에서 필요한 출처만 선택해 출력하세요. 샘플은 `Sample`과 `DefStream`
|
|
70
|
+
이름 및 그 하위 로거만 출력하며, 샘플의 `print()`는 로그로 대체했습니다.
|
|
71
|
+
Worker의 기존 시작 배너는 로깅 설정과 무관하게 그대로 출력됩니다.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from logging import DEBUG, Filter, Formatter, StreamHandler, getLogger
|
|
75
|
+
|
|
76
|
+
sources = (Filter('Sample'), Filter('DefStream'))
|
|
77
|
+
handler = StreamHandler()
|
|
78
|
+
handler.setFormatter(Formatter(
|
|
79
|
+
'%(asctime)s %(processName)s %(name)s %(levelname)s %(message)s'
|
|
80
|
+
))
|
|
81
|
+
handler.addFilter(lambda record: any(source.filter(record) for source in sources))
|
|
82
|
+
root = getLogger()
|
|
83
|
+
root.setLevel(DEBUG)
|
|
84
|
+
root.addHandler(handler)
|
|
85
|
+
|
|
86
|
+
logger = getLogger('Sample')
|
|
87
|
+
logger.info('Application started')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
필터는 루트 로거가 아닌 **핸들러**에 적용합니다. `Filter('DefStream')`은
|
|
91
|
+
`DefStream`과 `DefStream.` 하위 이름을 포함하지만 `DefStreamExtra`는 포함하지 않습니다.
|
|
92
|
+
위 설정은 독립 실행 애플리케이션을 위한 예제이며, 이미 있는 다른 핸들러의 출력은 바꾸지 않습니다.
|
|
93
|
+
브로커만 보고 싶으면 `DefStream` 대신 `DefStream.Broker.Implements.RabbitMQ` 또는
|
|
94
|
+
`DefStream.Broker.Implements.Redis`를 선택할 수 있습니다.
|
|
95
|
+
|
|
96
|
+
- 클래스 멤버 `logger`에 `DefStream.Worker`, `DefStream.Run`, `DefStream.Executor`,
|
|
97
|
+
`DefStream.Pool`, `DefStream.ThreadPool`, `DefStream.ProcessPool`을 사용합니다.
|
|
98
|
+
- Pool 공통 메서드도 실제 풀의 로거 멤버를 사용합니다. 사용자 하위 클래스는 기본 이름을
|
|
99
|
+
상속하며 원하면 `logger`를 명시적으로 재정의할 수 있습니다.
|
|
100
|
+
- Inspector·Server·RequestHandler는 `DefStream.Inspector`를 공유합니다.
|
|
101
|
+
HTTP 요청 수신은 DEBUG, 응답 상태와 전송 결과는 INFO입니다.
|
|
102
|
+
확장 고유 로그는 `DefStream.Inspector.Extensions.<확장 이름>`을 사용합니다.
|
|
103
|
+
- 정상 메시지별 처리 흐름은 DEBUG, 생명주기는 INFO, 주의할 사건은 WARNING,
|
|
104
|
+
처리 실패는 ERROR로 기록합니다. 본문·결과·인증정보는 기본 로그에 포함하지 않습니다.
|
|
105
|
+
- 핸들러가 전혀 없으면 Python의 `lastResort`에 의해 WARNING 이상이 stderr에 나올 수 있습니다.
|
|
106
|
+
사용자 예외 메시지에는 민감한 값을 넣지 마세요. 실패 traceback에 예외 메시지가 포함됩니다.
|
|
107
|
+
|
|
108
|
+
ProcessPool은 `spawn` 자식 프로세스를 사용하므로 부모의 핸들러가 자동으로 전달되지 않습니다.
|
|
109
|
+
자식도 로그를 출력하려면 import 가능한 `PoolSetup` 구현에서 같은 설정을 적용하고
|
|
110
|
+
`ProcessPool(..., setups=...)`로 전달하세요. 자식 초기화 훅이 실행되기 전의 DEBUG·INFO는
|
|
111
|
+
그 설정으로 수신할 수 없습니다.
|
|
112
|
+
[RabbitMQ 작업 예제의 LoggingSetup](./sample/Worker/RabbitMQ/Tasks.py)과
|
|
113
|
+
[부모·자식 설정 예제](./sample/Worker/RabbitMQ/Worker.py)를 참고하세요.
|
|
114
|
+
기존 애플리케이션에서는 이미 설정한 핸들러를 반복 추가하지 않도록 초기화 위치를 관리해야 합니다.
|
|
115
|
+
|
|
65
116
|
## 설치
|
|
66
117
|
|
|
67
118
|
Python **3.9 이상**이 필요합니다. 실제 메시지 처리를 위해 사용할 브로커 서버도 준비하세요.
|
|
@@ -494,13 +545,14 @@ class Add(
|
|
|
494
545
|
schema=request_schema,
|
|
495
546
|
validator=request_validator,
|
|
496
547
|
example={'a': 10, 'b': 20},
|
|
497
|
-
description='Add two integers',
|
|
498
548
|
),
|
|
499
549
|
response=Specification(
|
|
500
550
|
schema=response_schema,
|
|
501
551
|
validator=response_validator,
|
|
502
552
|
example=30,
|
|
503
553
|
),
|
|
554
|
+
name='add',
|
|
555
|
+
description='Add two integers',
|
|
504
556
|
):
|
|
505
557
|
def run(
|
|
506
558
|
self,
|
|
@@ -517,6 +569,8 @@ class Add(
|
|
|
517
569
|
- 일반 JSON Schema 딕셔너리와 직접 작성한 검증 함수도 각각 `schema`, `validator`에 전달할 수 있습니다.
|
|
518
570
|
- `example`은 문서용 값이며 자동 실행·검증하지 않습니다.
|
|
519
571
|
- `format`의 기본값은 `application/json`입니다. 문서의 미디어 타입만 바꾸며 브로커 코덱은 별도 설정입니다.
|
|
572
|
+
- Run의 `name`은 AsyncAPI Operation 키와 Metrics 작업 키에 함께 사용합니다.
|
|
573
|
+
생략하면 `모듈명.__qualname__`을 사용하며, Run의 `description`은 AsyncAPI Operation에 표시됩니다.
|
|
520
574
|
- 실행 순서는 초기화 훅 → 요청 검증 → `run()` → 응답 검증 → 완료 훅 → 응답 발행·ACK입니다.
|
|
521
575
|
|
|
522
576
|
검증 예외는 작업 실패로 처리되어 오류 훅과 `on_error` 정책을 따릅니다.
|
|
@@ -30,6 +30,13 @@ Configure execution, acknowledgements, failure policies, and monitoring without
|
|
|
30
30
|
- [Broker selection and operational considerations](#broker-selection-and-operational-considerations)
|
|
31
31
|
- [Examples and license](#examples-and-license)
|
|
32
32
|
|
|
33
|
+
## 로깅 지원
|
|
34
|
+
|
|
35
|
+
클래스별 표준 로거와 사용자 주도 핸들러 설정을 지원합니다.
|
|
36
|
+
샘플은 `Sample` 및 `DefStream` 계층만 출력하며, ProcessPool 자식은 별도 setup 훅으로
|
|
37
|
+
출력을 설정합니다. Worker의 시작 배너는 유지됩니다.
|
|
38
|
+
로거 이름, 선택 수신, 예외 메시지 주의사항과 프로세스 설정은 [로깅 안내](./README.md#로깅)를 참고하세요.
|
|
39
|
+
|
|
33
40
|
## Installation
|
|
34
41
|
|
|
35
42
|
Requires Python **3.9 or newer**. Prepare the broker server you intend to use.
|
|
@@ -474,13 +481,14 @@ class Add(
|
|
|
474
481
|
schema=request_schema,
|
|
475
482
|
validator=request_validator,
|
|
476
483
|
example={'a': 10, 'b': 20},
|
|
477
|
-
description='Add two integers',
|
|
478
484
|
),
|
|
479
485
|
response=Specification(
|
|
480
486
|
schema=response_schema,
|
|
481
487
|
validator=response_validator,
|
|
482
488
|
example=30,
|
|
483
489
|
),
|
|
490
|
+
name='add',
|
|
491
|
+
description='Add two integers',
|
|
484
492
|
):
|
|
485
493
|
def run(
|
|
486
494
|
self,
|
|
@@ -497,6 +505,8 @@ class Add(
|
|
|
497
505
|
- Plain JSON Schema dictionaries and custom validation functions can also be passed as `schema` and `validator`.
|
|
498
506
|
- `example` is documentation data and is not automatically executed or validated.
|
|
499
507
|
- `format` defaults to `application/json`. It changes documented media types, not broker codecs.
|
|
508
|
+
- Run's `name` is used as both the AsyncAPI Operation key and the Metrics task key.
|
|
509
|
+
When omitted, `module.__qualname__` is used; Run's `description` appears on the AsyncAPI Operation.
|
|
500
510
|
- Execution order: setup hooks → request validation → `run()` → response validation → completion hooks → reply/ACK.
|
|
501
511
|
|
|
502
512
|
Validation exceptions are task failures and follow error hooks and the `on_error`
|
|
@@ -26,9 +26,60 @@ DefStream은 메시지 브로커에서 받은 작업을 일반 Python 함수처
|
|
|
26
26
|
- [생명주기 훅](#생명주기-훅)
|
|
27
27
|
- [요청·응답 계약과 검증](#요청응답-계약과-검증)
|
|
28
28
|
- [상태 확인과 작업 콘솔](#상태-확인과-작업-콘솔)
|
|
29
|
+
- [로깅](#로깅)
|
|
29
30
|
- [브로커 선택과 운영 주의사항](#브로커-선택과-운영-주의사항)
|
|
30
31
|
- [예제와 라이선스](#예제와-라이선스)
|
|
31
32
|
|
|
33
|
+
## 로깅
|
|
34
|
+
|
|
35
|
+
DefStream은 표준 `logging`으로 기록하며 핸들러·포매터·레벨을 설정하지 않습니다.
|
|
36
|
+
애플리케이션에서 필요한 출처만 선택해 출력하세요. 샘플은 `Sample`과 `DefStream`
|
|
37
|
+
이름 및 그 하위 로거만 출력하며, 샘플의 `print()`는 로그로 대체했습니다.
|
|
38
|
+
Worker의 기존 시작 배너는 로깅 설정과 무관하게 그대로 출력됩니다.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from logging import DEBUG, Filter, Formatter, StreamHandler, getLogger
|
|
42
|
+
|
|
43
|
+
sources = (Filter('Sample'), Filter('DefStream'))
|
|
44
|
+
handler = StreamHandler()
|
|
45
|
+
handler.setFormatter(Formatter(
|
|
46
|
+
'%(asctime)s %(processName)s %(name)s %(levelname)s %(message)s'
|
|
47
|
+
))
|
|
48
|
+
handler.addFilter(lambda record: any(source.filter(record) for source in sources))
|
|
49
|
+
root = getLogger()
|
|
50
|
+
root.setLevel(DEBUG)
|
|
51
|
+
root.addHandler(handler)
|
|
52
|
+
|
|
53
|
+
logger = getLogger('Sample')
|
|
54
|
+
logger.info('Application started')
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
필터는 루트 로거가 아닌 **핸들러**에 적용합니다. `Filter('DefStream')`은
|
|
58
|
+
`DefStream`과 `DefStream.` 하위 이름을 포함하지만 `DefStreamExtra`는 포함하지 않습니다.
|
|
59
|
+
위 설정은 독립 실행 애플리케이션을 위한 예제이며, 이미 있는 다른 핸들러의 출력은 바꾸지 않습니다.
|
|
60
|
+
브로커만 보고 싶으면 `DefStream` 대신 `DefStream.Broker.Implements.RabbitMQ` 또는
|
|
61
|
+
`DefStream.Broker.Implements.Redis`를 선택할 수 있습니다.
|
|
62
|
+
|
|
63
|
+
- 클래스 멤버 `logger`에 `DefStream.Worker`, `DefStream.Run`, `DefStream.Executor`,
|
|
64
|
+
`DefStream.Pool`, `DefStream.ThreadPool`, `DefStream.ProcessPool`을 사용합니다.
|
|
65
|
+
- Pool 공통 메서드도 실제 풀의 로거 멤버를 사용합니다. 사용자 하위 클래스는 기본 이름을
|
|
66
|
+
상속하며 원하면 `logger`를 명시적으로 재정의할 수 있습니다.
|
|
67
|
+
- Inspector·Server·RequestHandler는 `DefStream.Inspector`를 공유합니다.
|
|
68
|
+
HTTP 요청 수신은 DEBUG, 응답 상태와 전송 결과는 INFO입니다.
|
|
69
|
+
확장 고유 로그는 `DefStream.Inspector.Extensions.<확장 이름>`을 사용합니다.
|
|
70
|
+
- 정상 메시지별 처리 흐름은 DEBUG, 생명주기는 INFO, 주의할 사건은 WARNING,
|
|
71
|
+
처리 실패는 ERROR로 기록합니다. 본문·결과·인증정보는 기본 로그에 포함하지 않습니다.
|
|
72
|
+
- 핸들러가 전혀 없으면 Python의 `lastResort`에 의해 WARNING 이상이 stderr에 나올 수 있습니다.
|
|
73
|
+
사용자 예외 메시지에는 민감한 값을 넣지 마세요. 실패 traceback에 예외 메시지가 포함됩니다.
|
|
74
|
+
|
|
75
|
+
ProcessPool은 `spawn` 자식 프로세스를 사용하므로 부모의 핸들러가 자동으로 전달되지 않습니다.
|
|
76
|
+
자식도 로그를 출력하려면 import 가능한 `PoolSetup` 구현에서 같은 설정을 적용하고
|
|
77
|
+
`ProcessPool(..., setups=...)`로 전달하세요. 자식 초기화 훅이 실행되기 전의 DEBUG·INFO는
|
|
78
|
+
그 설정으로 수신할 수 없습니다.
|
|
79
|
+
[RabbitMQ 작업 예제의 LoggingSetup](./sample/Worker/RabbitMQ/Tasks.py)과
|
|
80
|
+
[부모·자식 설정 예제](./sample/Worker/RabbitMQ/Worker.py)를 참고하세요.
|
|
81
|
+
기존 애플리케이션에서는 이미 설정한 핸들러를 반복 추가하지 않도록 초기화 위치를 관리해야 합니다.
|
|
82
|
+
|
|
32
83
|
## 설치
|
|
33
84
|
|
|
34
85
|
Python **3.9 이상**이 필요합니다. 실제 메시지 처리를 위해 사용할 브로커 서버도 준비하세요.
|
|
@@ -461,13 +512,14 @@ class Add(
|
|
|
461
512
|
schema=request_schema,
|
|
462
513
|
validator=request_validator,
|
|
463
514
|
example={'a': 10, 'b': 20},
|
|
464
|
-
description='Add two integers',
|
|
465
515
|
),
|
|
466
516
|
response=Specification(
|
|
467
517
|
schema=response_schema,
|
|
468
518
|
validator=response_validator,
|
|
469
519
|
example=30,
|
|
470
520
|
),
|
|
521
|
+
name='add',
|
|
522
|
+
description='Add two integers',
|
|
471
523
|
):
|
|
472
524
|
def run(
|
|
473
525
|
self,
|
|
@@ -484,6 +536,8 @@ class Add(
|
|
|
484
536
|
- 일반 JSON Schema 딕셔너리와 직접 작성한 검증 함수도 각각 `schema`, `validator`에 전달할 수 있습니다.
|
|
485
537
|
- `example`은 문서용 값이며 자동 실행·검증하지 않습니다.
|
|
486
538
|
- `format`의 기본값은 `application/json`입니다. 문서의 미디어 타입만 바꾸며 브로커 코덱은 별도 설정입니다.
|
|
539
|
+
- Run의 `name`은 AsyncAPI Operation 키와 Metrics 작업 키에 함께 사용합니다.
|
|
540
|
+
생략하면 `모듈명.__qualname__`을 사용하며, Run의 `description`은 AsyncAPI Operation에 표시됩니다.
|
|
487
541
|
- 실행 순서는 초기화 훅 → 요청 검증 → `run()` → 응답 검증 → 완료 훅 → 응답 발행·ACK입니다.
|
|
488
542
|
|
|
489
543
|
검증 예외는 작업 실패로 처리되어 오류 훅과 `on_error` 정책을 따릅니다.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# 로깅 지원 구현 기록
|
|
2
|
+
|
|
3
|
+
## 1. 구현 개요
|
|
4
|
+
|
|
5
|
+
[요구사항](./REQUIREMENTS.md)에 따라 Worker 실행 흐름과 Inspector에 Python 표준
|
|
6
|
+
`logging`을 적용했다. 출력 정책은 애플리케이션에 맡기고 클래스별 명시적 로거로
|
|
7
|
+
관찰 지점을 제공한다.
|
|
8
|
+
|
|
9
|
+
- 구현·검증일: 2026-10-20
|
|
10
|
+
- 사용자용 안내: [변경 로그](./README.md)
|
|
11
|
+
- 연계 구현: [RabbitMQ](../../../../DefStream-RabbitMQ/issues/feature/5/IMPLEMENTS.md),
|
|
12
|
+
[Redis](../../../../DefStream-Redis/issues/feature/5/IMPLEMENTS.md)
|
|
13
|
+
|
|
14
|
+
## 2. 클래스별 로거와 기록 책임
|
|
15
|
+
|
|
16
|
+
로거는 클래스 멤버 `logger`로 정의하고 공통 메서드는 `self.logger`를 사용한다.
|
|
17
|
+
사용자 하위 클래스의 이름을 자동으로 사용하지 않으며, 명시적으로 재정의할 수 있다.
|
|
18
|
+
|
|
19
|
+
| 대상 | 로거 이름 | 구현한 관찰 지점 |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| [Worker](../../../src/Worker/Worker.py) | `DefStream.Worker` | 작업 등록, 연결·구독·훅, 수신·제출, 성공·실패 정책, 종료·미확인 메시지 |
|
|
22
|
+
| [Pool](../../../src/Worker/Pool.py) | `DefStream.Pool` | 제출, 포화, 슬롯 반환, 완료 대기와 종료 |
|
|
23
|
+
| ThreadPool·ProcessPool | `DefStream.ThreadPool`·`DefStream.ProcessPool` | 구체 풀 구성과 상속받은 공통 동작 |
|
|
24
|
+
| [Executor](../../../src/Worker/Executor.py) | `DefStream.Executor` | 실행 환경 시작·종료, 작업·결과 전달과 실행 환경 장애 |
|
|
25
|
+
| [Run](../../../src/Worker/Run.py) | `DefStream.Run` | 작업 전체 이름, 훅·입출력 검증·실행 단계와 소요 시간 |
|
|
26
|
+
| [Inspector·Server·RequestHandler](../../../src/Inspector/Inspector.py) | `DefStream.Inspector` | 확장 등록·시작, 서버 생명주기, HTTP 수신·응답과 내부 오류 |
|
|
27
|
+
| [Inspector 확장](../../../src/Inspector/Extensions) | `DefStream.Inspector.Extensions.<클래스 이름>` | HealthCheck·Console·Metrics·Dashboard·Specifications의 고유 처리 |
|
|
28
|
+
|
|
29
|
+
ThreadPool·ProcessPool의 공통 처리는 구체 클래스의 로거로 기록한다.
|
|
30
|
+
`Specification`에는 독립 로거를 추가하지 않았다.
|
|
31
|
+
|
|
32
|
+
## 3. 레벨과 실패 처리
|
|
33
|
+
|
|
34
|
+
- INFO: Worker·풀·실행 환경·서버의 생명주기와 HTTP 응답 전송 결과.
|
|
35
|
+
- DEBUG: 메시지별 정상 처리, 작업 실행·검증·훅, 풀 포화와 확장 고유 진단.
|
|
36
|
+
- WARNING: 잘못된 메시지, 명시적 완료 대기의 시간 초과와 Console 요청 거부 등.
|
|
37
|
+
- ERROR: 작업·실행 환경·서버·확장 내부 실패와 종료 후 확인 처리 불가.
|
|
38
|
+
|
|
39
|
+
Worker로 전달되는 작업 실패의 최종 ERROR와 traceback은 Worker가 담당한다.
|
|
40
|
+
Run·Pool·Executor의 일반 작업 실패 추적은 DEBUG로 기록해 중복을 줄였다.
|
|
41
|
+
Mapping이 아닌 메시지의 거부는 WARNING으로 구분하고 기존 실패 정책 호출은 유지했다.
|
|
42
|
+
Run을 직접 호출했을 때의 예외 전파도 유지한다.
|
|
43
|
+
|
|
44
|
+
## 4. Inspector의 HTTP 기록
|
|
45
|
+
|
|
46
|
+
기본 WSGI 요청 처리 경계를 확장하여 다음을 기록한다.
|
|
47
|
+
|
|
48
|
+
- 파싱한 요청 수신: DEBUG, HTTP 메서드와 쿼리를 제외한 경로.
|
|
49
|
+
- 응답 전송 결과: INFO, 메서드·경로·상태 코드·응답 크기·소요 시간.
|
|
50
|
+
- WSGI·연결 처리 실패: ERROR, 예외 타입과 프레임의 파일·줄·함수 위치.
|
|
51
|
+
|
|
52
|
+
확장에서는 공통 HTTP 접근 로그를 반복하지 않는다. 전송 중단을 정상 전송으로
|
|
53
|
+
기록하지 않으며, 오류 기록에는 예외 문자열과 소스 코드 줄을 포함하지 않는다.
|
|
54
|
+
HealthCheck는 probe 예약·응답·판정과 응답 생성을 DEBUG로 기록하고,
|
|
55
|
+
예약 실패를 ERROR로 기록한다. 상태 변화 전용 INFO·WARNING은 추가하지 않았다.
|
|
56
|
+
|
|
57
|
+
## 5. 출력 설정과 샘플
|
|
58
|
+
|
|
59
|
+
- 라이브러리는 핸들러·NullHandler·포매터·필터·레벨을 설정하지 않는다.
|
|
60
|
+
- 루트 로거까지 기본 전파를 유지하며, 미설정 시 표준 `logging.lastResort`가
|
|
61
|
+
WARNING 이상을 stderr에 출력할 수 있다.
|
|
62
|
+
- 런타임 로그 메시지는 영어로 작성하고 한국어 문서·주석은 유지한다.
|
|
63
|
+
- 본문·결과·인증정보를 기본 문맥에 넣지 않는다. 단, Worker의 작업 실패
|
|
64
|
+
traceback에는 사용자 예외 메시지가 포함될 수 있으므로 사용자가 주의해야 한다.
|
|
65
|
+
- [Worker 샘플](../../../sample/Worker)과 [Broker 샘플](../../../sample/Broker)은
|
|
66
|
+
`Sample`과 `DefStream` 계층만 핸들러 필터로 선택한다.
|
|
67
|
+
- 샘플의 `print()`는 로그로 전환하고 라이브러리 시작 배너는 유지했다.
|
|
68
|
+
- [RabbitMQ Worker 샘플](../../../sample/Worker/RabbitMQ/Worker.py)은 부모 진입점과
|
|
69
|
+
ProcessPool의 `setups`에 [LoggingSetup](../../../sample/Worker/RabbitMQ/Tasks.py)을
|
|
70
|
+
적용한다. `spawn` 자식이 부모의 핸들러를 자동 상속한다고 가정하지 않는다.
|
|
71
|
+
|
|
72
|
+
## 6. 검증 결과
|
|
73
|
+
|
|
74
|
+
Python 3.13.16에서 실제 RabbitMQ·Redis가 실행 중인 환경으로 검증했다.
|
|
75
|
+
|
|
76
|
+
| 검증 범위 | 결과 |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| 코어 로깅·Inspector·Worker·풀·훅·프로세스·메시지 관련 테스트 | 151개 통과 |
|
|
79
|
+
| RabbitMQ 연계 테스트 | 52개 통과 |
|
|
80
|
+
| Redis 연계 테스트 | 25개 통과 |
|
|
81
|
+
| 세 프로젝트 소스·샘플의 로그 및 observe 호출 문자열 | 376곳 점검, 한국어 문자열 없음 |
|
|
82
|
+
| 세 프로젝트 소스·샘플 `compileall` 및 `git diff --check` | 통과 |
|
|
83
|
+
|
|
84
|
+
[로깅 테스트](../../../test/test_logging.py)는 클래스 멤버·상속·사용자 재정의,
|
|
85
|
+
레벨·본문 제외·작업 실패 traceback 중복 방지·배너 유지·샘플 필터·spawn 설정을
|
|
86
|
+
검증한다. [Inspector 로깅 테스트](../../../test/test_inspector_logging.py)는 실제 HTTP
|
|
87
|
+
요청에서 수신·응답 각 1회 기록, 쿼리·본문 제외, WSGI 500과 전송 중단을 검증한다.
|
|
88
|
+
기존 테스트의 이전 모듈 로거 기대값도 새 이름과 레벨에 맞췄다.
|
|
89
|
+
|
|
90
|
+
위 228개는 선택해 실행한 관련 테스트의 합계이며 코어 전체 테스트 실행을 뜻하지 않는다.
|
|
91
|
+
모든 Python 버전·모든 파일의 정적 타입 검사나 배포 검증을 완료한 것은 아니다.
|
|
92
|
+
|
|
93
|
+
### 재검증
|
|
94
|
+
|
|
95
|
+
개발 가상환경과 로컬 브로커가 준비된 작업공간 루트에서 실행한다.
|
|
96
|
+
통합 테스트는 브로커에 테스트 자원을 생성·정리하므로 운영 환경을 사용하지 않는다.
|
|
97
|
+
|
|
98
|
+
```powershell
|
|
99
|
+
$env:PYTHONIOENCODING = 'utf-8'
|
|
100
|
+
$env:DEFSTREAM_RABBITMQ_TESTS = '1'
|
|
101
|
+
$env:DEFSTREAM_REDIS_TESTS = '1'
|
|
102
|
+
Set-Location .\DefStream\test
|
|
103
|
+
& ..\..\.venv\Scripts\python.exe -m unittest test_logging test_inspector_logging test_worker test_worker_startup test_pool_callbacks test_runner_hooks test_lifecycle_hooks test_process_signals test_inspector test_inspector_console test_dashboard test_specifications test_protocol_contracts test_task_messages
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
브로커별 재검증 명령은 각 구현 기록을 참고한다.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# 로깅 지원
|
|
2
|
+
|
|
3
|
+
## 변경 요약
|
|
4
|
+
|
|
5
|
+
Worker와 Inspector의 동작을 클래스별 표준 로거로 관찰할 수 있습니다.
|
|
6
|
+
라이브러리는 로그를 기록하며, 출력 대상·형식·레벨·필터는 애플리케이션이 정합니다.
|
|
7
|
+
런타임 로그 메시지는 영어입니다.
|
|
8
|
+
|
|
9
|
+
## 추가한 기록
|
|
10
|
+
|
|
11
|
+
- `DefStream.Worker`: 등록·시작·수신·완료·실패·종료.
|
|
12
|
+
- `DefStream.Run`: 작업별 훅·입출력 검증·실행 단계.
|
|
13
|
+
- `DefStream.Pool`, `DefStream.ThreadPool`, `DefStream.ProcessPool`,
|
|
14
|
+
`DefStream.Executor`: 실행 환경·제출·결과 회수·대기·종료.
|
|
15
|
+
- `DefStream.Inspector`: 서버 생명주기, 요청 수신(DEBUG), 응답 상태·크기·시간(INFO).
|
|
16
|
+
- `DefStream.Inspector.Extensions.<클래스 이름>`: 각 확장 고유 진단.
|
|
17
|
+
|
|
18
|
+
정상 메시지별 상세 흐름은 DEBUG, 주요 생명주기는 INFO로 확인할 수 있습니다.
|
|
19
|
+
잘못된 메시지와 대기 시간 초과는 WARNING, 작업·내부 처리 실패는 ERROR로 구분합니다.
|
|
20
|
+
Pool 공통 동작도 실제 ThreadPool·ProcessPool의 로거 이름으로 기록됩니다.
|
|
21
|
+
|
|
22
|
+
## 사용자 설정과 호환성
|
|
23
|
+
|
|
24
|
+
- 기존 `DefStream.Worker.Worker` 등 모듈 경로 기반 이름으로 필터링했다면
|
|
25
|
+
새 클래스별 이름으로 바꾸세요. `DefStream` 계층 전체 수신도 가능합니다.
|
|
26
|
+
- 클래스 멤버 `logger`를 상속하며 사용자 하위 클래스에서 재정의할 수 있습니다.
|
|
27
|
+
사용자 작업이 직접 생성한 로거 이름은 프레임워크가 바꾸지 않습니다.
|
|
28
|
+
- 핸들러·NullHandler·레벨을 자동 설정하지 않습니다.
|
|
29
|
+
핸들러가 없으면 Python의 `lastResort`로 WARNING 이상이 출력될 수 있습니다.
|
|
30
|
+
- 본문·결과·인증정보는 기본 로그 문맥에서 제외합니다. 사용자 예외 메시지는
|
|
31
|
+
Worker의 실패 traceback에 포함될 수 있으므로 민감정보를 넣지 마세요.
|
|
32
|
+
- 작업 처리·정산·종료 계약과 기존 시작 배너는 유지합니다.
|
|
33
|
+
|
|
34
|
+
## 샘플 변경
|
|
35
|
+
|
|
36
|
+
샘플은 `print()` 대신 `Sample` 로거를 사용하며 `Sample`과 `DefStream` 계층만
|
|
37
|
+
출력합니다. [RabbitMQ Worker 샘플](../../../sample/Worker/RabbitMQ/Worker.py)은
|
|
38
|
+
부모와 spawn 자식에 [LoggingSetup](../../../sample/Worker/RabbitMQ/Tasks.py)을 적용합니다.
|
|
39
|
+
실제 애플리케이션도 ProcessPool 자식의 로깅을 별도로 설정해야 합니다.
|
|
40
|
+
설정 예제는 [사용 설명서](../../../README.md#로깅)를 참고하세요.
|