๐ ์ด ๋ด์ฉ์ ์ฑ
๋ด์ฉ ๋ฉ๋ชจ์
๋๋ค.
๊ฐ์ธ์ ์ธ ์๊ฐ๊ณผ ๊ฒฝํ ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ ์ก๋ด์ด ์์ผ๋, ์ฑ
์ ์ฝ์ผ๋ฉฐ ์๊ฒฌ์ ๋๋๊ณ ์ถ์๋ถ์ด ๋ด์ฃผ์๋ฉด ์ข๊ฒ ์ต๋๋ค.
6.1 ์คํํ ๋ ๋ฉํธ๋ฆฌ ์๊ฐ
OpenTelemetry๋ ํ๋ง๋๋ก ์ ๋ฆฌํ์๋ฉด ๋ก๊ทธ, ๋ฉํธ๋ฆญ, ์ถ์ ์ ํ๋ฒ์ ์์งํ๋ ์์ด์ ํธ ์ญํ ์ ํ๋ค๊ณ ๋งํ ์ ์๋ค.
์ญ์ฌ
OpenTelemetry๋ Cloud Native Computing Foundation (CNCF) ํ๋ก์ ํธ๋ก, ์ด์ ์ ๋ ํ๋ก์ ํธ์ธ OpenTracing๊ณผ OpenCensus๊ฐ ํฉ๋ณํ์ฌ ๋ง๋ค์ด์ก๋ค.
OpenTracing, OpenCensus๋ ์ฝ๋๋ฅผ ๊ณ์ธกํ๊ณ ๊ด์ธก์ฑ ๋ฐฑ์๋๋ก ํ ๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๋ ํ์ค์ด ์์๊ธฐ ๋๋ฌธ์ ๋ ํ๋ก์ ํธ์ ํต์ฌ ๊ธฐ๋ฅ์ ํตํฉํ๊ณ ํ ๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ์ ์์ฑ,์์ง,์ ์ก ๋ฐฉ์์ ํ์คํํ๋๊ฒ์ ๋ชฉํ๋ก ํ๊ณ ์๋ค.
๐ OpenTelemetry Mission ๋ณด๋ฌ๊ฐ๊ธฐ
์ํคํ ์ณ
OpenTelemetry๋ ์ ๊ณํ์ค์ผ๋ก, CNCF๋ด์์๋ ํฐ ์ํฅ๋ ฅ์ ๋ฏธ์น๊ณ ์๋ค. (OpenTelemetry Venders)
OpenTelemetry๋ ๋ฐฑ์๋ ์์คํ ์ ๊ตฌํํ๋ ๊ฒ์ด ์๋๋ผ, ์ดํ๋ฆฌ์ผ์ด์ ์์ ๊ด์ธก ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ ๋ค์ํ ๋ฐฑ์๋ ์์คํ ์ผ๋ก ํ ๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๋ ๋ฐฉ๋ฒ์ ๋ํ ํ์ค์ ์ ๊ณตํ๋ค.
๋ชฉํ
OpenTelemetry๋ ์ถ์ ,์งํ, ๋ก๊ทธ ์๊ด ๊ด๊ณ๋ฅผ ์ฐ๊ฒฐํ๋๊ฒ์ด ์ฃผ ๋ชฉํ๋ค.
6.2 ์คํํ ๋ ๋ฉํธ๋ฆฌ ์ปดํฌ๋ํธ
์คํํ ๋ ๋ฉํธ๋ฆฌ์ ํต์ฌ ๊ฐ๋ ์ Signals(์ ํธ), Context Propagation(์ปจํ ์คํธ์ ํ) ๊ทธ๋ฆฌ๊ณ Pipeline(ํ์ดํ๋ผ์ธ)์ด๋ค.
OpenTelemetry
โโโ Signals
โ โโโ Trace
โ โโโ Metrics
โ โโโ Log
โ โโโ Baggage
โโโ Context Propagation
โโโ Pipeline
- Signals (์ ํธ): ์ถ์ , ๋ฉํธ๋ฆญ, ๋ก๊ทธ, ๋ฐฐ๊ธฐ์ง ๋ฑ์ ํ
๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ ์ ํ์ ๋ํ ๊ธฐ์ ์ ์คํ์ ์ ์ํ๋ค.
์ ํธ๋ ์ถ์ ,๋ฉํธ๋ฆญ,๋ก๊ทธ,๋ฐฐ๊ธฐ์ง๋ฅผ ํฌ๊ดํ๋ ๊ฐ๋ ์ด๋ค.- **Signals์์ ์ ์ํ๋๊ฒ**
- ์ ํธ์ ๋ํ ๊ฐ์ด๋๋ผ์ธ์ ์ ๊ณตํ๋ ์คํฉ
- ์ ํธ ํํ๋ฐฉ์์ ๋ํ๋ด๋ ๋ฐ์ดํฐ ๋ชจ๋ธ
- ์ดํ๋ฆฌ์ผ์ด์ ๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ๋ฐ์๊ฐ ์ฝ๋๋ฅผ ๊ณ์ธกํ๋๋ฐ ์ฌ์ฉํ ์ ์๋ API
- ์ฌ์ฉ์๊ฐ API๋ฅผ ์ฌ์ฉํ์ฌ ํ ๋ ๋ฉํธ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋๋ก ํ๋๋ฐ ํ์ํ SDK
- ์ฌ์ฉ์ ๋จ์ํ ํ๋ ๊ณ์ธก ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ๊ณ์ธก์ ๋จ์ํ ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์์ด์ ํธ
- **Signals์ ํฌํจ๋๋๊ฒ**
- Trace (์ถ์ ): ์์คํ ์์ฒญ ๋ฐ ํธ๋์ญ์ ์ ์ด๋ ์ ๋ณด
- Metrics (๋ฉํธ๋ฆญ): ์์คํ ์์น์ ์ฑ๋ฅ ์งํ
- Log (๋ก๊ทธ): ์ด๋ฒคํธ ๋ฉ์์ง
- Baggage (๋ฐฐ๊ธฐ์ง): ์๋น์ค ๊ฐ ์์ฒญ๊ณผ ํจ๊ป ์ ๋ฌ๋๋ ๋ฉํ๋ฐ์ดํฐ ์ปจํ ์คํธ ์ ๋ณด
- **Signals์์ ์ ์ํ๋๊ฒ**
- Context Propagation (์ฝํ ์คํธ ์ ํ): ์๋น์ค๋ ์์ฒญ ๊ฐ์ ์ปจํ ์คํธ ์ ๋ณด(์: ๋ณด์ ํ ํฐ, ์ฌ์ฉ์ ์ธ์ ์๋ณ์ ๋ฑ)๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ์ ์ํ๋ค. ์ ์คํธ๋ฆผ๊ณผ ๋ค์ด์คํธ๋ฆผ ์๋น์ค ๊ฐ์ ์ ๋ณด๊ฐ ์ผ๊ด๋๊ฒ ์ ์ง๋๋๋ก ๋ณด์ฅํ๋ค.
- Pipeline (ํ์ดํ๋ผ์ธ): ์์ง๋ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ ์ ์ ํ ๋ฐฑ์๋ ์์คํ (์: ๋ชจ๋ํฐ๋ง ๋๊ตฌ, ๋ถ์ ํ๋ซํผ ๋ฑ)์ผ๋ก ์ ์กํ๋ ๊ณผ์ ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ ์ํ๋ค.
6.2.1 Signals(์ ํธ) ๊ตฌ์ฑ์์
[1] ๋ฐ์ดํฐ ๋ชจ๋ธ
๋ฐ์ดํฐ ๋ชจ๋ธ์ ๋ฉํธ๋ฆญ, ์ถ์ , ๋ก๊ทธ์ ๋ํ ์์ธํ ๋ ์ด์์๊ณผ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๊ธฐ์ ํ๋ค. (OpenTelemetry Spec)
OpenTelemetry ๋ฐ์ดํฐ ๋ชจ๋ธ์ ๋ฉํธ๋ฆญ,์ถ์ ,๋ก๊ทธ๊ฐ์ ์๊ด๊ด๊ณ๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ ํ์คํ ๋ฉ์ธ์ง์ ๋ฐ์ดํฐ ํ์์ด๋ฉฐ, ๋ฒค๋ ์ค๋ฆฝ์ ์ผ๋ก ์ค๊ณ๋์๋ค. gRPC ํ๋กํ ์ฝ ๋ฒํผ์ ํธํ์ฑ์๋ ๋ฌธ์ ๊ฐ ์๋ค.
- Metrics: https://opentelemetry.io/docs/specs/otel/overview/#metric-signal
- ์ ๋ง๋ค์ด์ง ๋ฉํธ๋ฆญ ์๋ฃจ์ (์,ํ๋ก๋ฉํ ์ฐ์ค)์ด ๋ง์ด ์๋ค๋ ์ ์ ๊ฐ์ํ์ฌ, Opentelemetry๋ ๋ฉํธ๋ฆญ์ ๊ธฐ์กด ์๋ฃจ์ ์ ํตํฉํ๋๊ฒ์ ์ค์ ์ ๋๊ณ ์๋ค.
- prometheus, StatsD์ ์์ ํ ํธํ๋๋ค. (์ฐธ๊ณ )
- Logs: https://opentelemetry.io/docs/specs/otel/overview/#log-signal
- ๋ก๊ทธ๋ ๊ธฐ์กด ๋ก๊ทธ ์์คํ ๊ณผ์ ํธํ์ฑ์ ์ ์งํ๋ฉด์ ์ถ์ ์ ๋ณด์ ๊ฐ์ ํ ๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ํตํฉํ ์ ์๋๋ก ์ค๊ณํ๋ค.
- ๊ธฐ์กด ๋ก๊ทธ ๋ฉ์ธ์ง ํ์์ ์ถ์ ๋ฑ์ ์๊ด๊ด๊ณ ์ ๋ณด์ ํ ๋ ๋ฉํธ๋ฆฌ ์ ๋ณด๋ฅผ ์ถ๊ฐํ๋๊ฒ์ด ์ผ๋ฐ์ ์ธ ์คํํ ๋ ๋ฉํธ๋ฆฌ์ ๋ฐฉํฅ์ฑ์ด๋ค.
- Trace : https://opentelemetry.io/docs/specs/otel/overview/#tracing-signal
- Trace๋ ๊ธฐ์กด์ ๋ค์ํ ์ถ์ ํ์ค์ ์ ์งํ๋๊ฒ๋ณด๋ค๋ ์๋ก์ด ์คํํ ๋ ๋ฉํธ๋ฆฌ ์ถ์ ์ผ๋ก ํตํฉํ๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
- Trace์ ํต์ฌ์ Spen์ด๋ฉฐ, Spen๊ฐ์ ์๊ด๊ด๊ณ๋ฅผ ๋ํ๋ด๋๊ฒ์ด ํต์ฌ์ด๋ค.
- Baggage: https://opentelemetry.io/docs/specs/otel/overview/#baggage-signal
- ์์ฒญ์ ๋ฐ๋ผ ์ด๋ํ๋ ํค-๊ฐ ์์ ์งํฉ์ ์๋ฏธํ๋ฉฐ, Baggage๋ฅผ ํตํด์๋น์ค๊ฐ์ ์ํ์ ์ปจํ ์คํธ ์ ๋ณด๋ฅผ ์ ๋ฌํ๊ณ ์ ์งํ๋ค.
- ์๊ฒฉ ๋ถ์์ ์ฃผ์์ ๋ฌ๊ณ ๋ฉํธ๋ฆญ, ์ถ์ ๋ฐ ๋ก๊ทธ์ ์ปจํ ์คํธ ์ ๋ณด๋ฅผ ์ถ๊ฐํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
๊ฐ ์ ํธ๋ 4๊ฐ์ง ์ฝ์ด ์ปดํฌ๋ํธ๋ฅผ ํฌํจํ๊ณ ์๋ค.
- APIs: ํ ๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ(์ถ์ , ๋ฉํธ๋ฆญ, ๋ก๊ทธ)๋ฅผ ์์งํ๊ธฐ ์ํ ์ผ๋ จ์ ๊ท์น๊ณผ ๋ฉ์๋๋ฅผ ์ ๊ณตํจ
- SDKs: OpenTelemetry ํ๋ก์ ํธ์ ์ํด ์ ๊ณต๋๋ API์ ๊ตฌํ์ฒด, API์ ์ ์๋ ๋ช ์ธ๋ฅผ ์ค์ ๋ก ์คํํ๋ ์ฝ๋๋ฅผ ํฌํจํจ (SDK๋ API์ ์์กด์ )
- OpenTelemetry Protocol (OTLP)
- Collector
[2] API
- ์ฐธ๊ณ ๋งํฌ (OpenTelemetry API)
API์ SDK๊ฐ ์ดํด๋์ง ์์์, ๋งค์ฐ ํผ๋์ค๋ฌ์ ๋๋ฐ, ์ฝ๋ ์์ ๋ฅผ ๋ณด๋ฉด ์กฐ๊ธ์ด๋๋ง(?) ์ดํด๊ฐ ๊ฐ๋ฅํ๋ค.
API๋ ์ถ์ ,๋ฉํธ๋ฆญ,๋ก๊ทธ ๋ฑ์ ๋ฐ์ดํฐ ์์ง์ ์ํ ๊ท๊ฒฉ(๋ช
์ธ)๋ฅผ ์ ์ํ๋ค.
์ฆ, API๋ ํ
๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ท์น์ด๋ผ๊ณ ์๊ฐํ ์ ์๋ค.
# API๋ง ์ฌ์ฉํ๋ ์์
# ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ ์ฒ๋ฆฌํ๊ธฐ ์ํด์๋ SDK๊ฐ ํ์ํจ
from opentelemetry import trace
# API๋ฅผ ํตํด ํธ๋ ์ด์๋ฅผ ๊ฐ์ ธ์ด
tracer = trace.get_tracer(__name__)
# API๋ฅผ ์ฌ์ฉํ์ฌ ์ถ์ ์์
with tracer.start_as_current_span("api-only-span"):
print("This span is created using API only and won't be exported without an SDK.")
[3] SDK
SDK๋ API์คํ์ ๊ฐ์ง๊ณ ๊ฐ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ํ๊ฒฝ์์ ์ค์ ์์
์ ์ํํ๋ค.
์ฆ, SDK๋ API๋ช
์ธ์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ์์ง,์ฒ๋ฆฌ, ๋ด๋ณด๋ด๊ธฐ ๋ฑ์ ๊ตฌ์ฒด์ ์ธ ์ฝ๋๋ฅผ ํฌํจํ๊ฒ ๋๋ค.
์ ๋ฆฌํ์๋ฉด, API๋ ์ด๋ก ์ ์ธ ์ค๊ณ๋์ด๊ณ , SDK๋ ์ค๊ณ๋๋ฅผ ๋ฐํ์ผ๋ก ์ค์ ๊ฑด๋ฌผ์ ์ง๋ ๊ฑด์ถ์
์๋ผ๊ณ ๋น์ ํ ์ ์๋ค.
# API์ SDK๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ ์ฝ๋ ์์ (Console Spen Exporter SDK ์ฌ์ฉ)
# SDK๋ API๊ฐ ์ ๊ณตํ๋ ์ธํฐํ์ด์ค์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ ๋ด๋ณด๋ธ๋ค.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# SDK ์ค์ : ํธ๋ ์ด์ ์ ๊ณต์ ์ค์
trace.set_tracer_provider(TracerProvider())
# ์ฝ์ ๋ด๋ณด๋ด๊ธฐ ์ค์
span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
trace.get_tracer_provider().add_span_processor(span_processor)
# API์ SDK๋ฅผ ์ฌ์ฉํ์ฌ ์ถ์ ์์
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("api-and-sdk-span"):
print("This span is created using both API and SDK and will be exported to the console.")
API์ SDK๋ ์ดํดํ๊ธฐ ์ด๋ ต๊ฒ ์์ด๋ ๊ฒ ํด๋จ๋!!
์ด์ ๋ ์ ์ฐ์ฑ์ ์ ๊ณตํ๊ธฐ ์ํจ์ด๋ค. ๋์ผํ API๋ฅผ ์ฌ์ฉํ๋ฉด์ ๋ค์ํ SDK๋ฅผ ์ ํํ๊ฑฐ๋ ๊ต์ฒดํ ์ ์์ด, ํน์ ์คํํ๊ฒฝ ๋ฐ ์๊ตฌ์ฌํญ์ ๋ ์ ํฉํ SDK๋ฅผ ์ ํํ๊ฑฐ๋ ๊ต์ฒดํ ์ ์๋ค.
์ด ๊ตฌ์กฐ ๋๋ถ์ OpenTelemetry๋ ๋ค์ํ ํ๋ซํผ๊ณผ ์ธ์ด์์ ๋๋ฆฌ ์ฌ์ฉ๋ ์ ์๋๊ฒ์ด๋ค.
# ๊ฐ์ API๋ฅผ ์ฌ์ฉํ์ง๋ง, ๋ค๋ฅธ SDK๋ฅผ ์ฌ์ฉํ๋ ์์ (OTLP Span Exporter SDK์ฌ์ฉ)
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter
# SDK ์ค์ : ํธ๋ ์ด์ ์ ๊ณต์ ์ค์
trace.set_tracer_provider(TracerProvider())
# OTLP ๋ด๋ณด๋ด๊ธฐ ์ค์
otlp_exporter = OTLPSpanExporter(endpoint="localhost:4317", insecure=True)
span_processor = SimpleSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
# API์ SDK๋ฅผ ์ฌ์ฉํ์ฌ ์ถ์ ์์
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("api-and-sdk-span-otlp"):
print("This span is created using both API and SDK and will be exported via OTLP.")
[4] ๊ณ์ธก๋ผ์ด๋ธ๋ฌ๋ฆฌ (instrumentation libraries)
๊ณ์ธก๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์๋๊ณ์ธก๊ณผ ๊ฐ์ ์๋ฏธ๋ผ๊ณ ๋ณผ ์ ์๋ค.
์น ํ๋ ์์ํฌ(์: Flask, Django, Spring), ๋ฐ์ดํฐ๋ฒ ์ด์ค ํด๋ผ์ด์ธํธ(์: JDBC, Sequelize), RPC ๋ผ์ด๋ธ๋ฌ๋ฆฌ(์: gRPC, Thrift) ๋ฑ ์ ๋ํ ๊ณ์ธก๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๊ณ , ๊ฐ ์ธ์ด๋ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํด๋น ์ธ์ด์ ํน์ฑ๊ณผ ํ๊ฒฝ์ ๋ง๊ฒ ์ค๊ณ๋์ด์๋ค.
API๊ฐ๋ฐ ์์ด ์๋์ผ๋ก ๊ณ์ธก์ด ๊ฐ๋ฅํ๋๋ก ๋ฏธ๋ฆฌ ์ค๊ณ๋ OpenTelemetry ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ๊ฒ์ด๋ค.
https://opentelemetry.io/ecosystem/registry/ ์ด ๋งํฌ์์ ๊ณ์ธก๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ฐพ์๋ณผ ์ ์๋ค.
(์ง์ฒ๋ฅ ์ด ๋ค ๋ค๋ฅด๋ฏ๋ก ์ฐ๊ธฐ์ ์ ํ์ธํด๋ด์ผํจ)
์์๋ก, FastAPI๋ opentelemetry-instrumentation-fastapi๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
# opentelemetry-instrumentation-fastapi ๋ฅผ ์ฌ์ฉํ๊ธฐ ์์
from fastapi import FastAPI
from opentelemetry import trace
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter
app = FastAPI()
# ํธ๋ ์ด์ ์ ๊ณต์ ์ค์
trace.set_tracer_provider(TracerProvider())
# OTLP Exporter ์ค์
otlp_exporter = OTLPSpanExporter(endpoint="localhost:4317", insecure=True)
span_processor = SimpleSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
# FastAPI ์ฑ์ ๋ํ ๊ณ์ธก ์ค์
FastAPIInstrumentor.instrument_app(app)
@app.get("/")
async def hello():
return {"message": "Hello from FastAPI with OpenTelemetry!"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
# opentelemetry-instrumentation-fastapi ์์ด fastapi ๊ณ์ธกํ๊ธฐ
# ๋ฏธ๋ค์จ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ฑฐ๋ ๊ฒฝ๋ก์ฐ์ฐ์์ ์ง์ ์ถ์ ์ฝ๋ ์ถ๊ฐ (์ด ์์ ์์๋ ๋ฏธ๋ค์จ์ด ๊ธฐ๋ฅ ์ฌ์ฉ)
from fastapi import FastAPI, Request
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.exporter.otlp.trace_exporter import OTLPSpanExporter
app = FastAPI()
# ํธ๋ ์ด์ ์ ๊ณต์ ์ค์
trace.set_tracer_provider(TracerProvider())
# OTLP Exporter ์ค์
otlp_exporter = OTLPSpanExporter(endpoint="localhost:4317", insecure=True)
span_processor = SimpleSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
# ํธ๋ ์ด์ ๊ฐ์ ธ์ค๊ธฐ
tracer = trace.get_tracer(__name__)
# ๋ฏธ๋ค์จ์ด ์ถ๊ฐ
@app.middleware("http")
async def add_tracing(request: Request, call_next):
with tracer.start_as_current_span(f"HTTP {request.method} {request.url.path}"):
response = await call_next(request)
return response
@app.get("/")
async def hello():
return {"message": "Hello from FastAPI without automatic instrumentation!"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
๊ทธ๋ฅ ๋ณด๊ธฐ์๋ ๋น์ท๋น์ทํ๋ฐ..
์ง์ ๋ฏธ๋ค์จ์ด๋ฅผ ๊ตฌํํ๋๊ฒ๋ณด๋ค opentelemetry-instrumentation-fastapi ๋ฅผ ์ฌ์ฉํ๋๊ฒ ๋ฌด์จ ์ด์ ์ด ์์๊น?
- ๊ฐํธํ ํตํฉ: ์๋์ผ๋ก ๊ฐ ๊ฒฝ๋ก๋ ๋ฏธ๋ค์จ์ด๋ฅผ ์ค์ ํ ํ์ ์์ด ๋ฐ๋ก ์ฌ์ฉํ ํ์ ์๊ณ , ๊ณ์ธก๋ก์ง์ ์ ๊ฒฝ์ธ ํ์๊ฐ ์๋ค.
- ์ต์ ํ: ๊ณ์ธก ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํด๋น ํ๋ ์์ํฌ์ ๋ด๋ถ ๋์์ ๋ํ ๊น์ ์ดํด๋ฅผ ๋ฐํ์ผ๋ก ๊ฐ๋ฐ๋๋ค. ์ง์ ๊ฐ๋ฐํ๋๊ฒ๋ณด๋ค ํจ์จ์ ์ด๊ณ ์ฑ๋ฅ์ ๋ ์ํฅ์ ๋ฏธ์น๋ค. ๋ํ, ์๋ฌ ์ถ์ , ๋น๋๊ธฐ ์ง์ ๋ฑ์ ๋ํ ์ถ๊ฐ ๊ธฐ๋ฅ๋ ๊ฐํธํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
- ํ๋ฐํ ์ปค๋ฎค๋ํฐ: ์ ์ง๋ณด์๋ ์ ๋ฐ์ดํธ ์ธก๋ฉด์์๋ ์ข๋ค. ์ง์์ ์ผ๋ก ์ ๋ฐ์ดํธ ๋๊ณ ์ ์ง๋ณด์ ๋๊ธฐ๋๋ฌธ์ด๋ค. OpenTelemetry ์์ฒด์ ๋ณํ์ ๋ฐ๋ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ ๋ฐ์ดํธ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
[5] ๋ฆฌ์์ค (Resources)
- ์ฐธ๊ณ : OpenTelemetry Resources
ํ
๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ ์ํฐํฐ(์: ์ ํ๋ฆฌ์ผ์ด์
, ์๋ฒ, ์๋น์ค)๋ฅผ ์ค๋ช
ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋งํ๋ค.
ํน์ ์ํฐํฐ์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ฌ, ๋ฆฌ์์ค๋ฅผ ์ฝ๊ฒ ์๋ณํ๊ณ , ๊ด๋ฆฌํ๋ฉฐ, ํํฐ๋งํ ์ ์๋๋ก ํ๋ค. ๋น์ ํ์๋ฉด, AWS ์ Resource Tag, K8s์ Metadata ๊ฐ์ ์ญํ ์ด๋ค.
OpenTelemetry๋ ์ถ์ ์ ์ด๊ธฐํํ๊ธฐ ์ํด TracerProvider, ๋ฉํธ๋ฆญ์ ์ด๊ธฐํ ํ๊ธฐ ์ํด MetricProvider๋ฅผ ์ฌ์ฉํ๋ค.
๊ฐ Provider ์์ฑ ์์ ์ ๋ฆฌ์์ค๋ ์์ฑํ๋ฉฐ, Exporter์์ ๋ฆฌ์์ค๋ฅผ ์ฐธ๊ณ ํ๋ค.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# ๋ฆฌ์์ค ์์ฑ
resource = Resource.create({
"service.name": "ExampleService",
"service.version": "1.0.0",
"host.name": "example-host"
})
# ํธ๋ ์ด์ ์ ๊ณต์์ ๋ฆฌ์์ค ์ค์
trace.set_tracer_provider(TracerProvider(resource=resource))
# ์ถ์ ์ค์
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("example-operation"):
print("This operation is associated with a resource.")
[5-์ถ๊ฐ] ์ดํธ๋ฆฌ๋ทฐํธ (attributes)
์ฝ๋๋ฅผ ํ์ธํ๋ค๋ณด๋, ํ๊ทธ์ฒ๋ผ ์ฌ์ฉํ ์ ์๋๊ฒ ๋ฆฌ์์ค ์ธ์๋ ์ดํธ๋ฆฌ๋ทฐํธ๋ผ๋๊ฒ ์๋๊ฑธ ์๊ฒ๋์๋ค.
๋ฌด์์ด ๋ค๋ฅธ๊ฑด์ง ํ์ธํ๊ณ ๋์ด๊ฐ๋ณด์
- ์ดํธ๋ฆฌ๋ทฐํธ(Attributes)
- ๋ชฉ์ : ์ดํธ๋ฆฌ๋ทฐํธ๋ ๊ฐ๋ณ ์คํฌ(์ถ์ ๋ฐ์ดํฐ์ ๊ธฐ๋ณธ ๋จ์)์ ์ง์ ์ฐ๊ฒฐ๋๋ฉฐ, ๊ทธ ์คํฌ์ ์์ ์ ๋ ๊ตฌ์ฒด์ ์ผ๋ก ์ค๋ช ํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค. ์๋ฅผ ๋ค์ด, HTTP ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์คํฌ์๋ ์์ฒญ ๋ฉ์๋, URL, ์ํ ์ฝ๋์ ๊ฐ์ ์ ๋ณด๊ฐ ์ดํธ๋ฆฌ๋ทฐํธ๋ก ์ถ๊ฐ๋ ์ ์๋ค.
- ์ ์ฉ ๋ฒ์: ์ดํธ๋ฆฌ๋ทฐํธ๋ ํน์ ์คํฌ์ ๊ตญํ๋์ด ์ฌ์ฉ๋๋ฉฐ, ์คํฌ๋ง๋ค ๋ค๋ฅผ ์ ์๋ค. ์ด๋ ๋์ ์ผ๋ก ๋ณํ ์ ์๋ ์ ๋ณด๋ฅผ ํฌํจํ๋ฉฐ, ์คํฌ์ ์๋ช ์ฃผ๊ธฐ ๋์์๋ง ์ ํจํ๋ค.
- ๋ฆฌ์์ค(Resources)
- ๋ชฉ์ : ๋ฆฌ์์ค๋ ์ถ์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ ์ํฐํฐ(์: ์ ํ๋ฆฌ์ผ์ด์ , ์๋ฒ, ์๋น์ค)์ ๋ํ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค. ์ด๋ ์ถ์ ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ ํ๊ฒฝ์ ๋ํ ์ ์ ์ธ ์ ๋ณด๋ฅผ ํฌํจํ๋ฉฐ, ํ ๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ ์ ์ฒด์ ์ผ๊ด๋๊ฒ ์ ์ฉ๋๋ค.
- ์ ์ฉ ๋ฒ์: ๋ฆฌ์์ค๋ ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋๋ ๋ฉํธ๋ฆญ ํ๋ก๋ฐ์ด๋์ ์ฐ๊ฒฐ๋์ด, ํด๋น ํ๋ก๋ฐ์ด๋๋ฅผ ์ฌ์ฉํด ์์ฑ๋ ๋ชจ๋ ์คํฌ์ด๋ ๋ฉํธ๋ฆญ์ ๊ณตํต์ ์ผ๋ก ์ ์ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํ๋์ ์๋น์ค ์ด๋ฆ, ์๋น์ค ๋ฒ์ , ํธ์คํธ ์ด๋ฆ ๋ฑ์ด ๋ชจ๋ ์คํฌ์ ๊ฑธ์ณ ์ผ๊ด์ ์ผ๋ก ํํ๋์ด์ผ ํ ์ ๋ณด๋ค.
[6] ๋ฐฐ๊ธฐ์ง (Baggage)
- ๋งํฌ: https://opentelemetry.io/docs/concepts/signals/baggage/
๋ฐฐ๊ธฐ์ง๋ ์ถ์ ์์ ์ฌ์ฉ๋๋ ์ฌ์ฉ์๊ฐ ์ ์ ๊ฐ๋ฅํ ํค-๊ฐ ์ ํ์์ ๋ฉํ๋ฐ์ดํฐ ์ด๋ค.
from opentelemetry import trace
from opentelemetry import baggage
# ํธ๋ ์ด์์ ๋ฐฐ๊ธฐ์ง ์ด๊ธฐํ
tracer = trace.get_tracer(__name__)
# ์ฌ์ฉ์ ์ธ์
์ ๋ณด๋ฅผ ๋ฐฐ๊ธฐ์ง์ ์ถ๊ฐ
baggage.set_baggage("user.session_id", "session_12345")
baggage.set_baggage("user.preferred_language", "en-US")
# ๋ฐฐ๊ธฐ์ง๋ฅผ ํ์ฉํ ์ถ์ ์์
with tracer.start_as_current_span("example-operation") as span:
# ๋ฐฐ๊ธฐ์ง์์ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํ์ฌ ๋ก๊ทธ์ ๊ธฐ๋ก
session_id = baggage.get_baggage("user.session_id")
language = baggage.get_baggage("user.preferred_language")
span.set_attribute("user.session_id", session_id)
span.set_attribute("user.language", language)
print(f"Operating in session {session_id} with language setting {language}")
๋ฐฐ๊ธฐ์ง๋ฅผ ์ฌ์ฉํ๋ ๋ชฉ์ ์ ๋ถ์ฐ ์์คํ
์์ ์๋น์ค ๊ฐ ์์ฒญ์ ์ฒ๋ฆฌํ ๋ ์ค์ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ณ ์ ์งํ๋ ๊ฒ์ด๋ค.
์ ์ฒด ํธ๋์ ์
์ ๋งฅ๋ฝ์ ์ ์งํ๋ฉด์ ๊ฐ ์๋น์ค๊ฐ ํ์ํ ์ ๋ณด์ ์ ๊ทผํ ์์๋๋ก ํ๋ค.
- ํ์์ฑ
- ๋ฐฐ๊ธฐ์ง๋ ์ฝํ ์คํธ ๊ฐ์ ํต์ผ๋ ํ์๊ณผ ํจํด์ผ๋ก ์ ๊ณตํ์ฌ, ๋ชจ๋ ์๋น์ค๊ฐ ๋์ผํ ์ ๋ณด๋ฅผ ๊ณต์ ํ๊ณ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ค.
- ์ธ์ด๋ ํ๋ซํผ์ ๊ด๊ณ์์ด, ๋ชจ๋ ์์ฉ ํ๋ก๊ทธ๋จ์ด ๋ฐฐ๊ธฐ์ง๋ฅผ ์ฝ๊ณ ๊ตฌ๋ฌธ ๋ถ์ํ ์ ์์ด, ๋ค์ํ ๊ธฐ์ ์คํ์ ์ฌ์ฉํ๋ ๋๊ท๋ชจ ๋ถ์ฐ ์์คํ ์์๋ ํตํฉ์ฑ์ ์ ์งํ ์ ์๋ค.
- ๋๊ท๋ชจ ๋ถ์ฐ์์คํ ์ ๊ตฌ์ถํ๊ณ ํ์ด ์ํ๋ ์ธ์ด๋ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ์์จ์ฑ์ ์ ๊ณตํ๋ ค๋ ๊ฒฝ์ฐ์ ์ ์ฉํ๋ค.
- ํ์ฉ๋ฒ
- ์ธ๋ถ์ ์ ์ฌ์ ์ผ๋ก ๋ ธ์ถํด๋ ์๊ด์๋ ๋ฏผ๊ฐํ์ง ์๋ ๋ฐ์ดํฐ์ ์ฌ์ฉํ๋ค. (์, ๊ณ์ ID, ์ฌ์ฉ์ ID, ์ ํ ID, ์๋ณธ IP๋ฑ)
- ์์ ์คํ์์๋ง ์์ธ์ค ํ ์ ์๋ ์ ๋ณด๊ฐ ์๋ค๋ฉด ํ์ ์คํ์ผ๋ก ์ ๋ฌํ๊ธฐ ์ํด์ ๋ฐฐ๊ธฐ์ง์ ์ ์ํ๊ณ ๋ค์ด์คํธ๋ฆผ ์๋น์ค์ ์คํฌ์ ์ ํํ ์ ์๋ค.
- ๊ด์ธก๊ฐ๋ฅ์ฑ ๋ฐฑ์๋์์๋ ๋ฐฐ๊ธฐ์ง๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณด๋ค ์ฌ์ด ๊ฒ์๊ณผ ํํฐ๋ง์ด ๊ฐ๋ฅํ๋ค.
- ์ฃผ์์ฌํญ
- ๋ฐฐ๊ธฐ์ง๋ ๋ถ์ฐ ์์คํ ๋ด ๋ชจ๋ ์๋น์ค์ ์ ๋ฌ๋๊ธฐ ๋๋ฌธ์, ๋ฏผ๊ฐํ ์ ๋ณด๋ ๋ฐฐ๊ธฐ์ง๋ฅผ ํตํด ์ ์กํ์ง ์๋๋ก ํด์ผ ํ๋ค.
- ๊ฐ ์์คํ ๋ง๋ค (์, fastapi, spring, rails๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด ๊ฐ๊ฐ) ๋์ผํ key-value ๋ฅผ ๊ฐ์ง ๋ฐฐ๊ธฐ์ง๋ฅผ ์ค์ ํด์ฃผ์ด์ผ ํ๋ค.
[7] ์ด๋ฒคํธ
์ด๋ฒคํธ(Event) ๋ ์ถ์ (Trace) ์ค์ ํน์ ์คํฌ(Span)๊ณผ ์ฐ๊ด๋ ์๊ฐ์ ๋ฏผ๊ฐํ ์ด๋ฒคํธ๋ฅผ ๋ํ๋ธ๋ค.์ด๋ฒคํธ๋ ์คํฌ ๋ด์์ ํน์ ์๊ฐ์ ๋ฐ์ํ๋ ์ฌ๊ฑด์ ๊ธฐ๋กํ์ฌ ์ถ์ ๋ฐ์ดํฐ์ ์ถ๊ฐ์ ์ธ ์ ๋ณด์ ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํ๋ ๋ฐ ์ฌ์ฉํ๋ค.
๊ธฐ๋ก๋ ์ด๋ฒคํธ๋ค์ ์คํฌ(Span)๊ณผ ํจ๊ป ์์ง๋์ด ์ถ์ ๋ฐ์ดํฐ์ ์ผ๋ถ๋ก ๊ด์ธก ๊ฐ๋ฅ์ฑ ๋ฐฑ์๋ ์์คํ
์ ์ ์ก๋๋ค.
์คํฌ์ ์๋ช
์ฃผ๊ธฐ ๋์ ๋ฐ์ํ๋ ์ค์ํ ์๊ฐ๋ค์ ํฌ์ฐฉํ์ฌ ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ฏ๋ก, ์ด๋ฅผ ์์งํ๊ณ ์ ์ฅํ๋ ๊ฒ์ ์์คํ
์ ํ๋์ ๋์ฑ ์ ์ดํดํ๊ณ ๋ฌธ์ ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํด๊ฒฐํ๋ ๋ฐ ์ค์ํ๋ค. (์๋ฌ๋ชจ๋ํฐ๋ง, ์ฑ๋ฅ๋ถ์, ์ฌ์ฉ์ ํ๋๋ถ์๋ฑ์ ์ฐ์ผ ์ ์์)
from fastapi import FastAPI
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
app = FastAPI()
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
# /๋ฅผ ์์ฒญํ๋ฉด "Hello, World!"๋ฅผ ๋ฐํํ๋ฉฐ, ์์ฒญ์ ๋ฐ์๋์ ์๋ต์ ๋ณด๋ผ๋ ์ด๋ฒคํธ์ ๊ธฐ๋ก
@app.get("/")
async def hello():
with tracer.start_as_current_span("hello_request") as span:
span.add_event("Received request", {"path": "/"})
response = "Hello, World!"
span.add_event("Sending response", {"response": response})
return response
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
[8] ๋งํฌ
๋งํฌ(Link) ๋ ์ฌ๋ฌ ์คํฌ(Span) ์ฌ์ด์ ๊ด๊ณ๋ฅผ ๋ํ๋ด๋ ๊ตฌ์กฐ๋ค.
์คํฌ๊ฐ์ ๊ด๊ณ๋ฅผ ํํํ๋ฉฐ, ์คํฌ์ ๋ค๋ฅธ ์คํฌ์ ์ฐ๊ฒฐํ๋ ์คํฌ ๋งํฌ๋ฅผ ์์ฑํ ์ ์๋ค. ์ฐ๊ฒฐ์ ์คํฌ๋ค์ด ์๋ก ๋ค๋ฅธ ์ถ์ ์ ์ํ๊ฑฐ๋ ๋์ผ ์ถ์ ์ ์ํ๋ฉด์๋ ๋ณต์กํ ์ํธ ์์ฉ์ ๊ฐ์ง ๋ ์ ์ฉํ๋ค.
- ์ฌ์ฉ์ฌ๋ก
- ๋น๋๊ธฐ ์์
- ๋ฐฐ์น์ฒ๋ฆฌ
- ๋ณต์กํ ์์กด์ฑ
๋งํฌ๋ฅผ ๋ง๋ค๊ธฐ ์ํด์๋ ์คํฌ ์ฝํ ์คํธ๊ฐ ํ์ํ๋ค.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ด๊ธฐํ
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
# ์ฒซ ๋ฒ์งธ ์คํฌ ์์ฑ
with tracer.start_as_current_span("first_operation") as first_span:
# ์ฒซ ๋ฒ์งธ ์์
์ ์ํ
# ๋ ๋ฒ์งธ ์คํฌ ์์ฑ, ์ฒซ ๋ฒ์งธ ์คํฌ๊ณผ ๋งํฌ๋ฅผ ์์ฑํ์ฌ
with tracer.start_as_current_span("second_operation", links=[trace.Link(first_span.get_span_context())]) as second_span:
# ๋ ๋ฒ์งธ ์์
์ ์ํ
pass
# ์ฒซ ๋ฒ์งธ ์คํฌ๊ณผ๋ ๋
๋ฆฝ์ ์ผ๋ก ์ธ ๋ฒ์งธ ์คํฌ์ ์์ฑํ๋ ์ฒซ ๋ฒ์งธ ์คํฌ๊ณผ ๋งํฌ
with tracer.start_as_current_span("third_operation", links=[trace.Link(first_span.get_span_context())]) as third_span:
# ์ธ ๋ฒ์งธ ์์
์ ์ํ
pass
6.2.2 Context Propagation (์ฝํ ์คํธ ์ ํ)
- ์ฐธ๊ณ : https://opentelemetry.io/docs/concepts/context-propagation/
์ปจํ ์คํธ ์ ํ(Context Propagation) ๋ ๋ถ์ฐ ์์คํ ๋ด์์ ์ถ์ (Trace) ๋ฐ์ดํฐ๋ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์๋น์ค ๊ฐ์ ์ ๋ฌํ๋ ๋ฉ์ปค๋์ฆ์ด๋ค.
์ปจํ
์คํธ ์ ํ๋ฅผ ํตํด ์์ฒญ์ด ๋ค์ํ ์๋น์ค๋ฅผ ๊ฑฐ์น๋ฉด์๋ ์ฐ๊ด๋ ์ถ์ ์ ๋ณด(์: ์คํฌ ID, ์ถ์ ID)์ ๋ฉํ๋ฐ์ดํฐ(์: Baggage)๋ฅผ ์ ์งํ๊ณ ๊ด๋ฆฌํ ์ ์๋ค.
์ถ์ ์๋ง ๊ตญํ๋์ง๋ ์์ง๋ง, ์ถ์ ์ ํตํด ํ๋ก์ธ์ค ๋ฐ ๋คํธ์ํฌ ๊ฒฝ๊ณ์ ์์๋ก ๋ถ์ฐ๋ ์๋น์ค ์ ๋ฐ์ ๊ฑธ์ณ ์์คํ
์ ๋ํ ์ธ๊ณผ์ ๋ณด๋ฅผ ๊ตฌ์ถํ ์ ์๋ค.
์ฝํ ์คํธ ์ ํ์๋ ๋๊ฐ์ง ํต์ฌ ๊ฐ๋ ์ด ์๋ค.
Context
- ์ฐธ๊ณ : Context
์ปจํ ์คํธ๋ ์ถ์ ์ ๋ณด(์: ์ถ์ ID, ์คํฌ ID)์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ ๊ฐ์ฒด๋ก, ์๋น์ค ๊ฐ ์์ฒญ์ ์ฐ๊ด์ฑ์ ํ์ ํ๊ณ ์ถ์ ํ๋ ๋ฐ ํ์ํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ค.
Propagation
์ ํ๋ ์๋น์ค๋ ํ๋ก์ธ์ค ๊ฐ์ ์ปจํ
์คํธ๋ฅผ ์ด๋์ํค๋ ๋ฉ์ปค๋์ฆ์ ์๋ฏธํ๋ค.
์ปจํ
์คํธ ๊ฐ์ฒด๋ ์ง๋ ฌํ(serialize)๋๊ฑฐ๋ ์ญ์ง๋ ฌํ(deserialize)๋์ด, ํ์ํ ์ถ์ ์ ๋ณด๊ฐ ๋ค์ ์๋น์ค๋ก ์ ๋ฌ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ด ์์
์ OpenTelemetry์ ๊ฐ์ ๊ณ์ธก ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํด ์๋์ผ๋ก ์ฒ๋ฆฌ๋๋ฉฐ, ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ด์ฌํ ํ์๋ ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก W3C์ TraceContext ๋ช ์ธ๋ฅผ ๋ฐ๋ฅด๋ ํค๋๋ฅผ ์ฌ์ฉํ์ฌ ์ปจํ ์คํธ๋ฅผ ์ ํํ๋ค.
OpenTelemetry๋ traceparent, tracestate ํค๋๋ฅผ ์ฌ์ฉํ์ฌ ์๋น์ค ๊ฐ์ ์ ํ๋๋ค.
# traceparent ํค๋
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
[1] [2] [3] [4]
- version: traceparent ํค๋์ ๋ฒ์
- TraceID: ์ ์ฒด ์ถ์ ์ ๊ณ ์ ํ๊ฒ ์๋ณํ๋ 16๋ฐ์ดํธ ๊ธธ์ด์ ์๋ณ์
- Perent Spen ID: ํ์ฌ ์คํฌ์ ๋ถ๋ชจ ์คํฌ์ ์๋ณํ๋ 8๋ฐ์ดํธ ๊ธธ์ด์ ์๋ณ์
- Trace Flag: ์ถ์ ๊ณผ ๊ด๋ จ๋ ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ 1๋ฐ์ดํธ ๊ธธ์ด์ ํ๋๊ทธ (์ํ๋ง ์ฌ๋ถ, "01" ์ํ๋ง ํ์ฑํ)
# tracestate ํค๋
tracestate: congo=t61rcWkgMzE,rojo=00f067aa0ba902b7
[key]=[value] ,[key]=[value]
Tracestate ํค๋์๋ Traceparent ํค๋์ ํจ๊ป ์ถ๊ฐ ์๋ณ์๋ฅผ ์ ํํ ์ ์๋ ์์ ๋ฐ์ดํฐ์ ํค-๊ฐ ์์ด ํฌํจ๋๋ค.
์์์ ์ธ๊ธํ Baggage๋ ์ฝ๊ฐ ํท๊ฐ๋ฆฌ๋๋ฐ, ์ญํ ๊ณผ ๋ชฉ์ ์ด ๋ค๋ฅด๋ค.
- Tracestate:
- traceparent ํค๋์ ํจ๊ป ์ถ์ ์ปจํ ์คํธ๋ฅผ ์ ํํ๋ ๋ฐ ์ฌ์ฉ
- ์ถ์ ์์คํ ์ด ํ์๋กํ๋ ๊ธฐ์ ์ , ์ด์์ ๋ฉํ๋ฐ์ดํฐ์ ํ
- Baggage:
- ์ฌ์ฉ์ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ญ์ ์ผ๋ก ์ ํํ๋ ๋ฐ ์ฌ์ฉ
- ์ ํ๋ฆฌ์ผ์ด์ ์์ค์ ์๋ฏธ์๋ ๋น์ฆ๋์ค/์ด์ ๋ฐ์ดํฐ ์ ํ
6.2.3 Pipeline (ํ์ดํ๋ผ์ธ)
Pipeline
ํ์ดํ๋ผ์ธ(Pipeline) ์ ๋ฐ์ดํฐ ์์ง, ์ฒ๋ฆฌ ๋ฐ ์ ์ก์ ํ๋ฆ์ ์ค๋ช ํ๋ ๊ฐ๋ ์ด๋ฉฐ, ํ ๋ ๋ฉํธ๋ฆฌ ์ ํธ(์ถ์ ,๋ฉํธ๋ฆญ,๋ก๊ทธ)๋ฅผ ์์ง, ๋ณํ, ์์ถํ๋ ๊ณผ์ ์ ํฌํจํ๋ค.
์ดํดํ๊ธฐ ์ด๋ ค์์ ์ฝ๋์์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ํ์ธํ๋ฉด ์ข์๊ฒ๊ฐ๋ค.
from fastapi import FastAPI
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
app = FastAPI()
# Provider: TracerProvider ์ค์
trace.set_tracer_provider(TracerProvider())
# Exporter: ์ถ์ ๋ฐ์ดํฐ ์ฝ์๋ก ์ถ๋ ฅ
exporter = ConsoleSpanExporter()
# Processor: SimpleSpanProcessor๋ฅผ ์ฌ์ฉํ์ฌ ์คํฌ ๋ฐ์ดํฐ๋ฅผ ์ฆ์ Exporter์ ๋ณด๋
processor = SimpleSpanProcessor(exporter)
trace.get_tracer_provider().add_span_processor(processor)
# Telemetry Generator: FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์๋์ผ๋ก ์ถ์ ํ๋๋ก ์ค์
FastAPIInstrumentor.instrument_app(app)
# ๊ธฐ๋ณธ ๋ฃจํธ ๊ฒฝ๋ก: ๊ฐ๋จํ HTTP GET ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ์ถ์
@app.get("/")
async def read_root():
tracer = trace.get_tracer(__name__)
# Telemetry Generator: API ์์ฒญ์ ์ถ์ ํฉ๋๋ค.
with tracer.start_as_current_span("read_root"):
return {"Hello": "World"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
- Provider (ํ๋ก๋ฐ์ด๋)
- ํ ๋ ๋ฉํธ๋ฆฌ ํ์ดํ๋ผ์ธ์ ์์์ ์ Provider๋ค.
- SDK์ ์ด๊ธฐ ์ค์ ๋จ๊ณ์์ ํธ๋ ์ด์๋ ๋ฏธํฐ๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, ๋ฐ์ดํฐ ์์ง์ ์์์ ์ญํ ์ ํ๋ค.
- TracerProvider๋ฅผ ์ฌ์ฉํ์ฌ ์ ํธ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ด๊ธฐํํ๋ค.
- ์ถ์ (TracerProvider), ๋ฉํธ๋ฆญ(MeterProvider), ๋ก๊ทธ (LoggerProvider) ๋ฑ์ ํ๋ก๋ฐ์ด๋๊ฐ ์๋ค.
- Telemetry Generator (ํ
๋ ๋ฉํธ๋ฆฌ ์์ฑ๊ธฐ)
- ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋์์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ ์ญํ ์ ํ๋ค.
- SDK๊ฐ ์ค์น๋ ํ๊ฒฝ์์ ์คํ๋์ด ์ฌ์ฉ์์ ์์ฒญ์ ์ถ์ ํ๊ฑฐ๋ ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ค.
- Processor (ํ๋ก์ธ์)
- ์์ง๋ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ์ปดํฌ๋ํธ๋ก, ๋ฐ์ดํฐ ํํฐ๋ง, ์ํ๋ง, ๋ณํ ๋ฑ์ ์ํํ ์ ์๋ค.
- ๋ฐ์ดํฐ๋ฅผ ์์ถํ๊ธฐ ์ ์ ํ์ํ ํ์์ผ๋ก ์กฐ์ ํ๋ ๋จ๊ณ๋ค.
- Exporter (์ต์คํฌํฐ)
- ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ ์ต์ข ์ ์ผ๋ก ์ธ๋ถ ์์คํ (์: ๋ชจ๋ํฐ๋ง ๋๊ตฌ, ๋ถ์ ์๋น์ค)์ผ๋ก ์ ์กํ๋ ์ญํ ์ ํ๋ค.
- ๋ค์ํ ํ์ ์ ์ต์คํฌํฐ๊ฐ ์กด์ฌํ๋ฉฐ, ๊ฐ๊ฐ ํน์ ๋ฐฑ์๋ ์์คํ ์ ์ต์ ํ๋์ด ์๋ค.
Collector
- ์ฐธ๊ณ ๋งํฌ: https://opentelemetry.io/docs/collector/
Pipeline์ ๋ณด๋ค๋ณด๋, ๋น์ทํ ๊ฐ๋ ์ธ Collector์ ์ฝ๊ฐ ํผ๋๋์๋ค.
์์์ ์ค๋ช
ํ๊ณ ์๋ ๋ค๊ฐ์ง ์์ Provider, Generator, Processer, Exporter๋ OpenTelemetry์ ํ
๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑ ์์์ด๋ฉฐ, SDK๋ด์์ ๊ตฌํ๋๋ค.
์ฆ, Pipeline์ SDK์์ ๊ตฌํ๋๋ฉฐ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋ ๋ด์ ์ง์ ํตํฉ๋์ด ๋ฐ์ดํฐ์ ์์ง๊ณผ ์ฒ๋ฆฌ ์์ถ์ ์ฒ๋ฆฌํ๋ค.
๋ฐ๋ฉด์, OpenTelemetry Collector๋ ์ด๋ฌํ ํ ๋ ๋ฉํธ๋ฆฌ ํ์ดํ๋ผ์ธ์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ถ๋ฆฌํ์ฌ, ๋ ๋ฆฝ์ ์ธ ์๋น์ค๋ ์์ด์ ํธ ํํ๋ก ๋ฐฐํฌํ ์ ์๊ฒ ํด์ฃผ๋ ๋ณ๋์ ๊ตฌ์ฑ ์์์ด๋ค.
Collector๋ ๋คํธ์ํฌ๋ฅผ ํตํด ๋ค์ํ ์์ค๋ก๋ถํฐ ํ ๋ ๋ฉํธ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ , ์ด๋ฅผ ์ฒ๋ฆฌํ ํ ๋ค์ํ ๋ฐฑ์๋ ์์คํ ์ผ๋ก ์ ์กํ๋ ์ญํ ์ ํ๋ค. (์ค์น๋ ๋์ปค, ์ฟ ๋ฒ๋คํฐ์ค, Linux apk rpm ๋ฑ๋ฑ ์ฌ๋ฌ ์ต์ ์ ์ ๊ณตํ๋ค.(์ฐธ๊ณ ))
6.3 ์ถ์
6.3.1 ์คํํ ๋ ๋ฉํธ๋ฆฌ ์ถ์ ์๊ฐ
์ถ์ (Trace)๋ ์ฌ์ฉ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์ฒญ์ ํ ๋ ์ด๋ค์ผ์ด ๋ฐ์ํ๋์ง์ ๋ํ ํฐ ๊ทธ๋ฆผ์ ์ ๊ณตํ๋ค.
์ํ Trace ์ฝ๋
์๋ ์ถ์ ์์ ๋ฅผ ํตํด ์ด๋ป๊ฒ ์ถ์ ํ๋์ง ํ์ธํด๋ณด์.
pip install opentelemetry-sdk opentelemetry-api
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ด๊ธฐํ
tracer_provider = TracerProvider()
# ์ฝ์ ์ต์คํฌํฐ ์ค์
exporter = ConsoleSpanExporter()
processor = SimpleSpanProcessor(exporter)
tracer_provider.add_span_processor(processor)
# ์ ์ญ ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ค์
trace.set_tracer_provider(tracer_provider)
# ํธ๋ ์ด์ ์ป๊ธฐ
tracer = trace.get_tracer(__name__)
# ์ค์ฒฉ๋ ์คํฌ ์์ฑ
with tracer.start_as_current_span("Red") as span_red:
# 'Red' ์คํฌ ์์
with tracer.start_as_current_span("Green") as span_green:
# 'Green' ์คํฌ ์์
with tracer.start_as_current_span("Blue") as span_blue:
# 'Blue' ์คํฌ ์์
print("ํ
์คํธ")
์ด๊ฑธ ์คํ์ํค๋ฉด JSON ํ์์ ์ถ๋ ฅ์ด ๋์จ๋ค. ๊ฐ ํญ๋ชฉ์ ํ์ธํด๋ณด์.
# ์ถ๋ ฅ ๊ฒฐ๊ณผ
ํ
์คํธ
{
"name": "Blue",
"context": {
"trace_id": "0x7ed659dfc0ffd4525411421dd32c5b0d",
"span_id": "0x892c5d277b377e8b",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0x95bfd1111d35c3d1",
"start_time": "2024-04-14T13:04:30.679814Z",
"end_time": "2024-04-14T13:04:30.679839Z",
"status": {
"status_code": "UNSET"
},
"attributes": {},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
{
"name": "Green",
"context": {
"trace_id": "0x7ed659dfc0ffd4525411421dd32c5b0d",
"span_id": "0x95bfd1111d35c3d1",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0x4b539330e3f8385e",
"start_time": "2024-04-14T13:04:30.679798Z",
"end_time": "2024-04-14T13:04:30.680267Z",
"status": {
"status_code": "UNSET"
},
"attributes": {},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
{
"name": "Red",
"context": {
"trace_id": "0x7ed659dfc0ffd4525411421dd32c5b0d",
"span_id": "0x4b539330e3f8385e",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": null,
"start_time": "2024-04-14T13:04:30.679770Z",
"end_time": "2024-04-14T13:04:30.680328Z",
"status": {
"status_code": "UNSET"
},
"attributes": {},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
์ํ Trace ์ฝ๋ + Attributes
Attribute๋ ์คํฌ์ ๋ํ ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค. (ํ๊ทธ์ ๋น์ท)
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ด๊ธฐํ
tracer_provider = TracerProvider()
# ์ฝ์ ์ต์คํฌํฐ ์ค์
exporter = ConsoleSpanExporter()
processor = SimpleSpanProcessor(exporter)
tracer_provider.add_span_processor(processor)
# ์ ์ญ ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ค์
trace.set_tracer_provider(tracer_provider)
# ํธ๋ ์ด์ ์ป๊ธฐ
tracer = trace.get_tracer(__name__)
# ์ค์ฒฉ๋ ์คํฌ ์์ฑ
with tracer.start_as_current_span("Red", attributes={"color": "red"}) as span_red:
# 'Red' ์คํฌ ์์
with tracer.start_as_current_span("Green", attributes={"color": "green"}) as span_green:
# 'Green' ์คํฌ ์์
with tracer.start_as_current_span("Blue", attributes={"color": "blue"}) as span_blue:
# 'Blue' ์คํฌ ์์
print("ํ
์คํธ")
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค. ์ถ๊ฐ ์ ๋ณด๊ฐ attributes์ ์ถ๊ฐ๋์๋ค.
ํ
์คํธ
{
"name": "Blue",
"context": {
"trace_id": "0x02eb6338a1f40daf7230e2df981eabf0",
"span_id": "0xb7518ad715b93ed0",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0x88769b3b31af6642",
"start_time": "2024-04-14T13:12:18.444421Z",
"end_time": "2024-04-14T13:12:18.444444Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "blue"
},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
{
"name": "Green",
"context": {
"trace_id": "0x02eb6338a1f40daf7230e2df981eabf0",
"span_id": "0x88769b3b31af6642",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0xedc13ebcf868ffe4",
"start_time": "2024-04-14T13:12:18.444405Z",
"end_time": "2024-04-14T13:12:18.444880Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "green"
},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
{
"name": "Red",
"context": {
"trace_id": "0x02eb6338a1f40daf7230e2df981eabf0",
"span_id": "0xedc13ebcf868ffe4",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": null,
"start_time": "2024-04-14T13:12:18.444377Z",
"end_time": "2024-04-14T13:12:18.444940Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "red"
},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
์ํ Trace ์ฝ๋ + Attributes + events
์ด๋ฒคํธ(Event)๋ ์คํฌ(Span) ๋ด์์ ๋ฐ์ํ๋ ์ฃผ์ ์๊ฐ์ด๋ ์ํ ๋ณํ๋ฅผ ๋ํ๋ด๋ ๋ฐ ์ฌ์ฉํ๋ค.
์ด๋ฒคํธ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ์ถ์ ๋ฐ์ดํฐ์ ์ค์ํ ํ์์คํฌํ์ ๊ด๋ จ ์ ๋ณด๋ฅผ ํฌํจ์์ผ ๋ถ์ ์ ๋ ๋ง์ ์ปจํ
์คํธ๋ฅผ ์ ๊ณตํ ์ ์๋ค.
'Blue' ์คํฌ์ ์ด๋ฒคํธ๋ฅผ ์ถ๊ฐํด๋ณด์.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ด๊ธฐํ
tracer_provider = TracerProvider()
# ์ฝ์ ์ต์คํฌํฐ ์ค์
exporter = ConsoleSpanExporter()
processor = SimpleSpanProcessor(exporter)
tracer_provider.add_span_processor(processor)
# ์ ์ญ ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ค์
trace.set_tracer_provider(tracer_provider)
# ํธ๋ ์ด์ ์ป๊ธฐ
tracer = trace.get_tracer(__name__)
# ์ค์ฒฉ๋ ์คํฌ ์์ฑ
with tracer.start_as_current_span("Red", attributes={"color": "red"}) as span_red:
# 'Red' ์คํฌ ์์
with tracer.start_as_current_span("Green", attributes={"color": "green"}) as span_green:
# 'Green' ์คํฌ ์์
with tracer.start_as_current_span("Blue", attributes={"color": "blue"}) as span_blue:
# 'Blue' ์คํฌ ์์
# ์ด๋ฒคํธ ์ถ๊ฐ
span_blue.add_event("Important Step Reached", {"step": "initialization"})
print("ํ
์คํธ")
๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
ํ
์คํธ
{
"name": "Blue",
"context": {
"trace_id": "0xca57089d5d70504a5a2d8298ef153326",
"span_id": "0x0f923cd0477c968d",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0x5ffc31811c7f0d2f",
"start_time": "2024-04-14T13:18:39.256182Z",
"end_time": "2024-04-14T13:18:39.256210Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "blue"
},
"events": [ # ์ด๋ฒคํธ ์ถ๊ฐ๋จ!!!
{
"name": "Important Step Reached",
"timestamp": "2024-04-14T13:18:39.256188Z",
"attributes": {
"step": "initialization"
}
}
],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
{
"name": "Green",
"context": {
"trace_id": "0xca57089d5d70504a5a2d8298ef153326",
"span_id": "0x5ffc31811c7f0d2f",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0xdc7e7fd90c4899c3",
"start_time": "2024-04-14T13:18:39.256164Z",
"end_time": "2024-04-14T13:18:39.256639Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "green"
},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
{
"name": "Red",
"context": {
"trace_id": "0xca57089d5d70504a5a2d8298ef153326",
"span_id": "0xdc7e7fd90c4899c3",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": null,
"start_time": "2024-04-14T13:18:39.256136Z",
"end_time": "2024-04-14T13:18:39.256700Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "red"
},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
์ํ Trace ์ฝ๋ + Attributes + events + links
๋งํฌ(Link)๋ ํ ์คํฌ๊ณผ ๋ค๋ฅธ ์คํฌ์ด๋ ํธ๋ ์ด์ค ๊ฐ์ ์ฐ๊ฒฐ์ ๋ํ๋ด๋ ๋ฐ ์ฌ์ฉํ๋ค.
๋ค๋ฅธ ํธ๋ ์ด์ค์ ์ํ๋ ์คํฌ๊ณผ์ ์ฐ๊ด์ฑ์ ํํํ๊ฑฐ๋, ํน์ ์์
์ ์ฐ๊ด๋ ์คํฌ์ ์ฐธ์กฐํ ๋ ์ ์ฉํ๋ค.
'Blue' ์คํฌ์ ๋งํฌ๋ฅผ ์ถ๊ฐํด๋ณด์!
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider, RandomIdGenerator
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
from opentelemetry.trace import SpanContext, TraceFlags, TraceState
# ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ด๊ธฐํ
tracer_provider = TracerProvider()
# ์ฝ์ ์ต์คํฌํฐ ์ค์
exporter = ConsoleSpanExporter()
processor = SimpleSpanProcessor(exporter)
tracer_provider.add_span_processor(processor)
# ์ ์ญ ํธ๋ ์ด์ ํ๋ก๋ฐ์ด๋ ์ค์
trace.set_tracer_provider(tracer_provider)
# ํธ๋ ์ด์ ์ป๊ธฐ
tracer = trace.get_tracer(__name__)
# ๋ค๋ฅธ ์คํฌ์ ์ปจํ
์คํธ ์์ฑ (์์ ์ฉ)
id_generator = RandomIdGenerator()
trace_id = id_generator.generate_trace_id()
span_id = id_generator.generate_span_id()
other_span_context = SpanContext(
trace_id=trace_id,
span_id=span_id,
is_remote=True,
trace_flags=TraceFlags.DEFAULT,
trace_state=TraceState()
)
# ์ค์ฒฉ๋ ์คํฌ ์์ฑ
with tracer.start_as_current_span("Red", attributes={"color": "red"}) as span_red:
# 'Red' ์คํฌ ์์
with tracer.start_as_current_span("Green", attributes={"color": "green"}) as span_green:
# 'Green' ์คํฌ ์์
with tracer.start_as_current_span("Blue", attributes={"color": "blue"}, links=[trace.Link(other_span_context)]) as span_blue:
# 'Blue' ์คํฌ ์์
# ์ด๋ฒคํธ ์ถ๊ฐ
span_blue.add_event("Important Step Reached", {"step": "initialization"})
print("ํ
์คํธ")
์ด์ blue Spen์ ๋งํฌ๊ฐ ์ถ๊ฐ๋์๋ค.
ํ
์คํธ
{
"name": "Blue",
"context": {
"trace_id": "0xb86e3902eb3919b10076b02d6f46377b",
"span_id": "0x15c255b44bfa9ed0",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0x2342aca79612d0bd",
"start_time": "2024-04-14T13:35:29.000877Z",
"end_time": "2024-04-14T13:35:29.000911Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "blue"
},
"events": [
{
"name": "Important Step Reached",
"timestamp": "2024-04-14T13:35:29.000886Z",
"attributes": {
"step": "initialization"
}
}
],
"links": [ # ๋งํฌ ์์ฑ
{
"context": {
"trace_id": "0xdb58530034b9cd00f08ef767b5199793",
"span_id": "0x8586c58f9af73b75",
"trace_state": "[]"
},
"attributes": {}
}
],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
{
"name": "Green",
"context": {
"trace_id": "0xb86e3902eb3919b10076b02d6f46377b",
"span_id": "0x2342aca79612d0bd",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": "0xd419153e6f98cab8",
"start_time": "2024-04-14T13:35:29.000857Z",
"end_time": "2024-04-14T13:35:29.001474Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "green"
},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
{
"name": "Red",
"context": {
"trace_id": "0xb86e3902eb3919b10076b02d6f46377b",
"span_id": "0xd419153e6f98cab8",
"trace_state": "[]"
},
"kind": "SpanKind.INTERNAL",
"parent_id": null,
"start_time": "2024-04-14T13:35:29.000822Z",
"end_time": "2024-04-14T13:35:29.001557Z",
"status": {
"status_code": "UNSET"
},
"attributes": {
"color": "red"
},
"events": [],
"links": [],
"resource": {
"attributes": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "1.24.0",
"service.name": "unknown_service"
},
"schema_url": ""
}
}
6.3.2 ์ถ์ ํ์ดํ๋ผ์ธ ๊ตฌ์ฑ
์ด ๋ถ๋ถ์ ๋์ ํ.. ๋ญ ์ค๋ช ํ๊ณ ์ ํ๋๊ฑด์ง, ์ด๋ป๊ฒ ํ ์คํธํ๋ผ๋๊ฑด์ง ์์๊ฐ ์์ด ์ผ๋จ ๊ทธ๋ฅ ๋์ด๊ฐ๋ค..
6.4 ๋ฉํธ๋ฆญ
6.4.1 ์คํํ ๋ ๋ฉํธ๋ฆฌ ๋ฉํธ๋ฆญ ์๊ฐ
๋ฉํธ๋ฆญ์ ์ ํด๋ฆฌ์ผ์ด์ ์์ ์ผ์ด๋๋ ์ผ์ ๋ํ ์ ๋ณด๋ฅผ ์ดํดํ ์ ์๋ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค.
์คํํ
๋ ๋ฉํธ๋ฆฌ ๋ฉํธ๋ฆญ์ ์นด์ดํฐ, ๊ฒ์ด์ง, ํ์คํ ๊ทธ๋จ ๋ฑ ๋ค์ํ ๋ฉํธ๋ฆญ ํ์
์ ์ง์ํ๋ค.
๊ธฐ์กด์ ์ฌ์ฉํ๋ ํ๋ก๋ฉํ
์ฐ์ค ๋ฉํธ๋ฆญ API์๋ ๋ง์ ์ฐจ์ด์ ์ด ์๋ค.
ํ๋ก๋ฉํ
์ฐ์ค๋ 4๊ฐ์ ๋ฉํธ๋ฆญ ์ ํ์ ์ ๊ณตํ์ง๋ง, ์คํํ
๋ ๋ฉํธ๋ฆฌ๋ 6๊ฐ์ง ๋ฉํธ๋ฆญ ์ ํ์ ์ ๊ณตํ๋ค.
์ํ Metric ์ฝ๋
pip install opentelemetry-api opentelemetry-sdk
# https://github.com/open-telemetry/opentelemetry-python/blob/main/docs/examples/metrics/reader/preferred_aggregation.py
import time
from opentelemetry.metrics import get_meter_provider, set_meter_provider
from opentelemetry.sdk.metrics import Counter, MeterProvider
from opentelemetry.sdk.metrics.export import (
ConsoleMetricExporter,
PeriodicExportingMetricReader,
)
from opentelemetry.sdk.metrics.view import LastValueAggregation
aggregation_last_value = {Counter: LastValueAggregation()}
exporter = ConsoleMetricExporter(
preferred_aggregation=aggregation_last_value,
)
reader = PeriodicExportingMetricReader(
exporter,
export_interval_millis=5_000,
)
provider = MeterProvider(metric_readers=[reader])
set_meter_provider(provider)
meter = get_meter_provider().get_meter("preferred-aggregation", "0.1.2")
counter = meter.create_counter("my-counter")
for x in range(10):
counter.add(x)
time.sleep(2.0)
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
import time
from opentelemetry.metrics import get_meter_provider, set_meter_provider
from opentelemetry.sdk.metrics import Counter, MeterProvider
from opentelemetry.sdk.metrics.export import (
ConsoleMetricExporter,
PeriodicExportingMetricReader,
)
from opentelemetry.sdk.metrics.view import LastValueAggregation
# ํน์ ๋ฉํธ๋ฆญ ์ธ์คํธ๋ฃจ๋จผํธ ์ ํ(Counter ๋ฑ)์ ๋ํด ์ฌ์ฉํ ๊ธฐ๋ณธ ์ง๊ณ ๋ฐฉ์์ ์ ์ (์ด๋ป๊ฒ ์ง๊ณํ ๊ฒ์ธ์ง)
aggregation_last_value = {Counter: LastValueAggregation()}
# ๋ฉํธ๋ฆญ ์ต์คํฌํฐ ์ด๊ธฐํ
# ์ฝ์์ ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ๋ฅผ ๋ด๋ณด๋ด๋ ์ญํ ์ ์ํํ๋ค.
exporter = ConsoleMetricExporter(
preferred_aggregation=aggregation_last_value,
)
# ๋ฉํธ๋ฆญ ๋ฆฌ๋ ์ด๊ธฐํ
# ์ค์ ๋ ๊ฐ๊ฒฉ(์ฌ๊ธฐ์๋ 5000 ๋ฐ๋ฆฌ์ด, ์ฆ 5์ด๋ง๋ค)์ผ๋ก ๋ฉํธ๋ฆญ์ ์์งํ๊ณ ์ต์คํฌํฐ๋ฅผ ํตํด ๋ด๋ณด๋ด๋ ์ญํ ์ ์ํํ๋ค.
reader = PeriodicExportingMetricReader(
exporter,
export_interval_millis=5_000,
)
# ๋ฉํธ๋ฆญ ํ๋ก๋ฐ์ด๋ ์ด๊ธฐํ
# ๋ฉํธ๋ฆญ ๋ฆฌ๋๋ฅผ ๋ฑ๋กํ์ฌ ์์ง๋ ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ ๋ด๋ณด๋ด๋ ์ญํ ์ ์ํํ๋ค
provider = MeterProvider(metric_readers=[reader])
set_meter_provider(provider)
# get_meter ํจ์๋ฅผ ์ฌ์ฉํด ๋ฉํธ๋ฆญ์ ์์ฑํ๊ณ ์
๋ฐ์ดํธํ๋ ๋ฐ ํ์ํ Meter ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค.
# Meter๋ ๋ฉํธ๋ฆญ์ ์ธก์ (์ฆ, ๋ฐ์ดํฐ ํฌ์ธํธ ์์ฑ)์ ์ฑ
์์ง๋ ๊ฐ์ฒด์ด๋ค.
meter = get_meter_provider().get_meter("preferred-aggregation", "0.1.2")
counter = meter.create_counter("my-counter")
for x in range(10):
counter.add(x)
time.sleep(2.0)
์ดํด ๊ทธ๋ฐ๋ฐ, ์๊ฐ๋ณด๋ค metric์ด ๋ณต์กํ๊ณ ์ด๋ ต๋ค.
๋ ๋ค์ด๊ฐ๊ธฐ์ ์ ์ฉ์ด์ ๊ตฌ์ฑ์์๋ฅผ ํ์ธํ๊ณ ๊ฐ๋๊ฒ ์ข์ ๊ฒ ๊ฐ๋ค.
OpenTelemetry ๋ฉํธ๋ฆญ ์ฉ์ด ์ ๋ฆฌ
[MetricProvider] # ๋ฉํธ๋ฆญ ์์คํ
์ ์์์ ์ผ๋ก, ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ ์์ง์ ์กฐ์ ํ๊ณ Meter ์ธ์คํด์ค๋ฅผ ์ ๊ณตํ๋ค.
↓
[Meter] # ๋ฉํธ๋ฆญ ์ธ์คํธ๋ฃจ๋จผํธ๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ค. (์ ํ๋ฆฌ์ผ์ด์
์ฝ๋์์ ๋ฉํธ๋ฆญ์ ์ ์ํ ๋ ์ฌ์ฉ)
↓
[Instrument] # ๊ฐ๋ณ ์ธก์ ์์
์ ์คํํ๋ ๊ฐ์ฒด (์นด์ดํฐ, ๊ฒ์ด์ง ๋ฑ)
↓
[Measurement] # ์ค์ ์ธก์ ๋ ๊ฐ์ ๋ํ๋ด๋ ๋ฐ์ดํฐ ํฌ์ธํธ, ์ธ์คํธ๋ฃจ๋จผํธ์์ ๋ฉํธ๋ฆญ ๊ฐ์ ์ธก์ ํ ๋ ์์ฑ๋จ
↓
[MetricReader] # ์์ง๋ ๋ฉํธ๋ฆญ์ ์ฒ๋ฆฌํ๊ณ ์ค๋นํ์ฌ ๋ฉํธ๋ฆญ ์ต์คํฌํฐ๋ก ์ ๋ฌ
↓
[MetricExporter] # ์ฒ๋ฆฌ๋ ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ๋ฅผ ์ธ๋ถ ์์คํ
์ผ๋ก ์ ์ก
↓
[External System]
- Meter:
- ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ(์ธก์ ๊ฐ)๋ฅผ ์์ฑํ๋ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ค.
- ๋ค์ํ ์ ํ์ ๋ฉํธ๋ฆญ Instrument๋ฅผ ์์ฑํ๋ค.
- Instrument:
- ์ธก์ ์ ์ํํ๋ ๊ฐ์ฒด (์ Counter, ObservableGauge ๋ฑ)
- ์ ํ๋ฆฌ์ผ์ด์ ์ ํน์ ๋ถ๋ถ์์ ์ธก์ ์ ์์งํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
- Measurement:
- ์ค์ ๋ก ์ธก์ ๋ ๋ฐ์ดํฐ ํฌ์ธํธ๋ฅผ ๋ํ๋ธ๋ค.
- ๋ฉํธ๋ฆญ ์ธ์คํธ๋ฃจ๋จผํธ๊ฐ ๋ฉํธ๋ฆญ ๊ฐ์ ์์งํ ๋๋ง๋ค ์ธก์ ์ด ์์ฑ๋๋ค.
- MetricReader:
- ์์ง๋ ๋ฉํธ๋ฆญ์ ์ฒ๋ฆฌํ๊ณ ์ต์ข ์ ์ผ๋ก ๋ฉํธ๋ฆญ ์ต์คํฌํฐ๋ก ์ ๋ฌํ๋ค.
- ๋ฉํธ๋ฆญ์ ์ฃผ๊ธฐ์ ์ผ๋ก ์์งํ๊ณ , ํ์์ ๋ฐ๋ผ ์ฆ์ ๋ด๋ณด๋ด๊ฑฐ๋ ์ข ๋ฃ ์ฒ๋ฆฌ๋ฅผ ์ํํ ์ ์๋ค.
6.4.2 ๋ฉํธ๋ฆญ ํ์ดํ๋ผ์ธ ๊ตฌ์ฑ
์ด ๋ถ๋ถ๋..... ๋ด์ผ์ ๋์๊ฒ ๋ถํํ๋ค..
6.5. ๋ก๊ทธ
์ฑ ์์ ๋ค๋ฃจ๋ ๋ด์ฉ์ ๊ณต์๋ฌธ์์์ ๊ฑฐ์ ์ฐพ์๋ณผ ์์์ด, ๋ณ๋๋ก ์๋ ๊ณต์Docs๋ฅผ ํตํด ๋ด์ฉ์ ์ ๋ฆฌํ๋ค (์ฑ ๋ด์ฉ ๐ ๐ปโ๏ธ์๋๐ ๐ปโ๏ธ)
* ์ฐธ๊ณ ๋งํฌ: https://opentelemetry.io/docs/specs/otel/logs/
๋ฉํธ๋ฆญ(metrics)๊ณผ ํธ๋ ์ด์ค(traces)์ ๋ํด์๋ ์๋ก์ด API๋ฅผ ์ง์ ํ๊ณ , ์ฌ๋ฌ ์ธ์ด์์ ์ด API์ ์ ์ฒด ๊ตฌํ์ ์ ๊ณตํ๋ '์ฒญ์ฌ์ง ์ค๊ณ(clean-sheet design)' ์ ๊ทผ ๋ฐฉ์์ ์ทจํ๊ณ ์๋ค.
ํ์ง๋ง ๋ก๊ทธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๋ด์ฅ๋ ๋ก๊น ๊ธฐ๋ฅ์ด ์๊ณ , ๋๋ฆฌ ์ฌ์ฉํ๋ ๋ก๊น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๊ธฐ๋๋ฌธ์, Metric, Trace์ ๋ค๋ฅด๊ฒ ๊ธฐ์กด ๊ธฐ์ ๊ณผ์ ํธํ์ฑ์ ์ ์งํ๋ฉด์, ๊ธฐ์กด ๋ก๊ทธ ๋ฉ์ธ์ง ํ์์ ์ถ์ ๋ฑ์ ์๊ด๊ด๊ณ ์ ๋ณด์ ํ ๋ ๋ฉํธ๋ฆฌ ์ ๋ณด๋ฅผ ์ถ๊ฐํ๋๋ก ๊ฐ๋ฐ๋์๋ค.
๋ก๊ทธ์ ๋ํ OpenTelemetry์ ์ ๊ทผ๋ฐฉ์
- ๋ก๊ทธ๋ฐ์ดํฐ ๋ชจ๋ธ ์ ์ (์ฐธ๊ณ ): ๋ก๊ทธ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ์ ์ํ์ฌ LogRecord๊ฐ ๋ฌด์์ธ์ง, ์ด๋ค ๋ฐ์ดํฐ๊ฐ ๊ธฐ๋ก, ์ ์ก, ์ ์ฅ ๋ฐ ํด์๋์ด์ผ ํ๋์ง์ ๋ํ ๊ท์น์ ์ ์ํ๋ค.
- ๋ก๊ทธ ๋ธ๋ฆฟ์ง API(์ฐธ๊ณ ): LogRecords๋ฅผ ๋ฐํํ๊ธฐ ์ํ Logs Bridge API๋ฅผ ์ ์ํ๋ค. ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์๋ ์ด API๋ฅผ ์ง์ ํธ์ถํ๋ ๊ฒ์ด ๊ถ์ฅ๋์ง ์์ผ๋ฉฐ, ์ด๋ ๊ธฐ์กด ๋ก๊น ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ OpenTelemetry ๋ก๊ทธ ๋ฐ์ดํฐ ๋ชจ๋ธ ๊ฐ์ ๋ค๋ฆฌ ์ญํ ์ ํ๋ ๋ก๊ทธ ์ดํ๋๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์๋ค์๊ฒ ์ ๊ณต๋๋ค.
- ๋ธ๋ฆฌ์ง API์ SDK ๊ตฌํ(์ฐธ๊ณ ): ๋ธ๋ฆฌ์ง API์ SDK ๊ตฌํ์ ์ ์ํ์ฌ LogRecords์ ์ฒ๋ฆฌ ๋ฐ ๋ด๋ณด๋ด๊ธฐ๋ฅผ ๊ตฌ์ฑํ ์ ์๋ค.
- ์๋ก์ด ๋ก๊ทธ ์์คํ (์ฐธ๊ณ ): ์๋กญ๊ฒ ์ค๊ณ๋ ๋ก๊ทธ ์์คํ ์ OpenTelemetry์ ๋ก๊ทธ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ๋ฐ๋ผ ๋ก๊ทธ๋ฅผ ์์ฑํ๋ค.
- ๊ธฐ์กด ๋ก๊ทธ ํฌ๋งท ํธํ์ฑ: ๊ธฐ์กด ๋ก๊ทธ ํฌ๋งท์ OpenTelemetry ๋ก๊ทธ ๋ฐ์ดํฐ ๋ชจ๋ธ๋ก ๋ช ํํ๊ฒ ๋งคํํ ์ ์๋ค. OpenTelemetry Collector๋ฅผ ํตํด OpenTelemetry ๋ก๊ทธ ๋ฐ์ดํฐ ๋ชจ๋ธ๋ก ๋ณํํ ์์๋ค.
OpenTelemetry ๋ก๊ทธ ์์ค ์ ํ
๋ก๊ทธ ์์ค ์ ํ์ ๋๋๊ณ ์ ์ํจ์ผ๋ก์จ, ๋ก๊ทธ์ ์์ง ๋ฐ ์ฒ๋ฆฌ ๋ฐฉ์์ ์์ด์ ๊ตฌ์ฒด์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์ ์ํ๊ณ ์๋ค.
- System Logs (์์คํ
๋ก๊ทธ):
- ์ด์ ์ฒด์ ๊ฐ ์์ฑํ๋ ๋ก๊ทธ๋ก, ๋ก๊ทธ์ ํ์์ด๋ ํฌํจ๋๋ ์ ๋ณด๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค. (syslog, windoes event logs..)
- OpenTelemetry Collector๋ฅผ ํตํด ์์คํ ๋ก๊ทธ๋ ์๋์ผ๋ก ๋ฆฌ์์ค ์ปจํ ์คํธ(์: ํธ์คํธ ์ด๋ฆ, IP ์ฃผ์)๋ฅผ ์ถ๊ฐํ๊ณ ์์งํ ์ ์๋ค.
- Infrastructure Logs (์ธํ๋ผ ๋ก๊ทธ):
- ์ธํ๋ผ ๋ก๊ทธ๋ ๋คํธ์ํฌ ์ฅ๋น, ๋ฐ์ดํฐ ์ผํฐ, ํด๋ผ์ฐ๋ ์๋น์ค, Kubernetes ์ด๋ฒคํธ ์ ๊ฐ์ IT ๋ค์ํ ์ธํ๋ผ ๊ตฌ์ฑ ์์์์ ์์ฑ๋๋ ๋ก๊ทธ๋ฅผ ๋งํ๋ค.
- OpenTelemetry Collector๋ฅผ ํตํด ๋ ธ๋, ํฌํธ, ์ปจํ ์ด๋ ๋ฑ์ ๋ฆฌ์์ค ์ปจํ ์คํธ๋ฅผ ์ถ๊ฐํ๊ณ ์์งํ ์ ์๋ค.
- Third-party Application Logs (์ 3์ ์ ํ๋ฆฌ์ผ์ด์
๋ก๊ทธ):
- ์๋ํํฐ ์ ํ๋ฆฌ์ผ์ด์ ๋ก๊ทธ๋ ์ ์๋ ค์ง ์ดํ๋ฆฌ์ผ์ด์ , ์๋ฅผ๋ค์ด mysql๊ณผ ๊ฐ์ ์๋ฃจ์ ์ ์ฌ์ฉํ์๋์ ๋ก๊ทธ๋ฅผ ๋งํ๋ค.
- OpenTelemetry๋ OpenTelemetry Collector์ filelog receiver ์ฌ์ฉํ๊ฑฐ๋, FluentBit๊ณผ ๊ฐ์ ๋ก๊ทธ ์์ง ์์ด์ ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ OpenTelemetry Collector๋ก ์ ์กํ์ฌ ๋ก๊ทธ๋ฅผ ์ถ๊ฐ๋ก ์ฒ๋ฆฌํ๋๊ฒ์ ๊ถ์ฅํ๋ค.
- Legacy First-Party Applications Logs (๋ ๊ฑฐ์ ์ฒซ ๋ฒ์งธ ํํฐ ์ ํ๋ฆฌ์ผ์ด์
๋ก๊ทธ):
- ์ฌ๋ด์์ ๊ฐ๋ฐ๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ์ํ๋ ๋ก๊ทธ๋ฅผ ๋งํ๋ค.
- OpenTelemetry๋ ๋ก๊ทธ๋ฅผ ์์งํ ๋ ์ผ๋ฐ ํ ์คํธ๊ฐ ์๋ json๊ณผ ๊ฐ์ ๊ตฌ์กฐํ๋ ํ์์ผ๋ก ์ถ๋ ฅํ๋๋ก ์ดํ๋ ์ผ์ด์ ์ ๋ก๊ทธ ํฌ๋ฉงํฐ๋ฅผ ์ฌ๊ตฌ์ฑํ๊ณ (๋ก๊ทธ์์ง ์ ๋ขฐ์ฑ ํฅ์), ๋ก๊ทธ๋ง๋ค TraceID, SpanID๋ฅผ ์ถ๊ฐํ๋๋ก ๊ถ์ฅํ๋ค.
- ์ผ๋ถ ๋ก๊น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ log appender ํน์ log bridge๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก, ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๋ก๊ทธ ๋ ์ฝ๋์ ์ถ๊ฐ์ ๋ณด(TraceID, SpenID)๋ฅผ ์ถ๊ฐํ๋๋ก ๊ถ์ฅํ๋ค.
- Via File or Stdout Logs (ํ์ผ์ด๋ ํ์ค ์ถ๋ ฅ์ ํตํ ๋ก๊ทธ):
- ๋ก๊ทธ๊ฐ ํ์ผ ๋๋ ํ์ค ์ถ๋ ฅ์ผ๋ก ์์ฑ๋๋ ๊ฒฝ์ฐ๋ฅผ ๋งํ๋ค.
- OpenTelemetry๋ OpenTelemetry Collector์ filelog receiver ์ฌ์ฉํ๊ฑฐ๋, FluentBit๊ณผ ๊ฐ์ ๋ก๊ทธ ์์ง ์์ด์ ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ OpenTelemetry Collector๋ก ์ ์กํ์ฌ ๋ก๊ทธ๋ฅผ ์ถ๊ฐ๋ก ์ฒ๋ฆฌํ๋๊ฒ์ ๊ถ์ฅํ๋ค.
- Direct to Collector (์ง์ ์ปฌ๋ ํฐ๋ก ์ ์ก):
- ๋ก๊ทธ๋ฅผ OpenTelemetry Protocol์ ํตํด ์ถ๋ ฅ๋๋๋ก ์ง์ ์ดํ๋ฆฌ์ผ์ด์ ์ ์์ ํ์ฌ ์ฌ์ฉํ๋๊ฒ์ ๋งํ๋ค.
- ์ฅ์ : ๋ก๊ทธ ๋ฐ์ดํฐ๋ฅผ ํ์ผ์ด๋ ๋ค๋ฅธ ์ค๊ฐ ์ ์ฅ์๋ฅผ ๊ฑฐ์น์ง ์๊ณ , ์ง์ OpenTelemetry Collector ๊ฐ์ ๋ฐ์ดํฐ ์์ง ์์คํ ์ผ๋ก ์ ์กํ๋ ๋ฐฉ๋ฒ์ ์ด ๋ฐฉ์์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ์ง์ฐ์ ์ต์ํํ๊ณ ํจ์จ์ ๋์ผ ์ ์๋ค.
- ๋จ์ : ๋ก์ปฌ ํ์ผ๋ก ๋ก๊ทธ๋ฅผ ๋ณด์ ํ๋ ๊ฐ๋จํจ์ด ์ฌ๋ผ์ง๋ฉฐ, ๋ก๊ทธ๋ฅผ ์์ ํ ๋ชฉ์ ์ง๊ฐ ๋ก๊ทธ๋ฅผ ๋ฐ์ ์ ์์๋๋ง ์๋ํ๋ค.
- ๋ก์ปฌํ์ผ์๋ ๋ก๊ทธ๋ฅผ ์ ์ฌํ๊ณ , OTLP๋ก ์ปฌ๋ ํฐ๋ก ์ง์ ์ ์ก ๊ฐ๋ฅํ๋๋ก ํ๊ธฐ ์ํด Bridge API ์ SDK๋ฅผ ์ ๊ณตํ๋ค.
- New First-Party Application Logs (์ ์ฒซ ๋ฒ์งธ ํํฐ ์ ํ๋ฆฌ์ผ์ด์
๋ก๊ทธ):
- ์๋ก ๊ฐ๋ฐ๋๊ณ ์๋ ์ดํ๋ฆฌ์ผ์ด์ ์์ ์ด๋ป๊ฒ ๋ก๊ทธ๋ฅผ ๋ณด๋ด๋๊ฒ์ด ์ข์์ง์ ๋ํ ๋ด์ฉ์ด๋ค.
- ๋ก๊ทธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ธฐ์กด์ฒ๋ผ ์ฌ์ฉํ๊ณ , Bridge API ์ SDK๋ฅผ ์ฌ์ฉํ์ฌ ๋ก๊ทธ์ TraceID ๋ฑ์ ์ถ๊ฐํ๋ค.
Log ์ฝ๋ ํ ์คํธ ํด๋ณด๊ธฐ
์ํ FastAPI ์ฝ๋
main.py๋ฅผ ์์ฑํ๊ณ ์๋ ์ฝ๋๋ฅผ ๋ณต์ฌํ๋ค.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
์๋ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ค.
$ pip install fastapi uvicorn
$ uvicorn main:app --reload
์ดํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋๋์ง http://127.0.0.1:8000์ ์ ์ํด์ ํ์ธํด๋ณด์
์ํ FastAPI ์ฝ๋ + Trace์ถ๊ฐ
์ ์ฝ๋์ Trace๋ฅผ ์ถ๊ฐํด๋ณด์.
์๊น ์์ฑํ main.py์ ๋ด์ฉ์ ์ญ์ ํ๊ณ ์๋ ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์.
from fastapi import FastAPI
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
app = FastAPI()
# OpenTelemetry ํธ๋ ์ด์ ์ค์
trace.set_tracer_provider(
TracerProvider(
resource=Resource.create({SERVICE_NAME: "simple-fastapi-service"})
)
)
tracer = trace.get_tracer(__name__)
# OTLP๋ก ํธ๋ ์ด์ค ๋ฐ์ดํฐ๋ฅผ localhost๋ก ์ ์ก
otlp_exporter = OTLPSpanExporter(endpoint="localhost:4317", insecure=True)
span_processor = BatchSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
# FastAPI ์ฑ์ OpenTelemetry ๊ตฌ์ฑ
FastAPIInstrumentor.instrument_app(app)
@app.get("/")
def read_root():
with tracer.start_as_current_span("root_span"):
return {"Hello": "World"}
์๋ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ค.
$ pip install fastapi uvicorn opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation-fastapi opentelemetry-exporter-otlp
$ uvicorn main:app --reload
์ดํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋๋์ง http://127.0.0.1:8000์ ์ ์ํด์ ํ์ธํด๋ณด์
๋ฐฑ์๋๋ฅผ ์ค์ ํด๋์๋ค๋ฉด trace๊ฐ ์ ์์ ์ผ๋ก ์ฐํ ๋ณด์ผ๊ฒ์ด๋ค.
์ํ FastAPI ์ฝ๋ + Trace + Log์ถ๊ฐ
์ด์ ์ ์ฝ๋์ ๋ก๊ทธ๋ฅผ ์ถ๊ฐํด๋ณด์.
์๊น ์์ฑํ main.py์ ๋ด์ฉ์ ์ญ์ ํ๊ณ ์๋ ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์.
from fastapi import FastAPI
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.logging import LoggingInstrumentor
import logging
app = FastAPI()
# OpenTelemetry ํธ๋ ์ด์ ์ค์
trace.set_tracer_provider(
TracerProvider(
resource=Resource.create({SERVICE_NAME: "simple-fastapi-service"})
)
)
tracer = trace.get_tracer(__name__)
# OTLP๋ก ํธ๋ ์ด์ค ๋ฐ์ดํฐ๋ฅผ localhost๋ก ์ ์ก
otlp_exporter = OTLPSpanExporter(endpoint="localhost:4317", insecure=True)
span_processor = BatchSpanProcessor(otlp_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
# FastAPI ์ฑ์ OpenTelemetry ๊ตฌ์ฑ
FastAPIInstrumentor.instrument_app(app)
# ๋ก๊น
๊ตฌ์ฑ
LoggingInstrumentor().instrument(set_logging_format=True)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
@app.get("/")
def read_root():
with tracer.start_as_current_span("root_span"):
logging.info("Handling root request")
return {"Hello": "World"}
์๋ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ค.
$ pip install opentelemetry-instrumentation-logging
$ uvicorn main:app --reload
์ดํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋๋์ง http://127.0.0.1:8000์ ์ ์ํด์ ํ์ธํด๋ณด์
์ค์ ํ๋๋ก ๋ก๊ทธ์ ๋์จ TraceID๋ฅผ ํ์ธํ ์ ์์๋ค.
6.6 ์ปฌ๋ ํฐ
์คํํ ๋ ๋ฉํธ๋ฆฌ ์ปฌ๋ ํฐ(OpenTelemetry Collector) ๊ฐ์
์ปฌ๋ ํฐ๋ ๋ค์ํ ์์ค(์ ํ๋ฆฌ์ผ์ด์ , ์์คํ , ์ธํ๋ผ ๋ฑ)์์ ๋ก๊ทธ, ๋ฉํธ๋ฆญ, ํธ๋ ์ด์ค ๋ฐ์ดํฐ๋ฅผ ์์ง, ๋ณํ ํ๊ณ ์ฒ๋ฆฌํ ํ ์ฌ๋ฌ ๋ฐฑ์๋(์: ๋ชจ๋ํฐ๋ง ๋๊ตฌ, ๋ก๊ทธ ๋ถ์ ์๋น์ค)๋ก ์ ์กํ๋ค.
OpenTelemetry๋ฅผ ํ
์คํธํ๊ฑฐ๋ ์๊ท๋ชจ ํ๊ฒฝ์์๋ Collector์์ด ๋ฐ๋ก ๋ฐฑ์๋๋ก ๋ณด๋ผ ์ ์์ง๋ง,
์ผ๋ฐ์ ์ผ๋ก๋ Collector๋ฅผ ์ฌ์ฉํ๋๊ฒ์ ๊ถ์ฅํ๋ค.
Collector์์ ์ฌ์๋, ์ผ๊ด์ฒ๋ฆฌ, ์ํธํ, ๋ฏผ๊ฐ๋ฐ์ดํฐ ํํฐ๋ง ๋ฑ ์ถ๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ค์น ๋ฐฉ๋ฒ
์ค์น ๋ฐฉ๋ฒ๋ ๊ฐ๋จํ๋ค.
docker ์ปจํ
์ด๋๋ก ์คํํ๊ฑฐ๋, ๋ฐ์ด๋๋ฆฌ๋ก ์คํํ ์ ์๋ค. ์ฐธ๊ณ
Collector ์ ์ฉ ํจํด
- No Collector (๋งํฌ)
- ์ดํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ๋ก ๋ฐฑ์๋๋ก ๋ณด๋ด๋ ๊ตฌ์ฑ์ ๋งํ๋ค.
- ์์ ๋์๋ ์ํ์ฝ๋๋ค์ Metric, Log, Trace๋ค์ OTLP๋ฅผ ์ด์ฉํด์ ๋ฐ๋ก ๋ฐฑ์๋๋ก ๋ณด๋๋ค.
- No Collector ํจํด์ ์ฌ์ฉํ๊ธฐ ๊ฐํธํ๊ณ , ์ถ๊ฐ ์ค์ ํ ํ์๊ฐ ์๋ค๋ ์ฅ์ ์ด ์์ง๋ง, ์์ง, ์ฒ๋ฆฌ,๋ด๋ณด๋ด๊ธฐ ์๋ํฌ์ธํธ ๋ฑ ์์ ์ด ํ์ํ๊ฒฝ์ฐ ์ฝ๋์ ์์ ์ด ํ์ํ๋ค.
- ๋ํ ๋ด๋ณด๋ด๊ธฐ ์๊ฐ ์ ํ๋์ด์์ด ์ ํ ์ฌํญ์ ํ์ธํด์ผํ๋ฉฐ, ์ฌ์๋ ๋ฑ์ ๋ํด ์ง์ ๊ณ ๋ฏผํด์ผํ๋ค.
- ์ผ๋ฐ์ ์ผ๋ก No Collector ๊ตฌ์ฑ์ ํ ์คํธํ๊ฒฝ์ด๊ฑฐ๋ ์์ฃผ ์๊ท๋ชจ์ผ๋๋ง ์ฌ์ฉํ๋๋ก ๊ถ์ฅํ๋ค.
- Agent (๋งํฌ)
- ์๋ฒ๋น ํ๋์ Collector๋ฅผ ๊ตฌ์ฑํ๊ฑฐ๋, ์ฌ์ด๋์นด ์ปจํ ์ด๋๋ก ๊ตฌ์ฑํ๋ ๋ฐฉ์์ ๋งํ๋ค.
- ๊ตฌ์ฑ์ด ๊ฐ๋จํ๋ค๋ ์ฅ์ ์ด ์์ผ๋, ํ์ฅ์ฑ ๋ฌธ์ (์๋ฒ์๊ฐ ์ฆ๊ฐํ ์๋ก ์ปฌ๋ ํฐ๋ ๋ง์์ง)๊ฐ ๋ฐ์ํ ์ ์๊ณ , ์ ์ฐ์ฑ์ด ๋ถ์กฑํ๋ค.
- Gateway (๋งํฌ)
- Collector ์๋ฒ๋ฅผ ๋ฐ๋ก ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ๋งํ๋ค. (Collector ์๋ฒ๊ตฌ์ฑ)
- ์ค์์ง์คํ๋ ์ปฌ๋ ํฐ ์๋ฒ๊ทธ๋ฃน์ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก, ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐ ๊ด๋ฆฌ๋ฅผ ์ค์์์ ์ํํ ์ ์๋ค.
- ์ฅ์ ์ผ๋ก๋ ๋ณด์์ ์ฑ ์ด๋ ์ค์ ๋ฑ์ ์ค์์์ ๊ด๋ฆฌํ ์ ์์ผ๋ฉฐ, ๊ฐ๋ณ ์ดํ๋ฆฌ์ผ์ด์ ์ค์ ์ ๋ํด ์ ๊ฒฝ์ธ ํ์๊ฐ ์๋ค.
- ๋จ์ ์ผ๋ก๋ ์์คํ ์ ๋ณต์ก์ฑ์ ์ฆ๊ฐ์ํค๊ณ , ์ถ๊ฐ์ ์ธ ์ ์ง๋ณด์๊ฐ ํ์ํ๋ค. ๋ํ, ์ค์ ์ปฌ๋ ํฐ๊ฐ ์คํจํ ๊ฒฝ์ฐ ์์คํ ์ ์ฒด์ ๋ฐ์ดํฐ ์์ง์ ์ํฅ์ ์ค ์ ์์ผ๋ฏ๋ก ๋จ์ผ์คํจ์ง์ ์ด ๋ ์ ์๋ค.
- ๋ํ ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฌ๋จ๊ณ์ ๊ฑธ์ณ ์์ง๋๊ธฐ๋๋ฌธ์ ์ฒ๋ฆฌ ์ง์ฐ์๊ฐ์ด ๋ฐ์ํ ์ ์๋, ์๋นํ ์์ ์ปดํจํ ๋ฆฌ์์ค๊ฐ ์ถ๊ฐ๋์ด ์ด์๋น์ฉ์ ์ฆ๊ฐ๋ก ์ด์ด์ง ์ ์๋ค.
Collector ๊ตฌ์ฑ์์
Receivers (๋งํฌ)
- ๋ฐ์ดํฐ๊ฐ Collector๋ก ๋ค์ด๊ฐ๋ ๋ฐฉ๋ฒ์ ์ ์ํ๋ค.
- Receiver๋ ์ง์ ๋ ํ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ๋ด๋ถ ํ์์ผ๋ก ๋ณํํ ํ ํด๋น ํ์ดํ๋ผ์ธ์ ์ ์๋ Processer ์ Exporter์ ์ ๋ฌํ๋ค.
- Collector์์๋ ํ๋์ด์์ Receiver๊ฐ ํ์ํ๋ค.
- Collector๋ ๊ตฌ์ฑํ๋๋ผ๋ ๋ฐ๋ก ํ์ฑํ ๋์ง ์๋๋ค. Service ์น์ ๋ด์ ์ ์ ํ ํ์ดํ๋ผ์ธ์ ์ถ๊ฐํด์ผ ํ์ฑํ ๋๋ค.
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
Processors (๋งํฌ)
- Processer๋ Receivers์์ ์์ง๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์์ ํ๊ฑฐ๋ ๋ณํํ ํ Exporter์ ์ ๋ฌํ๋ค.
- ํํฐ๋ง, ์ญ์ , ์ด๋ฆ๋ฐ๊พธ๊ธฐ, ์ฌ๊ณ์ฐ, ๋ฉํ๋ฐ์ดํฐ ์ถ๊ฐ, ์ํ๋ง ๋ฑ์ ์์ ์ด ํฌํจ๋๋ฉฐ ํ์ดํ๋ผ์ธ์ ์์์ ๋ฐ๋ผ ์ฒ๋ฆฌํ๋ ์์ ์ ์์๊ฐ ๊ฒฐ์ ๋๋ค.
- Processer๋ฅผ ๊ตฌ์ฑํ๋๋ผ๋ ๋ฐ๋ก ํ์ฑํ ๋์ง ์๋๋ค. Service ์น์ ๋ด์ ์ ์ ํ ํ์ดํ๋ผ์ธ์ ์ถ๊ฐํด์ผ ํ์ฑํ ๋๋ค.
processors:
attributes:
actions:
- key: environment
value: "production"
action: insert
- key: service_name
value: "example-service"
action: insert
Exporters (๋งํฌ)
- Exporter๋ ํ๋์ด์์ ๋ฐฑ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ๋ด๋ณด๋ธ๋ค.
- Exporter๋ pull ๋๋ Push ๊ธฐ๋ฐ์ผ ์ ์์ผ๋ฉฐ, ํ๋ ์ด์์ ๋ฐ์ดํฐ ์์ค๋ฅผ ์ง์ํ ์ ์๋ค.
- Exporter๋ ๊ตฌ์ฑํ๋๋ผ๋ ๋ฐ๋ก ํ์ฑํ ๋์ง ์๋๋ค. Service ์น์ ๋ด์ ์ ์ ํ ํ์ดํ๋ผ์ธ์ ์ถ๊ฐํด์ผ ํ์ฑํ ๋๋ค.
exporters:
loki:
endpoint: "http://loki:3100"
otlp:
endpoint: "http://tempo:4317"
protocol: grpc
prometheusremotewrite:
endpoint: "http://mimir:9009/api/prom/push"
Service
- Service ์น์ ์์๋ Receiver,Processer,Exporter๋ฅผ ํ๋์ ํ์ดํ๋ผ์ธ์ผ๋ก ์ฐ๊ฒฐํ๋ค.
- ๋ก๊ทธ, ๋ฉํธ๋ฆญ, ํธ๋ ์ด์ค ๊ฐ๊ฐ์ ๋ํด ๋ณ๋์ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๋ค.
service:
pipelines:
traces:
receivers: [otlp]
processors: [attributes]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [attributes]
exporters: [prometheusremotewrite]
logs:
receivers: [otlp]
processors: [attributes]
exporters: [loki]
Connectors (๋งํฌ)
- Connector๋ ํน์ ์ ํ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ํ๋ฆ ์ ์ด๋ฅผ ๋ด๋นํ๋ ๊ตฌ์ฑ ์์์ด๋ค.
- ๋ ํ์ดํ๋ผ์ธ์ ์ฐ๊ฒฐํ๋ ์ญํ ์ ํ๋ฉฐ, ํ ํ์ดํ๋ผ์ธ์ ๋์์ ๋ฐ์ดํฐ Export ์ญํ ๊ณผ ๋ค๋ฅธ ํ์ดํ๋ผ์ธ์ ์์์์ ๋ฐ์ดํฐ Reciver ์ญํ ์ ๊ฒธํ๋ค.
- ๋ฐ์ดํฐ์ ์ ํ์ด ๋์ผํ๊ฑฐ๋ ๋ค๋ฅผ ์ ์๋ ์ฌ๋ฌ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ์ฐ๊ฒฐํ ์ ์๋ค.
# count ์ปค๋ฅํฐ๊ฐ ์ฌ์ฉ๋์ด ํธ๋ ์ด์ค ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ ,
#ํด๋น ๋ฐ์ดํฐ๋ฅผ ๋ฉํธ๋ฆญ ๋ฐ์ดํฐ๋ก ๋ณํํ์ฌ ๋ค๋ฅธ ํ์ดํ๋ผ์ธ์ผ๋ก ์ ์ก
receivers:
foo:
exporters:
bar:
connectors:
count:
spanevents:
my.prod.event.count:
description: The number of span events from my prod environment.
conditions:
- 'attributes["env"] == "prod"'
- 'name == "prodevent"'
service:
pipelines:
traces:
receivers: [foo]
exporters: [count]
metrics:
receivers: [count]
exporters: [bar]