Skip to content
~/sph.sh

OpenTelemetry Temelleri: Modern Observability için Başlangıç Rehberi

Pratik implementasyon örnekleri, yaygın hatalar ve detaylı terminoloji sözlüğü ile OpenTelemetry'nin trace, metric ve log sistemlerini kapsayan kapsamlı başlangıç rehberi.

Özet

OpenTelemetry (OTel), dağıtık sistemlerden telemetri verisi toplamak için birleşik, vendor-agnostic bir yaklaşım sunan açık kaynak bir observability framework'üdür. Bu kapsamlı rehber, observability temellerini, OpenTelemetry mimarisini, çalışan kod örnekleriyle pratik implementasyon pattern'lerini ve semantic convention'lar ile sampling stratejileri gibi temel kavramları ele alıyor. Uygulamaları nasıl instrument edeceğinizi, collector'ları nasıl deploy edeceğinizi, yaygın hatalardan nasıl kaçınacağınızı ve sistemlerinize production-ready observability'yi nasıl ekleyeceğinizi öğreneceksiniz.

Giriş: Dağıtık Sistem Challenge'ı

Monolitik bir uygulamayı debug etmek basittir - birkaç log statement eklersin, sorunu reproduce edersin ve execution flow'u takip edersin. Ama tek bir kullanıcı request'inin 10-50 microservice'ten geçtiği dağıtık sistemlerde, geleneksel debugging yaklaşımları yetersiz kalır. Yavaş bir checkout request'i, payment service'teki bir database query'sinden, inventory service'teki bir cache miss'ten veya shipping service'teki bir third-party API timeout'undan kaynaklanabilir.

Challenge sadece bir şeylerin yanlış olduğunu tespit etmek değildir - metrikler ve alertler bunu halleder. Asıl zorluk neden yanlış olduğunu ve problemin dağıtık sistemde nerede başladığını anlamaktır. İşte observability tam burada kritik hale gelir.

OpenTelemetry, bu challenge'a endüstri standardı çözüm olarak ortaya çıktı. Kubernetes'ten sonra CNCF'nin en aktif ikinci projesi olan ve Google, Microsoft, Amazon ve Uber dahil 1000'den fazla organizasyonun desteğini alan OpenTelemetry, vendor lock-in olmadan telemetri verisi toplamak, işlemek ve export etmek için standardize bir yol sunuyor.

Bu rehber, temel kavramları anlamaktan uygulamalarınızda production-ready instrumentation implement etmeye kadar OpenTelemetry temellerinde size yol gösterecek.

Observability Temellerini Anlamak

Observability Nedir?

Observability, bir sistemin internal state'ini external output'larını inceleyerek anlama yeteneğidir. Önceden tanımlanmış metrikler ve alert'lere dayanan ve "ne bozuk" sorusunu yanıtlayan monitoring'den farklı olarak, observability soruları önceden bilmeden sistem davranışı hakkında rastgele sorular sormanızı sağlar.

Farkı düşünün:

Monitoring: "API error rate %5'in üzerinde" Observability: "Kullanıcı X'in checkout request'i neden 14:23'te payment service'te başarısız oldu ve o anda database query pattern'leri nasıldı?"

Monitoring size bilinen problemlerin ne zaman oluştuğunu söyler. Observability bilinmeyen problemleri araştırmanıza ve production'daki sistem davranışını anlamanıza yardımcı olur.

Üç Observability Signal'i

Modern observability, tam sistem görünürlüğü sağlamak için birlikte çalışan üç correlation'lu signal'e dayanır:

Trace'ler

Bir trace, bir request'in dağıtık sistemlerdeki tüm yolculuğunu span'lerden oluşan Directed Acyclic Graph (DAG) olarak kaydeder. Her span tek bir operation'ı temsil eder ve şunları içerir:

  • Start ve end timestamp'leri - Kesin operation timing'i
  • Operation adı - Açıklayıcı identifier (örn. "GET /api/orders")
  • Parent-child ilişkileri - Operation'ların nasıl nest olduğu ve bağlandığı
  • Attribute'lar - HTTP method, status code, database name gibi metadata
  • Event'ler - Span sırasında belirli zaman noktaları (örn. "cache miss", "retry attempt")
  • Status - Success, error veya unset

Trace'ler "Bu request her service'te ne kadar sürdü?" ve "Hangi service başarısızlığa neden oldu?" gibi soruları yanıtlar.

Metrikler

Metrikler, zaman içinde sistem performansını temsil eden aggregate edilmiş sayısal veridir:

  • Counter'lar - Monoton artan değerler (toplam request, toplam error)
  • Gauge'lar - Anlık değerler (mevcut memory kullanımı, aktif connection'lar)
  • Histogram'lar - Değer dağılımı (latency percentile'ları, response boyutları)
  • UpDownCounter'lar - Artan veya azalan değerler (queue depth, concurrent kullanıcılar)

Metrikler "95th percentile latency nedir?" ve "Service saniyede kaç request handle ediyor?" gibi soruları yanıtlar.

Log'lar

Log'lar, service'lerden belirli event'ler hakkında detaylı context sağlayan timestamp'li mesajlardır. trace_id ve span_id kullanarak trace'lerle correlation yapıldığında, log'lar önemli ölçüde daha değerli hale gelir ve bir trace'ten ilgili log mesajlarına anında atlama yapmanızı sağlar.

Log'lar "Tam error mesajı neydi?" ve "Exception oluştuğunda variable değerleri nelerdi?" gibi soruları yanıtlar.

Üç Signal'in Önemi

Her signal farklı insight'lar sağlar:

  • Metrikler problemleri tespit eder ve zaman içinde trend'leri gösterir
  • Trace'ler request flow'unu açıklar ve bottleneck'leri tanımlar
  • Log'lar detaylı event-level bilgi sağlar

Asıl güç üç signal'in correlation'ından gelir. Metriklere dayalı bir alert tetiklendiğinde, error status'üne göre trace'leri filtreleyerek başarısız request'leri tanımlarsın, problematic service'i bulmak için trace detaylarını incelersin, sonra root cause'u anlamak için correlation'lu log'lara bakarsın. Bu unified troubleshooting workflow, Mean Time To Resolution (MTTR)'ı önemli ölçüde azaltır.

OpenTelemetry Mimarisi

OpenTelemetry, birbirine bağlı birkaç component aracılığıyla eksiksiz bir observability framework sağlar. Bu mimariyi anlamak, instrumentation'ı etkili bir şekilde implement etmenize ve sorunlar ortaya çıktığında troubleshoot etmenize yardımcı olur.

API Layer

OpenTelemetry API, implementation detaylarını belirlemeden telemetri generate etmek için language-specific interface'ler tanımlar. API versiyonlar arasında stabil'dir ve şunları sağlar:

  • Tracer, meter ve logger oluşturmak için interface'ler
  • Context propagation mekanizmaları
  • SDK configure edilmediğinde no-op implementation'lar
  • Instrumentation code ile telemetri export arasında decoupling

Instrumentation kodunu API'ye göre yazarsın ve SDK gerçek implementation'ı sağlar. Bu ayrım esneklik sağlar - application kodunu değiştirmeden SDK implementation'larını değiştirebilirsin.

SDK Implementation

SDK, API specification'ı implement eder ve şunları handle eder:

  • TracerProvider initialization - Tracing infrastructure'ını kurar
  • Span lifecycle management - Span'leri oluşturur, yönetir ve export eder
  • Metric instrument registration - Counter'ları, gauge'ları, histogram'ları configure eder
  • Context propagation - Operation'lar arasında trace context'ini korur
  • Resource attribute'ları - Service'i tanımlar (name, version, environment)
  • Sampling kararları - Hangi trace'lerin tutulacağına karar verir
  • Exporter configuration - Telemetriyi destination'lara gönderir

Instrumentation Library'leri

Pre-built instrumentation library'leri, popüler framework'lerden kod değişikliği olmadan otomatik olarak telemetri yakalar. Bu library'ler, operation'ları intercept etmek ve otomatik olarak span generate etmek için bytecode injection (Java), monkey-patching (Python, Node.js) veya middleware (Go) gibi teknikler kullanır.

Yaygın instrumentation library'leri:

  • HTTP server'lar - Express, FastAPI, Spring Boot, Gin
  • HTTP client'lar - Axios, requests, HttpClient
  • Database'ler - PostgreSQL, MongoDB, Redis, MySQL
  • RPC framework'leri - gRPC, Thrift
  • Message queue'lar - Kafka, RabbitMQ, SQS, Pub/Sub

Auto-instrumentation, minimum çabayla observability değerinin %80'ini sağlar. Sonra business-specific operation'lar için manual instrumentation eklersin.

OpenTelemetry Collector

Collector, configurable pipeline'lar aracılığıyla telemetriyi alıp işleyip export eden vendor-agnostic bir proxy'dir. Application'lar ile observability backend'leri arasında ara katman görevi görür ve şunları sağlar:

Temel avantajlar:

  • Buffering ve retry'lar - Backend unavailability'yi gracefully handle eder
  • Protocol translation - Telemetri formatları arasında convert eder (OTLP, Jaeger, Zipkin)
  • Data preprocessing - Telemetriyi filtreler, transform eder ve enrich eder
  • Multi-backend export - Aynı anda birden fazla destination'a telemetri gönderir
  • Centralized configuration - Telemetri pipeline'larını tek yerden yönetir
  • Resource optimization - Batching ve compression network overhead'i azaltır

Collector pipeline component'leri:

  • Receiver'lar - Telemetriyi kabul eder (OTLP, Jaeger, Prometheus, Zipkin)
  • Processor'lar - Veriyi transform eder (batch, memory_limiter, attributes, filter)
  • Exporter'lar - Backend'lere gönderir (Jaeger, Prometheus, Elasticsearch, cloud services)

Başlarken: Pratik Implementation

Çalışan örneklerle OpenTelemetry instrumentation'ı implement edelim. Hemen değer elde etmek için auto-instrumentation ile başlayacağız, sonra business logic için manual instrumentation ekleyeceğiz.

Node.js Auto-Instrumentation

İlk olarak gerekli paketleri yükle:

bash
npm install @opentelemetry/sdk-node \            @opentelemetry/auto-instrumentations-node \            @opentelemetry/exporter-trace-otlp-grpc \            @opentelemetry/semantic-conventions

Application kodunu import etmeden önce OpenTelemetry'yi initialize etmek için tracing.js oluştur:

javascript
// tracing.js - Bunu ilk olarak import et, diğer import'lardan önceconst { NodeSDK } = require('@opentelemetry/sdk-node');const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');const { Resource } = require('@opentelemetry/resources');const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } = require('@opentelemetry/semantic-conventions');
// Service'ini tanımlamak için resource attribute'ları configure etconst resource = new Resource({  [ATTR_SERVICE_NAME]: 'payment-service',  [ATTR_SERVICE_VERSION]: '1.2.0',});
// OTLP exporter'ı configure et (local dev için console exporter'a değiştir)const traceExporter = new OTLPTraceExporter({  url: 'http://localhost:4317', // OpenTelemetry Collector endpoint});
// Auto-instrumentation ile SDK'yı initialize etconst sdk = new NodeSDK({  resource,  traceExporter,  instrumentations: [getNodeAutoInstrumentations()],});
// SDK'yı başlatsdk.start();
// Graceful shutdownprocess.on('SIGTERM', () => {  sdk.shutdown()    .then(() => console.log('Tracing terminated'))    .catch((error) => console.log('Error terminating tracing', error))    .finally(() => process.exit(0));});

Application entry point'ini tracing'i önce import edecek şekilde güncelle:

javascript
// server.jsrequire('./tracing'); // İlk import olmalı
const express = require('express');const app = express();
app.get('/api/orders/:id', async (req, res) => {  // Bu HTTP request otomatik olarak trace ediliyor  const order = await fetchOrder(req.params.id);  res.json(order);});
app.listen(3000, () => {  console.log('Server running on port 3000');});

Application'ını başlat:

bash
node server.js

Her HTTP request artık ek kod olmadan otomatik olarak trace ediliyor. Auto-instrumentation HTTP method, URL, status code ve response time'ı otomatik olarak yakalar.

Python Auto-Instrumentation

OpenTelemetry paketlerini yükle:

bash
pip install opentelemetry-distro \            opentelemetry-exporter-otlp \            opentelemetry-instrumentation-flask

Flask app'ini oluşturmadan önce instrumentation'ı initialize et:

python
# app.pyfrom opentelemetry import tracefrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporterfrom opentelemetry.sdk.resources import Resourcefrom opentelemetry.semconv.attributes import ATTR_SERVICE_NAME, ATTR_SERVICE_VERSIONfrom opentelemetry.instrumentation.flask import FlaskInstrumentor
# Resource attribute'larını configure etresource = Resource.create({    ATTR_SERVICE_NAME: "order-service",    ATTR_SERVICE_VERSION: "1.0.0",})
# Tracer provider'ı initialize etprovider = TracerProvider(resource=resource)processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4317"))provider.add_span_processor(processor)trace.set_tracer_provider(provider)
# Flask app'i oluşturfrom flask import Flask, jsonifyapp = Flask(__name__)
# Flask'ı auto-instrument etFlaskInstrumentor().instrument_app(app)
@app.route('/api/orders/<order_id>')def get_order(order_id):    # Bu endpoint otomatik olarak trace ediliyor    order = fetch_order_from_db(order_id)    return jsonify(order)
if __name__ == '__main__':    app.run(port=5000)

Application'ını çalıştır:

bash
python app.py

Business Logic için Manual Instrumentation

Auto-instrumentation framework-level operation'ları yakalar, ama business logic için manual span'lere ihtiyacın var:

javascript
// Node.js manual instrumentationconst { trace, SpanStatusCode } = require('@opentelemetry/api');
async function processPayment(orderId, amount) {  const tracer = trace.getTracer('payment-service');
  // Bu business operation için custom span oluştur  return await tracer.startActiveSpan('processPayment', async (span) => {    try {      // Business context'i span attribute olarak ekle      span.setAttribute('order.id', orderId);      span.setAttribute('payment.amount', amount);      span.setAttribute('payment.currency', 'USD');
      // Payment processing'i simulate et      const result = await chargeCustomer(amount);
      // Result bilgisini ekle      span.setAttribute('payment.transaction_id', result.transactionId);      span.setAttribute('payment.status', 'success');
      span.setStatus({ code: SpanStatusCode.OK });      return result;
    } catch (error) {      // Error bilgisini kaydet      span.recordException(error);      span.setStatus({        code: SpanStatusCode.ERROR,        message: error.message,      });      throw error;    } finally {      span.end(); // Her zaman span'i bitir    }  });}

Python manual instrumentation:

python
# Python manual instrumentationfrom opentelemetry import tracefrom opentelemetry.trace import Status, StatusCode
tracer = trace.get_tracer(__name__)
def process_order(order_id):    with tracer.start_as_current_span("process_order") as span:        try:            # Business context ekle            span.set_attribute("order.id", order_id)            span.set_attribute("order.type", "express")
            # Business logic'i gerçekleştir            order = validate_order(order_id)            span.set_attribute("order.items_count", len(order.items))
            inventory_result = check_inventory(order)            span.set_attribute("inventory.available", inventory_result.available)
            # Payment operation için nested span            with tracer.start_as_current_span("charge_payment") as payment_span:                payment_span.set_attribute("payment.amount", order.total)                payment_result = charge_customer(order)                payment_span.set_attribute("payment.status", payment_result.status)
            span.set_status(Status(StatusCode.OK))            return {"success": True, "order_id": order_id}
        except Exception as e:            span.record_exception(e)            span.set_status(Status(StatusCode.ERROR, str(e)))            raise

Service'ler Arası Context Propagation

Distributed tracing'in çalışması için trace context'inin service boundary'leri arasında flow etmesi gerekir. OpenTelemetry, W3C Trace Context standardını kullanarak context'i HTTP header'larında propagate eder.

Auto-instrumentation bunu otomatik olarak handle eder HTTP request'leri için:

javascript
// Service A, Service B'ye HTTP request yaparconst axios = require('axios');
// OpenTelemetry auto-instrumentation otomatik olarak// traceparent ve tracestate header'larını bu request'e inject ederconst response = await axios.get('http://service-b/api/data');

Manual HTTP client'lar veya message queue'lar için context'i explicit olarak inject et:

javascript
const { propagation, context } = require('@opentelemetry/api');
// Mevcut context'i alconst ctx = context.active();
// Context'i HTTP header'larına inject etconst headers = {};propagation.inject(ctx, headers);
// Propagate edilmiş header'larla request yapawait fetch('http://service-b/api/data', { headers });

Python context propagation:

python
from opentelemetry import propagatefrom opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagatorimport requests
# Trace context'ini header'lara inject etheaders = {}propagate.inject(headers)
# Propagate edilmiş context ile request yapresponse = requests.get('http://service-b/api/data', headers=headers)

OpenTelemetry Collector Configuration

Collector, application'lar ile observability backend'leri arasında kritik bir ara katman görevi görür. İşte production-ready bir configuration:

yaml
# otel-collector-config.yamlreceivers:  otlp:    protocols:      grpc:        endpoint: 0.0.0.0:4317      http:        endpoint: 0.0.0.0:4318
processors:  # Memory limiter OOM crash'lerini önler  memory_limiter:    check_interval: 1s    limit_mib: 512    spike_limit_mib: 128
  # Batch processor network overhead'i azaltır  batch:    timeout: 200ms    send_batch_size: 8192    send_batch_max_size: 10000
  # Resource attribute'ları ekle  resource:    attributes:      - key: deployment.environment        value: production        action: upsert
exporters:  # Trace'leri Jaeger'a gönder  jaeger:    endpoint: jaeger-collector:14250    tls:      insecure: true
  # Metrikleri Prometheus'a gönder  prometheus:    endpoint: "0.0.0.0:8889"
  # Debug için console exporter  logging:    loglevel: info
service:  pipelines:    traces:      receivers: [otlp]      processors: [memory_limiter, batch, resource]      exporters: [jaeger, logging]
    metrics:      receivers: [otlp]      processors: [memory_limiter, batch]      exporters: [prometheus]

Collector'ı Docker ile deploy et:

bash
docker run -d --name otel-collector \  -p 4317:4317 \  -p 4318:4318 \  -p 8889:8889 \  -v $(pwd)/otel-collector-config.yaml:/etc/otel-collector-config.yaml \  otel/opentelemetry-collector:latest \  --config=/etc/otel-collector-config.yaml

Collector Deployment Pattern'leri

Agent Pattern:

  • Her application'ın yanında sidecar veya DaemonSet olarak collector deploy et
  • Gateway'e göndermeden önce local aggregation yapar
  • Network trafiğini azaltır ama resource consumption'ı artırır

Gateway Pattern:

  • Centralized collector service
  • Tüm application'lar gateway'e telemetri gönderir
  • Managment'i basitleştirir ama potential bottleneck oluşturur

Hierarchical Pattern (Önerilen):

  • Agent'lar basic processing ile locally collect eder
  • Gateway'ler heavy processing ve routing yapar
  • Reliability ve performance'ın en iyi dengesi

Temel Kavramlar

Semantic Convention'lar

Semantic convention'lar, interoperability için attribute isimlendirmeyi standardize eder. Herkes method, request.method veya http_method gibi varyasyonlar yerine http.method kullandığında, observability tool'ları service'ler arasında consistent analiz sağlar.

Attribute isimlendirme kuralları:

  • Lowercase ve underscore kullan (snake_case)
  • Namespace prefix ile başla (http., db., messaging.)
  • Custom attribute'lar için reverse domain notation kullan (com.company.attribute)

Yaygın semantic convention namespace'leri:

javascript
// HTTP operation'larspan.setAttribute('http.method', 'GET');span.setAttribute('http.route', '/api/orders/:id');span.setAttribute('http.status_code', 200);span.setAttribute('http.url', 'https://api.example.com/orders/123');
// Database operation'larspan.setAttribute('db.system', 'postgresql');span.setAttribute('db.name', 'orders_db');span.setAttribute('db.statement', 'SELECT * FROM orders WHERE id = $1');span.setAttribute('db.operation', 'SELECT');
// Messaging operation'larspan.setAttribute('messaging.system', 'kafka');span.setAttribute('messaging.destination', 'order-events');span.setAttribute('messaging.operation', 'publish');
// RPC operation'larspan.setAttribute('rpc.system', 'grpc');span.setAttribute('rpc.service', 'OrderService');span.setAttribute('rpc.method', 'GetOrder');
// Exception bilgisispan.setAttribute('exception.type', 'PaymentException');span.setAttribute('exception.message', 'Insufficient funds');

Sampling Stratejileri

Scale'de, trace'lerin %100'ünü collect etmek prohibitively expensive hale gelir. Saniyede 10,000 request işleyen high-traffic bir service, massive telemetri volume generate eder. Sampling, görünürlüğü korurken maliyetleri azaltır.

Head-Based Sampling:

Karar trace root'ta verilir. Basit probabilistic sampling tüm trace'lerin bir yüzdesini tutar:

javascript
// Tüm trace'lerin %10'unu sample etconst { NodeSDK } = require('@opentelemetry/sdk-node');const { TraceIdRatioBasedSampler } = require('@opentelemetry/sdk-trace-base');
const sdk = new NodeSDK({  sampler: new TraceIdRatioBasedSampler(0.1), // %10 sampling  // ... diğer config});

Tail-Based Sampling:

Karar trace tamamlandıktan sonra verilir. Collector, tutup tutmamaya karar vermeden önce full trace'i inceler. Bu intelligent sampling sağlar:

  • Error'ların %100'ünü tut
  • Latency threshold'ları aşan trace'leri tut
  • Belirli kullanıcılar veya operation'lar için trace'leri tut
  • Başarılı fast trace'leri drop et

Tail-based sampling collector configuration gerektirir:

yaml
# Collector tail sampling configurationprocessors:  tail_sampling:    decision_wait: 10s    num_traces: 100000    policies:      - name: errors        type: status_code        status_code:          status_codes: [ERROR]      - name: slow-traces        type: latency        latency:          threshold_ms: 1000      - name: probabilistic        type: probabilistic        probabilistic:          sampling_percentage: 5

Pratik sampling stratejisi:

  1. Implementation sırasında %100 sampling ile başla
  2. Instrumentation'ı validate ettikten sonra %10'da head-based sampling ekle
  3. Tüm error'ları tutmak için tail-based sampling implement et
  4. Veri değerini anladıkça baseline sampling'i azalt
  5. Sampling effectiveness'ını monitor et - gerçek issue'ları yakalıyor musun?

Resource Attribute'ları

Resource attribute'ları telemetri kaynağını tanımlar ve bir service'ten gelen tüm signal'lerde consistent olmalıdır:

javascript
const { Resource } = require('@opentelemetry/resources');const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } = require('@opentelemetry/semantic-conventions');
const resource = new Resource({  [ATTR_SERVICE_NAME]: 'payment-service',  [ATTR_SERVICE_VERSION]: '2.1.0',  'deployment.environment': 'production',  'service.instance.id': process.env.HOSTNAME,  'cloud.provider': 'aws',  'cloud.region': 'us-east-1',  'cloud.availability_zone': 'us-east-1a',});

Resource attribute'ları şunları sağlar:

  • Environment veya version'a göre trace'leri filtreleme
  • Region veya availability zone'a göre metrikleri gruplama
  • Issue'ları belirli deployment'larla correlation yapma
  • Infrastructure-level pattern'leri anlama

Yaygın Hatalar ve Çözümleri

1. Late Initialization

Problem: OpenTelemetry SDK'yı application framework'lerini import ettikten sonra initialize etmek missed instrumentation'a neden olur. Auto-instrumentation module import'larını intercept etmeye dayanır.

Semptom: Eksik HTTP veya database span'leri olan incomplete trace'ler.

Çözüm: OpenTelemetry'yi herhangi bir application import'undan önce import et ve initialize et:

javascript
// Yanlış - app tracing'den önce import edilmişconst express = require('express');require('./tracing');
// Doğru - tracing önce import edilmişrequire('./tracing');const express = require('express');

2. High Cardinality Attribute'lar

Problem: Span attribute olarak unbounded değerler eklemek (user ID'ler, timestamp'ler, query parameter'lı full URL'ler) milyonlarca unique combination oluşturur ve storage'ı overwhelm eder.

Semptom: Massive storage maliyetleri, yavaş query'ler, backend veriyi reject ediyor.

Çözüm: Attribute'lar için bounded değerler kullan. Unbounded değerleri span event olarak store et:

javascript
// Yanlış - high cardinalityspan.setAttribute('user.id', userId); // Milyonlarca unique kullanıcıspan.setAttribute('order.timestamp', Date.now()); // Her request'te uniquespan.setAttribute('http.url', fullUrlWithParams); // Request başına unique
// Doğru - bounded değerlerspan.setAttribute('http.route', '/api/orders/:id'); // Sınırlı route'larspan.setAttribute('user.tier', 'premium'); // Az sayıda tierspan.addEvent('order_created', { 'order.id': orderId }); // Event, attribute değil

3. Eksik Context Propagation

Problem: Service boundary'leri arasında trace context propagate edilmemesi, ayrı operation'lar gibi görünen broken trace'lere neden olur.

Semptom: Her service isolated span'ler gösteriyor; service'ler arası request flow'u takip edilemiyor.

Çözüm: HTTP client'ların trace context header'larını içerdiğinden emin ol. Auto-instrumentation kullan veya context'i manuel olarak inject et:

python
# Context propagation'ı verify etfrom opentelemetry import propagateimport requests
headers = {}propagate.inject(headers)  # Trace context'i inject etprint(f"Headers: {headers}")  # traceparent içermeli
response = requests.get('http://service-b/api/data', headers=headers)

4. Memory Limiter'ları Unutmak

Problem: Memory limiter olmayan collector'lar, traffic spike'larında telemetri buffering mevcut memory'yi aştığında crash olur.

Semptom: OOM error'larıyla collector crash'leri; telemetri verilerinde gap'ler.

Çözüm: Batch processor'dan önce her zaman memory_limiter processor configure et:

yaml
processors:  memory_limiter:    check_interval: 1s    limit_mib: 512  # Container memory'nin %80'i  batch:    timeout: 200ms
service:  pipelines:    traces:      processors: [memory_limiter, batch]  # memory_limiter İLK

5. Over-Instrumentation

Problem: Her function call için span oluşturmak massive span count generate eder, trace'leri analiz etmeyi zorlaştırır ve maliyetleri artırır.

Semptom: Basit request'ler için 500+ span'li trace'ler; yavaş query'ler; bottleneck'leri tanımlamak zor.

Çözüm: Sadece service boundary'lerinde ve kritik business operation'larda instrument et:

javascript
// Yanlış - çok fazla spanfunction processOrder(order) {  return tracer.startActiveSpan('processOrder', (span1) => {    const validated = tracer.startActiveSpan('validateOrder', (span2) => {      const result = tracer.startActiveSpan('checkFields', (span3) => {        // Her küçük fonksiyon trace ediliyor      });    });  });}
// Doğru - stratejik span'lerfunction processOrder(order) {  return tracer.startActiveSpan('processOrder', async (span) => {    span.setAttribute('order.id', order.id);
    // Internal validation trace edilmemiş - hızlı    validateOrder(order);
    // Sadece önemli operation'ları trace et    const payment = await tracer.startActiveSpan('chargePayment', async (paymentSpan) => {      return await chargeCustomer(order.total);    });  });}

Guideline: İyi tasarlanmış trace'te service başına 5-15 span olur, yüzlerce değil.

6. Semantic Convention'ları İgnore Etmek

Problem: Standard convention'lar yerine custom attribute isimleri kullanmak interoperability'yi bozar ve automatic backend analizi önler.

Semptom: Dashboard'lar populate olmuyor; automatic service map'ler yok; standard metrikler eksik.

Çözüm: Her zaman OpenTelemetry semantic convention'larına refer et:

javascript
// Yanlış - custom isimlerspan.setAttribute('request_method', 'GET');span.setAttribute('status', 200);span.setAttribute('db_type', 'postgres');
// Doğru - semantic convention'larspan.setAttribute('http.method', 'GET');span.setAttribute('http.status_code', 200);span.setAttribute('db.system', 'postgresql');

7. Collector Olmadan Doğrudan Export

Problem: Application'ların doğrudan observability backend'lerine export etmesi tight coupling yaratır ve single point of failure oluşturur.

Semptom: Backend down olduğunda application takılıyor; retry logic yok; buffering yok.

Çözüm: Application'lar ile backend'ler arasında her zaman OpenTelemetry Collector kullan:

javascript
// Doğru - collector'a export etconst traceExporter = new OTLPTraceExporter({  url: 'http://otel-collector:4317', // Doğrudan backend'e değil collector'a});

İstisna: Collector overhead'inin prohibitive olduğu serverless function'lar doğrudan export edebilir.

8. Inconsistent Resource Attribute'lar

Problem: Service'lerin resource attribute'ları için farklı formatlar kullanması correlation'ı ve filtrelemeyi önler.

Semptom: Service'ler dashboard'larda duplicate görünüyor; environment'a göre filtre yapılamıyor; broken dependency'ler.

Çözüm: Organizasyon genelinde resource attribute'ları standardize et:

javascript
// Standardize edilmiş formatconst resource = new Resource({  'service.name': 'payment-service',  // Her zaman kebab-case  'service.version': '1.2.0',         // Her zaman semantic versioning  'deployment.environment': 'production', // Her zaman lowercase: dev/staging/production});

9. Instrumentation'ı Test Etmemek

Problem: Instrumentation kodu test edilmediğinde production'da failure'lar ortaya çıkıyor.

Semptom: Production'da eksik span'ler, yanlış attribute'lar keşfediliyor.

Çözüm: Instrumentation için test'ler yaz:

javascript
const { InMemorySpanExporter } = require('@opentelemetry/sdk-trace-base');
describe('Payment Processing', () => {  let spanExporter;
  beforeEach(() => {    spanExporter = new InMemorySpanExporter();    // SDK'yı in-memory exporter ile configure et  });
  it('creates span with correct attributes', async () => {    await processPayment('order-123', 99.99);
    const spans = spanExporter.getFinishedSpans();    expect(spans).toHaveLength(1);    expect(spans[0].name).toBe('processPayment');    expect(spans[0].attributes['order.id']).toBe('order-123');    expect(spans[0].attributes['payment.amount']).toBe(99.99);  });});

10. Erken Aggressive Sampling

Problem: Rollout sırasında aggressive sampling (%0.1) implement etmek instrumentation issue'larını keşfetmeyi önler.

Semptom: Problemler için eksik trace'ler; instrumentation validate edilemiyor.

Çözüm: Initial implementation sırasında yüksek sampling rate (%50-100) ile başla. Veri değerini anladıkça kademeli olarak azalt.

OpenTelemetry Terminoloji Sözlüğü

Temel Kavramlar

Observability Bir sistemin internal state'ini external output'larını (trace'ler, metrikler, log'lar) inceleyerek anlama yeteneği. Önceden tanımlanmış monitoring olmadan sistem davranışı hakkında rastgele sorular sormanızı sağlar.

Telemetry Sistemlerin operation'larını tanımlayan verileri. OpenTelemetry context'inde trace'leri, metrikleri ve log'ları ifade eder.

Signal Telemetri verisinin bir kategorisi. OpenTelemetry üç signal tanımlar: trace'ler, metrikler ve log'lar.

Instrumentation Telemetri verisi generate eden kod. Automatic (library'ler aracılığıyla) veya manual (custom kod) olabilir.

Tracing Terminolojisi

Trace Tek bir request'in dağıtık sistemlerdeki yolculuğunun span'lerden oluşan Directed Acyclic Graph (DAG) olarak eksiksiz kaydı.

Span Bir trace içindeki tek bir operation; start time, end time, operation adı, attribute'lar, event'ler ve parent-child ilişkileri içerir.

Trace Context Span'leri complete trace'lere correlate etmek için service boundary'leri arasında propagate edilen metadata. Trace ID, span ID ve sampling kararını içerir.

Span Attribute'ları Metadata sağlayan span'lere eklenmiş key-value pair'ler (örn. http.method, db.statement).

Span Event'leri Span lifetime sırasında discrete occurrence'ları temsil eden timestamp'li mesajlar (örn. "cache miss", "retry attempt").

Span Status Operation'ın succeed olup olmadığını (OK), fail olup olmadığını (ERROR) veya status'ün unknown (UNSET) olduğunu gösterir.

Parent Span Child span'leri başlatan span, operation nesting'i gösteren hiyerarşik ilişkiler oluşturur.

Root Span Bir trace'teki ilk span, request'in sisteme entry point'ini temsil eder.

Context Propagation Trace context'ini service boundary'leri arasında geçirmek için mekanizma, distributed tracing'i mümkün kılar. HTTP header'ları aracılığıyla W3C Trace Context standardını kullanır.

Baggage Cross-cutting concern'lar (user ID, feature flag'ler) için trace context'i ile birlikte propagate edilen key-value pair'ler. Span verisine dahil değil.

Metrik Terminolojisi

Metric Zaman içinde capture edilen sistem performansının aggregate edilmiş sayısal ölçümü.

Counter Cumulative değerleri temsil eden monoton artan metrik (toplam request'ler, toplam error'lar).

Gauge Artabilen veya azalabilen point-in-time ölçüm (mevcut memory kullanımı, aktif connection'lar).

Histogram Min, max, sum, count ve bucket'ları kaydeden ölçüm dağılımı (latency dağılımı, response boyutları).

UpDownCounter Artabilen veya azalabilen metrik, yukarı ve aşağı giden değerleri track eder (queue depth, concurrent kullanıcılar).

Metric Instrument Ölçümleri kaydetmek için API interface'i (meter aracılığıyla oluşturulur).

Aggregation Metrik ölçümlerini zaman içinde ve dimension'lar arasında combine etme yöntemi.

Collector Terminolojisi

Collector Configurable pipeline'lar aracılığıyla telemetri verisini alıp işleyip export eden vendor-agnostic proxy.

Receiver Çeşitli protokoller (OTLP, Jaeger, Zipkin, Prometheus) aracılığıyla telemetri verisini kabul eden collector component'i.

Processor Telemetri verisini transform eden collector component'i (batching, filtering, attribute modification, sampling).

Exporter İşlenmiş telemetriyi observability backend'lerine gönderen collector component'i.

Pipeline Collector'daki receiver'lar, processor'lar ve exporter'lar aracılığıyla configure edilmiş telemetri flow'u.

OTLP (OpenTelemetry Protocol) Telemetri verisini transmit etmek için native protokol. gRPC (port 4317) ve HTTP (port 4318) destekler.

Sampling Terminolojisi

Sampling İstatistiksel önemi korurken sadece trace'lerin bir subset'ini tutarak telemetri volume'ünü azaltma tekniği.

Head-Based Sampling Complete trace'i görmeden trace root'ta verilen sampling kararı. Basit ama intelligent kararlar veremez.

Tail-Based Sampling Trace tamamlandıktan sonra verilen sampling kararı, trace karakteristiklerine (error'lar, latency) dayalı intelligent sampling'i mümkün kılar.

Sampling Rate Tutulan trace'lerin yüzdesi. 0.1, trace'lerin %10'unun sample edildiği anlamına gelir.

Sampler Configure edilmiş stratejiye dayalı sampling kararları veren component.

Semantic Convention Terminolojisi

Semantic Convention'lar Interoperability sağlayan attribute'lar, metrikler ve resource attribute'ları için standardize edilmiş isimlendirme convention'ları.

Resource Attribute'ları Telemetri kaynağını tanımlayan attribute'lar (service adı, version, environment, cloud provider).

Attribute Namespace İlgili attribute'ları gruplayan prefix (http.*, db.*, messaging.*).

Span Kind Span'in trace'teki rolünü tanımlayan kategori: INTERNAL, SERVER, CLIENT, PRODUCER, CONSUMER.

API ve SDK Terminolojisi

API Implementation'ı prescribe etmeden telemetri generate etmenin nasıl yapılacağını tanımlayan language-specific interface'ler.

SDK Telemetri generate etmek ve export etmek için gerçek functionality sağlayan API specification'ın implementation'ı.

TracerProvider Tracer'ları oluşturmak için factory, exporter'lar, sampler'lar ve processor'larla configure edilir.

Tracer Belirli bir instrumentation scope içinde span'leri oluşturmak için interface (library veya service).

MeterProvider Metrik kaydetmek için kullanılan meter'ları oluşturmak için factory.

Meter Metrik instrument'ları (counter'lar, gauge'lar, histogram'lar) oluşturmak için interface.

Resource Resource attribute'larla tanımlanan telemetri üreten entity'nin immutable temsili.

Propagator Trace context'ini boundary'ler arasında inject etmekten ve extract etmekten sorumlu component.

Yaygın Kısaltmalar

OTel - OpenTelemetry OTLP - OpenTelemetry Protocol CNCF - Cloud Native Computing Foundation APM - Application Performance Monitoring SLI - Service Level Indicator SLO - Service Level Objective MTTR - Mean Time To Resolution MTTD - Mean Time To Detection RED - Rate, Errors, Duration (key metrikler) DAG - Directed Acyclic Graph W3C - World Wide Web Consortium

Sonraki Adımlar ve Kaynaklar

Önerilen Öğrenme Yolu

  1. Local environment'ı kur Experimentation için Docker Compose kullanarak OpenTelemetry Collector ve Jaeger deploy et

  2. Sample bir service'i instrument et Hemen sonuç görmek için Node.js veya Python'da auto-instrumentation ile başla

  3. Manual instrumentation ekle Manual instrumentation pattern'lerini anlamak için business logic için custom span'ler oluştur

  4. Staging'e deploy et Realistic traffic ile collector configuration'ı ve sampling stratejilerini test et

  5. Correlation implement et Log'lara trace_id ekle ve trace'lerden metrikler generate et

  6. Production'a roll out yap Non-critical service'lerle başlayarak incremental olarak deploy et

Official Kaynaklar

Dokümantasyon:

Community:

Öğrenme:

Önerilen Backend'ler

Open Source:

  • Jaeger - Distributed tracing odaklı
  • Grafana Tempo - Scalable trace storage
  • Prometheus - Metrik monitoring
  • SigNoz - Unified observability platform

Commercial:

  • Datadog - Comprehensive observability
  • Honeycomb - Query-driven exploration
  • New Relic - Full-stack observability
  • Lightstep - Enterprise tracing

Sonuç

OpenTelemetry, dağıtık sistemlerde observability için endüstri standardı yaklaşımı sağlıyor. Auto-instrumentation implement ederek, collector'ları deploy ederek, semantic convention'ları takip ederek ve signal'leri correlate ederek, debugging'i saatler süren investigation'lardan dakikalara dönüştüren derin sistem görünürlüğü elde edersin.

Bir service ile başla, yaklaşımı validate et ve incremental olarak genişlet. Setup ve öğrenmedeki initial investment, daha hızlı incident resolution, önlenen outage'lar ve gelişmiş sistem anlayışı sayesinde kendini geri öder.

OpenTelemetry ile çalışmak bana observability'nin mümkün olan tüm veriyi toplamakla ilgili olmadığını gösterdi - doğru veriyi, doğru zamanda, doğru context ile toplamakla ilgili. Burada açıklanan framework'ler ve pattern'ler bu foundation'ı sağlıyor.

OpenTelemetry ecosystem'i yeni instrumentation library'leriyle, enhanced collector capability'leriyle ve expanded semantic convention'larla evrim geçirmeye devam ediyor. Bugün OpenTelemetry'ye yatırım yapmak, observability'nin geleceğine yatırım yapmak demek - vendor-neutral, standards-based ve community-driven bir gelecek.

İlgili Yazılar