Monolitik uygulamada tek log dosyasıyla idare ederdiniz. 20 mikroservis arasında gezinen bir isteği takip etmek için ise distributed tracing şart. OpenTelemetry (OTel), CNCF''in trace/metric/log standardıdır — vendor-agnostic, tüm diller destekli.
Temel Kavramlar
İlgili rehberler: Yazılım geliştirme süreçleri · PostgreSQL optimizasyonu · Git ileri seviye komutlar · Redis nedir, nasıl kullanılır · Docker ile deploy
- Trace: Bir isteğin tüm yolculuğu (root span + çocukları)
- Span: Trace içindeki tek bir iş birimi (DB çağrısı, HTTP request)
- Trace context: Servisler arası geçen ID (W3C traceparent header)
- Exporter: Trace''i backend''e gönderen (Jaeger, Zipkin, OTLP)
Node.js Auto-Instrumentation
npm i @opentelemetry/api @opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-http
// tracing.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const sdk = new NodeSDK({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'webapp',
[SemanticResourceAttributes.SERVICE_VERSION]: '1.2.3'
}),
traceExporter: new OTLPTraceExporter({
url: 'http://otel-collector:4318/v1/traces'
}),
instrumentations: [getNodeAutoInstrumentations()]
});
sdk.start();
process.on('SIGTERM', () => sdk.shutdown());
# server.js'i çalıştırırken tracing.js'i önce yükle
node -r ./tracing.js server.js
Manuel Span
const { trace, SpanStatusCode } = require('@opentelemetry/api');
const tracer = trace.getTracer('webapp');
async function calculateReport(userId) {
return tracer.startActiveSpan('calculate-report', async span => {
span.setAttribute('user.id', userId);
try {
const data = await fetchData(userId);
span.setAttribute('data.count', data.length);
const result = processData(data);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (err) {
span.recordException(err);
span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
throw err;
} finally {
span.end();
}
});
}
Context Propagation
Bir servis başka bir servise HTTP çağrısı yaptığında traceparent header otomatik eklenir. Receiver service bu header''ı okuyup aynı trace''e devam eder.
# Otomatik eklenen header
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
# versiyon-trace_id-span_id-flags
OTel Collector
Her servisin doğrudan Jaeger''a göndermesi yerine, aradaki Collector trace''i toplar, sample''lar, zenginleştirir ve backend''e gönderir. Mimaride fan-out noktası.
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc: { endpoint: 0.0.0.0:4317 }
http: { endpoint: 0.0.0.0:4318 }
processors:
batch: {}
tail_sampling:
policies:
- name: errors
type: status_code
status_code: { status_codes: [ERROR] }
- name: slow
type: latency
latency: { threshold_ms: 500 }
- name: baseline
type: probabilistic
probabilistic: { sampling_percentage: 1 }
exporters:
otlp/jaeger:
endpoint: jaeger:4317
tls: { insecure: true }
logging: {}
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch, tail_sampling]
exporters: [otlp/jaeger, logging]
Jaeger UI
Jaeger''ı Docker ile tek container olarak kaldırabilirsiniz. Trace''leri service, operation, duration, tag ile arar ve zaman akışını grafiksel gösterir.
docker run -d --name jaeger \
-p 4317:4317 \
-p 16686:16686 \
jaegertracing/all-in-one:latest
# UI: http://localhost:16686
Sampling Stratejisi
- Head sampling: istek başında karar, ucuz ama hata trace''lerini kaçırabilir
- Tail sampling: tüm trace''i topla, sonra karar ver (collector''da). Hatalar her zaman saklanır
- Probabilistic: %1-5 örneklem genelde yeter
- Rate-limiting: saniyede max N trace
Metric ve Log Entegrasyonu
OTel sadece trace değil — metric (Prometheus alternative) ve log''ları da aynı SDK ile export eder. 3''ü birlikte: bir span''den ilgili log''lara ve metric''lere atlamak mümkün (Observability 2.0).
Vendor Seçimi
- Self-hosted: Jaeger, Tempo + Grafana, SigNoz
- SaaS: Datadog APM, New Relic, Honeycomb, Lightstep
- OTel''in en büyük faydası: vendor-agnostic — exporter değiştirerek vendor değiştirebilirsin
Modern Yazılım Geliştirme ve DevOps Pratikleri
Profesyonel yazılım geliştirme süreci üç pillar üzerine kuruludur: kaynak kontrolü (Git + GitHub/GitLab pull request akışı, code review zorunlu), CI/CD pipeline (otomatik test + lint + build + deploy), ve gözlemlenebilirlik (Sentry/Datadog/Grafana ile log, metric, trace toplama). Test piramidi (unit > integration > e2e) ile kod kalitesini garantilemek, mikroservis mimarisinde Docker container ve Kubernetes orkestrasyonu kullanmak, REST veya GraphQL API tasarımında OpenAPI/GraphQL Schema sözleşmesi tutmak modern standardlardır. Yazılım geliştirme yaşam döngüsü boyunca (gereksinim → tasarım → implementasyon → test → deploy → bakım) Agile/Scrum sprintleri 1-2 hafta, DevOps takımları sürekli teslim (continuous delivery) prensibiyle çalışır.
OpenTelemetry, Jaeger/Tempo kurulumu ve mikroservis observability için iletişime geçin