-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontextTracing
More file actions
105 lines (72 loc) · 7.35 KB
/
contextTracing
File metadata and controls
105 lines (72 loc) · 7.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 배경
- asset 조회 요청시 userid 와 ticker 가 무었이었는지, 그리고 asset 을 어떻게 조회했는지(주로 어떤 비동기 작업이 있었는지) 로그를 남길 필요성을 느껴서 비동기 작업들과 그 결과로 일종의 작업코드를 만들어서 로그를 남겼었음.
이후로도 점점 디테일하거나 특정한 로그가 필요했으나 디버그용으로 그때그떄 임시로 만들어 쓰거나 요청이 많지않아 손수 추적이 어렵지 않았음.
- 챗봇을 광고하자 유저들의 사용패턴이나 서버 모니터링 관점에서 더 자세한 로그가 필요했음.
특히 Inquire_V2 에서 Product, Market, Market-Child, OpenAI 등을 아우르는 비동기 작업에 대한 컨텍스트를 추적하고 로그를 남겨야 함.
# 방향 설정
- AsyncLocalStorage 사용하는것이 적절해보임. Nestjs 서드파티 nestjs-cls 도 있음.
- 분산환경에서 컨텍스트 추적에 대한 스터디를 좀더 하면서 TraceContext, W3C 표준, APM, open-telemetry 등 분산시스템에서 컨텍스트 추적과 모니터링에 대한 얕은 리서치를 진행함.
여러 솔루션이 있지만 공식적인 국제 표준은 W3C TraceContext 뿐. 현재 가장 범용적인 솔루션인것도 같음.
OpenTelemetry 라이브러리는 W3C TraceContext 를 구현하며, 다양한 다른 솔루션들과의 호환도 가능.
=> 이왕이면 국제 표준을 따라보자. OpenTelemetry 로 W3C TraceContext 를 구현하자. 단, 당장의 최소한의 필요만 구현하자.
# 검토
- OpenTelemetry JS SDK 2.x 는 Node.js ^18.19.0 || >=20.6.0 버전에서만 동작함.
프로젝트는 도커 이미지, keymetrics/pm2:18-alpine 을 사용하고 Node.js 18.12.1 임.
저 이미지를 사용하는것이 언젠가 부채가 될거라 생각하긴 했는데 이참에 node:xx.xx.xx-alpine3.xx 로 바꿀까?
=> Node.js 18.20.8 로 마이그레이션 하자.
- https://www.w3.org/TR/trace-context/
- https://opentelemetry.io/docs/
- https://github.com/open-telemetry/opentelemetry-js
- https://github.com/open-telemetry/opentelemetry-python
- 3 서버들(Product, Market, MarketChild)에 일단 간단히 적용하고 한번 보자.
- dnslookup, tcp, tls 등 모든것이 찍히는게 흥미롭네.
- MarketChild 쪽에서 컨텍스트가 안 이어지는문제 발견.
- 왜 그런지 보기 전에, trace-context 와 opentelemetry 에 대해 필요한 기본 사항을 이해해야해! (W3C 표준과 Opentelemetry 관련한 위 공식문서 참고함)
=> W3C Trace Context 표준과 Opentelemetry 로 이를 구현하는것 간단 정리.
- HTTP 요청 헤더에 traceparent 가 필수.
- traceparent 는 version, trace-id, parent-id, trace-flags 를 가짐.
- parent-id 는 부모 Span 의 id(span-id) 를 의미함.
- 요청 받으면 가장먼저 (nest 미들웨어보다 먼저) traceparent 파싱해서 Trace Context 구성함.
- 이떄, 만약 헤더에 traceparent 없어도 Trace Context 구성함. (새로 만들거나) (당연히, 이미 받은 요청 헤더에 traceparent 를 추가하는건 아님)
- 다른 작업을 할때마다 Trace Context 를 전파함. (HTTP 요청 할떄는 요청 헤더에 traceparent 만들어서 넣음)
- 전체 Context 는 하나의 trace_id 를 가지며 하나의 Trace Context 로 묶이고 모든 작업은 span_id 를 가지고 span_id 는 부모를 가지며 트리구조로 구성.
- 처음에 루트 스팬이 만들어짐.
- AsyncLocalStorage 안에는 trace_id 와 span_id 를 보관. (부모 span_id 등은 보관할 필요없음)
- Trace Context 를 전파하는 하는 것의 의미는, 한쪽에서 현재 trace_id 와 span_id 를 전파하고 전파받은쪽은 받은 Trace Context 와 Span 을 부모로 새로운 하위 Span 을 만드는 것임.
- 각 Span 의 생명주기는 잘 관리 되어야함. 특히 반드시 적잘한 타이밍에 span.end() 를 호출해야함.
- 혹시 응답을 기다리지 않고 버려지는 작업이더라도. (예시: span.setStatus({ code: CANCELLED }) 이후 span.end() 등으로)
- 동일 Trace Context 에 속한 모든 작업들은 각각 Span 으로 잘 연결될 수 있어야함.
- 여러 작업을 병열로 진행할땐 각 작업들이 동일한 부모 Span 을 갖도록 잘 관리되어야함. (context.with() 또는 AsyncLocalStorage 기반에서)
=> Trace Context 전파와 각 Span 의 생명주기 관리가 올바르게 되야 분산된 모든 작업(Span)이 하나의 Context 로 연계될 수 있음.
=> MarketChild 서버로 전파할 스팬들이 하나의 Trace Context 로 묶이는지 확인해야함. (아... 테스크 큐(동시성큐와 워커큐)에서 문제가 있겠다는 직감)
=> 테스크큐 구현에서 Context 가 이어질 수 없는 문제가 있음을 확인함.
=> context.with 로 쉽게 연결가능. (테스크큐 구현이 좋지 못한것 같음. 실행컨텍스트 관리가 어려운 구현임. 따로 점검필요함을 코드에 코맨트 해두기)
=> 커스텀 콘솔스팬익스포터 만들어서 디버그 해보자. (어디까지나 임시조치이다. 다른 계측 도구 써야함)
=> http 로깅할때 trace_id 달아주고 각 작업에서 trace_id 와 확인하고픈 data 만 간단히 로깅하면 목표를 달성 하겠군!
(이런식으로 직접 서버에 로깅 하는것은 어디까지나 임시조치임. exporter 계측 도구를 연결해서 관측하는게 바람직할것임. 그 전 단계로서 일단 필요한기능을 하는 임시적 도구를 만들어 써보자는거지.)
# 구현 프로세스
[V] Node.js 버전 18.20.8 으로 마이그레이션
[V] dockerfile
[V] test
[V] check_node_version read TargetVersion from engines.json in root
[V] fix errors caused by version
- 테스트에서 몇가지 에러 발견한것 빠른 수정!
[V] fix test errors
[V] make simple and syncronous e2e cases
[V] redis env issue -> todo
[V] Due to abandoned asynchronous operations, Jest exited a few seconds after the test run had completed.
-> Doc. Inquire_V2 경쟁하는 프로미스들
- 직전 픽스한 마켓차일드서버 exists 에서 다시 문제 발견.
[V] fix MarketChild exists - 주의 관찰 및 개선 필요함
[V] OpenTelemetry 이용해서 Context 추적가능하게 로깅하기 (어디까지나 임시조치임. 전문 계측 도구를 통해 분석하는게 바람직할것임.)
[V] OpenTelemetry 를 서버에 적용
[V] Fix - MarketChild 로 Trace Context 전파 잘 되도록
=> 차일드 컨텍스트 전파 잘된다 확인.
[V] CustomConsoleSpanExporter
=> Inquire_V2 에서 3 서버 모두 컨텍스트 전파 잘된다. 확인.
[V] HttpLogger 에 trace_id 포함하기
(MarketChild 는 uvicorn.access 로거를 메인 로거로 쓰고있는데 이거 엉망이구만! 일단 대충 미들웨어로 로거 하나 더 달아줌)
[V] 언제 어떤 작업에서든 trace_id 를 포함해서 로깅할 수 있도록 하기
[V] 필요한 부분 로깅하기, CustomConsoleSpanExporter 비활성하기
[] openAI 에도 SDK 사용해서 트레이싱 세팅할 수 있다. 세팅하고 Product > YahooFinanceTickerService 에서 req_id 로깅하는 부분 지우기.
[] 계측 도구 exporter 로 연결해서 사용해보기?