
fromm์ OpenTelemetry ๋์ ์ฌ์

- #monitoring
- #observability
- #OpenTelemetry
- #SigNoz
์๋ ํ์ธ์. ๋ ธ๋จธ์ค์์ fromm ๋ฐฑ์๋ ๊ฐ๋ฐ์ ํ๊ณ ์๋ ๊น์ฐํ์ ๋๋ค.
๋ฐฑ์๋ ํ์์ ๋๋ CloudWatch์ ํ๊ณ์ OpenTelemetry์ ๋์
fromm์ ๋ฐฑ์๋๋ ECS์ Lambda์์ ๋์ํ๋ nest.js ์ดํ๋ฆฌ์ผ์ด์ ์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ธฐ์กด ๋ฐฑ์๋ ์์คํ ์ ๋ชจ๋ํฐ๋ง์ AWS CloudWatch๋ก ํ๊ณ ์์์ต๋๋ค. CloudWatch๋ฅผ ํตํ ๋ชจ๋ํฐ๋ง์ ์ดํ๋ฆฌ์ผ์ด์ ๋ฐฐํฌ์ ๋ฉํธ๋ฆญ๊ณผ ๋ก๊ทธ๋ฅผ ์ค์ ์ ์ด๋ ค์ ์์ด ์์งํ ์ ์๋ค๋ ์ , exporter ์ collector ๋ฑ ์ถ๊ฐ์ ์ธ ์ธํ๋ผ ๊ตฌ์ฑ ๋ฐ ๊ด๋ฆฌ๋ถ๋ด์ด ์๋ค๋ ์ ๋ฑ์ด ์ฅ์ ์ด๋ผ ์ ํ์ฉํ๊ณ ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฑ์ ๊ท๋ชจ๊ฐ ์ปค์ง๊ณ ๋จ์ํ ๋ชจ๋ํฐ๋ง์์ observability ํ๋ณด์ ํ์์ฑ์ด ์๊ธฐ๋ฉฐ ๋ค์๊ณผ ๊ฐ์ CloudWatch์ ํ๊ณ๊ฐ ๋๊ปด์ง๊ธฐ ์์ํ์ต๋๋ค.
์ปค์คํ ๋ฉํธ๋ฆญ์ ๋ถ์กฑ
CloudWatch์์ ์ ๊ณต๋๋ Lambda function ๋จ์์ API Count, Latency ๋ฑ์ ๋ฉํธ๋ฆญ์ผ๋ก function ์ ์ฒด ์ํ๋ฅผ ๋ชจ๋ํฐ๋ง ํ ์๋ ์์ง๋ง, API Path๋ณ๋ก Count, Error, Latency ๋ฑ์ ์ธก์ ํ๋ ค๋ฉด custom metric์ ์ง์ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ์ด ๊ฒฝ์ฐ log๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ํ custom metric์ ํ๋ํ๋ ์ค์ ํด์ผ ํ ๋ฟ๋ง ์๋๋ผ ์ถ๊ฐ ๋น์ฉ๊น์ง ๋ถ๋ดํด์ผ ํ์ต๋๋ค.
๋ถ์ฐ ํธ๋ ์ด์ฑ ๋ฏธ์ง์
์ฑ์ ๊ท๋ชจ๊ฐ ์ปค์ง๊ณ ์ฌ๋ฌ ์๋น์ค๊ฐ ์ถ๊ฐ๋จ์ ๋ฐ๋ผ ์๋น์ค๊ฐ internal call์ด ๋ง์์ก์ต๋๋ค. ํ๋์ ์์ฒญ์ ๋ฐ๋ผ๊ฐ๋ฉฐ ์ด๋์์ ์ด๋ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ณ ์ด๋์ ๋์ ์ํฅ์ ๋ฏธ์น๊ณ ์๋์ง ํ๋ฆ์ ํ์ ํ ํ์์ฑ์ด ๋๊ปด์ก์ต๋๋ค.
Metric Resolution์ ํ๊ณ
CloudWatch์์ ์ ๊ณต๋๋ ๋ฉํธ๋ฆญ์ ๊ธฐ๋ณธ์ ์ผ๋ก 1๋ถ๋จ์์ Standard Resolution์ ์ ๊ณตํ๋ฉฐ ๊ธฐ๊ฐ์ด ๊ธธ์ด์ง์๋ก ํด์๋๋ ๋์ฑ ๋จ์ด์ง๋๋ค. fromm์ ํธ๋ํฝ ์์์ ํ์ ํด๋ณด๋ 1๋ถ Count๋ก ์กํ ์ง์ ํธ๋ํฝ์ 50% ์ด์์ด ์ด๊ธฐ 5~10์ด ๋ด์ ๋ฐ์ํ๋ค๋ ๊ฒ์ ์๊ฒ ๋์๊ณ ๋ฐ๋ผ์ 1์ด, 5์ด, 10์ด ๋จ์์ High Resolution์ด ๋ฐ๋์ ํ์ํ์ต๋๋ค.
๋ก๊ทธ์ ์ง์ฐ
CloudWatch์ Log Insight์ ๊ฒฝ์ฐ ์ดํ๋ฆฌ์ผ์ด์ ๋ก๊ทธ๊ฐ ์ธ์ ๋๊ธฐ๊น์ง 1~2๋ถ ์ ๋์ ์ง์ฐ์ด ๋ฐ์ํฉ๋๋ค. Live Tail์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ค์๊ฐ ๋ก๊ทธ๋ฅผ ํ์ธํ ์ ์์ง๋ง ECS์๋น์ค ๋ฟ๋ง ์๋๋ผ Lambda์ ๊ฐ์๊ฐ ๋ง์ log group์ ๊ฐ์ ๋ํ ๋ง์์ก๊ณ ์ฅ์ ๊ฐ ๋ฐ์ํ ์ํฉ์์ ์ด๋ฅผ ์ ๋ถ Live Tail๋ก ํ์ธํ๊ธฐ๋ ์ด๋ ค์ ์ต๋๋ค. ํ์ํ ๋์ ์ ์ ํ ๋ก๊ทธ๋ฅผ ๋ฐ๋ก๋ฐ๋ก ๊ฒ์ํ ํ์๊ฐ ์์์ต๋๋ค.
์์ ๊ฐ์ ์ด์ ๋ก CloudWatch์์ ๋ฒ์ด๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก observability๋ฅผ ํ๋ณดํ๊ณ ์ ํ์ต๋๋ค. ์ด๋ฅผ ์ํด Datadog, Splunk, Whatap ๋ฑ ๋ค์ํ ์์ฉ์๋ฃจ์ , LGTM ์คํ, OpenTelemetry ๋ฑ์ ๋ชจ๋ํฐ๋ง ํด์ ์ฌ์ฉ์ ๊ฒํ ํ์ต๋๋ค. ์ฌ๋ฌ ๋ฐฉ๋ฒ๋ค์ ๊ฒํ ํ๋ฉฐ ํ๋๋ฅผ ์ ํํ๊ธฐ ์ํ ๊ธฐ์ค์ ๋ค์๊ณผ ๊ฐ์์ต๋๋ค.
- API๋ณ Latency, Count, Saturation ๋ฑ ํ์ํ Metric์ ๊ณ ํด์๋๋ก ์์งํ ์ ์์ ๊ฒ.
- ์ฌ๋ฌ ์๋น์ค๋ค์ ๊ฑธ์น ์ด๋ฒคํธ์ ๋ถ์ฐ ์ถ์ ์ด ๊ฐ๋ฅํ ๊ฒ.
- ์ค์๊ฐ์ ๊ฐ๊น์ด ๋ก๊ทธ์ ์์ง๊ณผ ๊ฐํธํ ๊ฒ์์ด ๊ฐ๋ฅํ ๊ฒ.
- ECS ๋ฟ๋ง ์๋๋ผ Lambda์์๋ ๋์ผํ ๋ชจ๋ํฐ๋ง์ด ๊ฐ๋ฅํ ๊ฒ.
- ์ด์์ ๊ณผ๋ํ ์๊ฐ ๋ฐ ๋น์ฉ์ด ๋ค์ด๊ฐ์ง ์์ ๊ฒ.
Datadog ๋ฐ Splunk ์ ๊ฒฝ์ฐ ์์ ์กฐ๊ฑด๋ค์ ๋๋ถ๋ถ ๋ง์กฑํ ์ ์๋ ๊ฐ๋ ฅํ ์๋ฃจ์ ์ด์์ง๋ง ์ด๋ฅผ ๋์ ํ๊ฒ ๋๋ฉด ํ์ฌ ์ธํ๋ผ ๋น์ฉ๊ณผ ๋ง๋จน๋ ์ถ๊ฐ๋น์ฉ์ ์ง๋ถํด์ผ๋ง ํ์ต๋๋ค. Whatap์ ๊ฒฝ์ฐ ECS, RDS์ ์์ด์ ์ข์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฉด์๋ ๊ฐ๊ฒฉ์ด ๋น๊ต์ ์ ๋ ดํ์ง๋ง Lambda์ ๋ชจ๋ํฐ๋ง์ ๋ถ๊ฐ๋ฅํด ์ ํฌ๊ฐ ์ฌ์ฉํ๊ธฐ์ ์ด๋ ต๋ค๋ ํ๋จ์ด ๋ค์๊ณ LGTM ์ ๊ฒฝ์ฐ DevOps ํ ์์ด ๋ฐฑ์๋ํ์์ ์ง์ ๋์ ํด์ ์ฌ์ฉํ๊ธฐ์ ์ด์๋์ด๋๊ฐ ๋๋ฌด ๋๊ณ ์ค์ผ์ผ์ด ํฌ๋ค๊ณ ํ๋จํ์์ต๋๋ค. ๋ฐ๋ผ์ ์ ํฌ๋ OpenTelemetry ๋ก Metric, Trace, Log ๋ฅผ ์์งํ๊ณ Self-Hosted SigNoz๋ฅผ ์ฌ์ฉํด ์๊ฐํํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ ํฌ๊ฐ ์๊ฐํ๋ ๊ธฐ๋ฅ์ ์ ๋ถ ๋ง์กฑํ ์ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค.
OpenTelemetry๋
OpenTelemetry๋ ์ฝ๋๋ฅผ ๊ณ์ธกํ๊ณ telemetry data๋ฅผ observability backend๋ก ๋ด๋ณด๋ด๋ ํ์ค์ด ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด OpenTracing๊ณผ OpenCensus๋ผ๋ ํ๋ก์ ํธ๊ฐ ํฉ์ณ์ ธ ๋ง๋ค์ด์ง CNCF ํ๋ก์ ํธ์ ๋๋ค. ๋ฐ๋ผ์ OpenTelemetry๋ฅผ ํตํด ๊ณ์ธก๋๋ traces, metrics, logs ๋ฑ telemetry data ๋ ํ์คํ๋ data ํ๋กํ ์ฝ์ธ OTLP๋ก export ๋๋ฉฐ ๋ฒค๋์ ์ข ์์ฑ์ ๊ฐ์ง์ง ์์ต๋๋ค. Observability backend๋ก Prometheus, Grafana, Jaeger, Datadog, SigNoz ๋ฑ ๋ค์ํ ์๋ฃจ์ ์ ์ ํํ ์ ์์ผ๋ฏ๋ก ์ถํ ํ์์ฑ์ด ์ข๋ ์ปค์ง๊ฒ ๋์์๋ SigNoz๋ง ๊ต์ฒดํด ๋ค๋ฅธ ๋ฐฑ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ๋ ์ ํฌ์๊ฒ ํฐ ๋งค๋ ฅ์ผ๋ก ๋ค๊ฐ์์ต๋๋ค.
OpenTelemetry๋ Agent, API, SDK ๋ฑ์ ํํ๋ก WAS์ telemetry data๋ฅผ ์์ฑํ๊ณ ์ด ๋ฐ์ดํฐ๋ฅผ Collector๋ก ์ ์กํด Collector๊ฐ ๋ฐ์ดํฐ ํ๋ก์ธ์ฑ ํ ์ธ๋ถ ๋ฐฑ์๋๋ก ์ ์กํ๋ ์ํคํ ์ณ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
์ด๋ OpenTelemetry Collector๋ฅผ ์ข๋ ์์ธํ ์ดํด๋ณด๋ฉด Receivers, Processors, Exporters ๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค. ๊ฐ๊ฐ์ ๊ตฌ์ฑ์์๋ค์ ๋ค์๊ณผ ๊ฐ์ ์ญํ ์ ํฉ๋๋ค.
Receivers
- OTLP, Jaeger, Zipkin ๋ฑ push-based protocol ์ง์ํด application์ด collector๋ก ๋ฐ์ดํฐ ์ ์ก
- ์ด๋ OTLP๋ HTTP, gRPC ๋ชจ๋ ์ฌ์ฉ๊ฐ๋ฅ
- Prometheus ๋ฑ pull-based protocol ์ง์ํด collector๊ฐ ์ง์ ๋ฐ์ดํฐ ์คํฌ๋ํ ๊ฐ๋ฅ
Processors
- Batch : ํจ์จ์ ์ธ ์ ์ก์ ์ํด ๋ฐ์ดํฐ๋ฅผ ๋ฌถ์
- Filter : ๊ด๋ จ ์๋ ๋ฐ์ดํฐ ์ ๊ฑฐ
- Normalization : ๋ฐ์ดํฐ ํ์ ๋ณํ, ํ์คํ
- Attributes : ๋ฉํ๋ฐ์ดํฐ ์ฃผ์ ์ฒ๋ฆฌ
- Sampling : ๋ฐ์ดํฐ ์ํ๋ง์ ํตํ ์ ์กฐ์
- Memory Limiter : ๋ฆฌ์์ค ์ฌ์ฉ ์ ํ ๋ฐ ๊ณผ๋ถํ ๋ฐฉ์ง
Exporters
- ๋ฐฑ์๋ ์์คํ ์ผ๋ก ๋ฐ์ดํฐ ์ ์ก
- ์ ์ก ์คํจ ์ ์ฌ์๋ ๋ก์ง ์ ๊ณต
- ์ฌ๋ฌ ๋ฐฑ์๋๊ฐ ๋ก๋๋ฐธ๋ฐ์ฑ
๋ฟ๋ง ์๋๋ผ Collector์ ํฌ์ค์ฒดํฌ, ์ธ์ฆ ๋ฐ ๊ถํ๊ด๋ฆฌ ๋ฑ ๊ธฐ๋ฅ์ ํ์ฅํ ์ ์๋ extension๋ ์ ๊ณต๋ฉ๋๋ค.
Collector์ receivers, processors, exporters ์ค์ ์ ๋ค์๊ณผ ๊ฐ์ OpenTelemetry Collector YAML ์ ํตํด ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
exporters:
otlp:
endpoint: otelcol:4317
extensions:
health_check:
pprof:
zpages:
service:
extensions: [health_check, pprof, zpages]
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
nest.js์์ OpenTelemetry client ์ฌ์ฉ
์ ํฌ๊ฐ ์ ํํ SigNoz์์๋ telemetry data๋ฅผ ์๊ฐํํ ์ ์๋ frontend, ์ ์ฅํ๋ time series database์ธ ClickHouse, OpenTelemetry collector ๊น์ง ZooKeeper๋ก ๊ด๋ฆฌํด์ค ๋ฐฑ์๋์ ์ ๊ฒฝ์ ๋ง์ด ์ฐ์ง ์๊ณ ๋ OpenTelemetry client ์ค์ ๋ง์ผ๋ก ์ด๊ธฐ ๋์ ์ ์ฝ๊ฒ ํ ์ ์์์ต๋๋ค. ์ฌ๊ธฐ์์ nest.js application์์ OpenTelemetry client๋ฅผ ์ด๋ป๊ฒ ์ค์ ํ๊ณ ์ฌ์ฉํ ์ ์๋์ง ์์๋ณด๊ฒ ์ต๋๋ค.
Automatic Instrumentation์ ํตํ OpenTelemetry ์ค์
๋จผ์ OpenTelemetry์์ ์ ๊ณตํ๋ auto instrumentation์ ํตํด ์ต์ํ์ ์ฝ๋๋ก ๊ธฐ๋ณธ์ ์ธ metrics, traces, logs ๋ฅผ ์์งํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
1. OpenTelemetry packages ์ค์น
npm install --save @OpenTelemetry/api
npm install --save @OpenTelemetry/sdk-node
npm install --save @OpenTelemetry/auto-instrumentations-node
npm install --save @OpenTelemetry/exporter-trace-otlp-http
2. tracer.ts ํ์ผ ์ค์
import { getNodeAutoInstrumentations } from '@OpenTelemetry/auto-instrumentations-node';
import { Resource } from '@OpenTelemetry/resources';
import * as OpenTelemetry from '@OpenTelemetry/sdk-node';
import { SemanticResourceAttributes } from '@OpenTelemetry/semantic-conventions';
import dotenv from 'dotenv';
dotenv.config();
// For Debug
// import { diag, DiagConsoleLogger, DiagLogLevel } from '@OpenTelemetry/api';
// diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.ALL);
const exporterOptions = {
url: 'OTEL Collector URL',
};
const traceExporter = new OTLPTraceExporter(exporterOptions);
const sdk = new OpenTelemetry.NodeSDK({
traceExporter,
instrumentations: [
getNodeAutoInstrumentations({
'@OpenTelemetry/instrumentation-fs': {
enabled: false
}
})
],
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'Service Name'
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.stage
})
});
process.on('SIGTERM', () => {
sdk.shutdown()
.then(() => console.log('Tracing terminated'))
.catch(error => console.log('Error terminating tracing', error))
.finally(() => process.exit(0));
});
export default sdk;
3. main.ts ์์ tracer ์์
// eslint-disable-next-line import/order
import tracer from './tracer';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
// tracer๋ฅผ ๊ฐ์ฅ ๋จผ์ ์์
await tracer.start();
const app = await NestFactory.create(AppModule);
// nest.js app config
// ...
await app.listen(3000);
}
bootstrap();
์ด๋ tracer๋ ๋ฐ๋์ application์ ๋ฉ์ธ ํ์ผ (ex. main.ts)์ ์ต์๋จ์ import ์์ผ์ผ ํฉ๋๋ค.
๋ฐ๋ผ์ lint์ ์ํฅ์ ๋ฐ์ง ์๋๋ก import/order๋ฅผ ํด๋น๋ผ์ธ์ ๋ฌด์ํ๋๋ก eslint-disable-next-line import/order
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
Custom Metrics ์์ง
๋ค์์ผ๋ก๋ OpenTelemetry๋ฅผ ํตํด Custom Metrics๋ฅผ ์์งํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
1. MetricsService ์์ฑ
import { Injectable } from '@nestjs/common';
import { metrics, Meter } from '@OpenTelemetry/api';
@Injectable()
export class MetricsService {
private meter: Meter;
private requestCounter;
private requestDurationHistogram;
private activeUsersGauge;
constructor() {
this.meter = metrics.getMeter('nestjs-application');
// Counter Metric ์์
this.requestCounter = this.meter.createCounter('app.request.count', {
description: 'API Count'
});
// Histogram Metric ์์
this.requestDurationHistogram = this.meter.createHistogram('app.request.duration', {
description: 'latency (ms)',
unit: 'ms'
});
// Gague Metric ์์
this.activeUsersGauge = this.meter.createObservableGauge('app.active_users', {
description: 'Active Users Gauge'
});
// active user ๋ฉํธ๋ฆญ ๋ฑ๋ก
let activeUsers = 0;
this.meter.createObservableGauge('app.active_users', {
description: 'Active Users Gauge',
callback: observableResult => {
observableResult.observe(activeUsers);
}
});
// active user ์
๋ฐ์ดํธ
this.updateActiveUsers = (count: number) => {
activeUsers = count;
};
}
// API Count ์ฆ๊ฐ
incrementRequestCount(endpoint: string, method: string, statusCode: number) {
this.requestCounter.add(1, {
endpoint,
method,
statusCode: statusCode.toString()
});
}
// API Latency ๊ธฐ๋ก
recordRequestDuration(endpoint: string, method: string, durationMs: number) {
this.requestDurationHistogram.record(durationMs, {
endpoint,
method
});
}
// ํ์ฑ ์ฌ์ฉ์ ์ ์
๋ฐ์ดํธ
updateActiveUsers: (count: number) => void;
}
2. MetricsMiddleware ์์ฑ
import { MetricsService } from './metrics.service';
export class MetricsMiddleware {
constructor(private metricsService: MetricsService) {}
use(req, res, next) {
const startTime = Date.now();
const endpoint = req.path;
const method = req.method;
// ๊ธฐ์กด ์๋ต end ๋ฉ์๋ ์ ์ฅ
const originalEnd = res.end;
// ์๋ต end ๋ฉ์๋ ์ค๋ฒ๋ผ์ด๋
res.end = function (...args) {
const duration = Date.now() - startTime;
const statusCode = res.statusCode;
// ๋ฉํธ๋ฆญ ๊ธฐ๋ก
this.metricsService.incrementRequestCount(endpoint, method, statusCode);
this.metricsService.recordRequestDuration(endpoint, method, duration);
// ์๋ end ๋ฉ์๋ ํธ์ถ
return originalEnd.apply(res, args);
}.bind({ metricsService: this.metricsService });
next();
}
}
3. app.module์ service ๋ฐ middleware ๋ฑ๋ก
import { Module } from '@nestjs/common';
import { MetricsService } from './metrics.service';
import { MetricsMiddleware } from './metrics.middleware'
import { AppController } from './app.controller';
@Module({
imports: [],
controllers: [AppController],
providers: [MetricsService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) { consumer.apply(MetricsMiddleware).forRoutes('*'); }
}
์์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ๋ชจ๋ API call์ ๋ํด API Count, API Latency, Active User Count ๋ฅผ ์ธก์ ํ ์ ์์ต๋๋ค. ๋ฟ๋ง ์๋๋ผ MetricsService ์ ๋ฐ๋ก ์ธก์ ํ custom metric์ ์ถ๊ฐํ๊ณ controller ํน์ service ๋ ๋ฒจ์์ ํด๋น metric์ ์ฆ๊ฐ์ํค๋ ๋ฐฉ๋ฒ์ผ๋ก ํน์ API์๋ง ๋ฐ๋ก metric์ ์์งํ ์ ์์ต๋๋ค.
๋ง์น๋ฉฐ
์ด๋ฒ ๊ธ์์๋ fromm ๋ฐฑ์๋ ํ์์ observability ํ๋ณด๋ฅผ ์ํด CloudWatch๋ฅผ ๋ฒ์ด๋ OpenTelemetry๋ฅผ ๋์ ํ๊ธฐ๊น์ง์ ์ฌ์ ์ ํจ๊ป ์ดํด๋ณด์์ต๋๋ค. ๋ค์ ๊ธ์์๋ ECS, K8S ํ๊ฒฝ ๋ฑ ์ผ๋ฐ์ ์ธ container ํ๊ฒฝ๊ณผ๋ ์กฐ๊ธ ๋ค๋ฅธ ์ค์ ์ ํด์ฃผ์ด์ผ ํ๋ Lambda์์ OpenTelemetry๋ฅผ ๋์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๋๊น์ง ์ฝ์ด์ฃผ์ ๋ชจ๋ ๋ถ๊ป ๊ฐ์ฌ๋๋ฆฝ๋๋ค๐โโ๏ธ