APM Best Practices: Dos and Don'ts Guide für Praktiker

blog-APM_Best_Practices.jpg

Application Performance Management (APM) ist die Praxis der regelmäßigen Überwachung, Messung und Analyse der Leistung und Verfügbarkeit von Softwareanwendungen. APM hilft Ihnen, Einblicke in komplexe Microservice-Umgebungen zu gewinnen, die Site Reliability Engineering (SRE)-Teams überfordern können. Die gewonnenen Erkenntnisse schaffen eine optimale Benutzererfahrung und erzielen die gewünschten Geschäftsergebnisse. Es ist ein komplexer Prozess, aber das Ziel ist klar: Sicherzustellen, dass eine Anwendung reibungslos läuft und die Erwartungen der Nutzer und Unternehmen erfüllt. 

Ein klares Verständnis des Betriebs einer Anwendung und eine proaktive APM-Praxis sind entscheidend für die Aufrechterhaltung leistungsstarker Softwareanwendungen. APM sollte nicht nur ein nachträglicher Gedanke sein. Es sollte von Anfang an berücksichtigt werden. Bei proaktiver Implementierung kann es in die Ausführung der Software integriert werden, indem Monitoring-Komponenten direkt in die Anwendung eingebettet werden.

Was ist Application Performance Management?

Application Performance Management umfasst die kontinuierliche Überwachung, Analyse und Verwaltung der Backend- und Frontend-Leistung einer Anwendung. Die Anwendungsüberwachung wird erweitert und weiterentwickelt, aber die APM-Strategie sollte nicht in Silos erstellt werden. Es ist wichtig, mehrere Stakeholder, Geschäftsexperten, Anwendungsentwickler und Betriebsteams einzubeziehen. Eine erfolgreiche APM-Strategie geht über die Verfügbarkeit oder den Serverzustand hinaus und konzentriert sich auf Application Service Level Objectives (SLOs), bevor sie für die Benutzer zu einem Problem werden. 

Die moderne APM-Implementierung umfasst die Instrumentierung Ihrer Anwendungen, um drei Arten von Telemetriedaten zu erfassen: Traces (Anforderungsflüsse), Metriken (aggregierte Messwerte) und Logs (diskrete Ereignisse). Die Herausforderung besteht nicht nur darin, Daten zu erfassen, sondern die richtigen Daten ohne die Leistung zu beeinträchtigen.

Erfahren Sie mehr über Beobachtbarkeitsmetriken.

Es gibt zahlreiche Instrumentierungsansätze, aber die effektivste Strategie kombiniert die automatische Instrumentierung (für Frameworks und Bibliotheken) mit der manuellen Instrumentierung (für Geschäftslogik). Die automatische Instrumentierung mithilfe von OpenTelemetry-Agenten kann 80 % Ihrer Beobachtbarkeitsanforderungen mit minimalen Codeänderungen erfassen:

# Auto-instrumentation handles this automatically
@app.route('/api/orders')
def create_order():
    # Add manual span only for critical business logic
    with tracer.start_as_current_span("order.validation") as span:
        span.set_attribute("order.value", order_total)
        if not validate_order(order_data):
            span.set_status(Status(StatusCode.ERROR))
            return 400

  • Do: Beginnen Sie mit der automatischen Instrumentierung, und fügen Sie dann manuelle Bereiche für geschäftskritische Abläufe hinzu.

  • Don't: Instrumentieren Sie nicht jeden Funktionsaufruf manuell – Sie erzeugen Performance-Overhead und Rauschen.

  • Fallstrick: Eine Überinstrumentierung kann 15%–20% Latenz hinzufügen. Überwachen Sie Ihr Monitoring mit Leistungsvergleichen anhand von Basislinien.

Einige Komponenten, die eine Organisation oder ein Unternehmen bei der Entwicklung einer APM-Strategie berücksichtigen sollte, sind:

  • Performance-Monitoring, einschließlich der Bewertung von Latenz, Service-Level-Zielen, Reaktionszeit, Durchsatz und Anfragevolumen

  • Fehlerverfolgung, einschließlich Ausnahmen, Abstürze und fehlgeschlagene API-Aufrufe 

  • Infrastruktur-Monitoring, einschließlich der Überwachung der Integrität und Ressourcennutzung von Servern, Containern und Cloud-Umgebungen, die die Anwendung unterstützen

  • Nutzererfahrungsmetriken, einschließlich Ladezeiten, Sitzungsleistung, Klickpfade und Browser- oder Gerätedetails (Es muss berücksichtigt werden, dass selbst wenn die Systemmetriken in Ordnung sind, Benutzer immer noch Leistungsprobleme haben können.)

Wichtige Prinzipien des effektiven APM

Die Kernprinzipien eines effektiven Application Performance Management sind durchgängige Transparenz (vom Browser des Nutzers bis zur Datenbank), Echtzeit-Monitoring und -Einblicke sowie kontextbezogene Einblicke mit Fokus auf Nutzer- und Geschäftsziele. APM kann die Skalierbarkeit von Anwendungen verbessern, indem es kontinuierliche Verbesserungen ermöglicht und die Leistung im Laufe der Zeit steigert.

  • Do: Implementieren Sie Echtzeit-Dashboards mit SLO-basierten Warnungen anstelle von willkürlichen Schwellenwerten.

  • Don't: Verlassen Sie sich nur auf regelmäßige Leistungsüberprüfungen oder CPU-/Speicherwarnungen – Metriken zur Benutzererfahrung des Geräts.

  • Pitfall: Alarmmüdigkeit durch niedrigstufige Systemmetriken. Konzentrieren Sie sich auf nutzerorientierte SLOs, die auf echte Probleme hinweisen.

Bei der Erstellung einer APM-Strategie sind einige wichtige Grundsätze zu beachten:

1. Proaktives Monitoring: Verhindern Sie Probleme, bevor sie sich auf Nutzer auswirken, indem Sie Warnmeldungen einrichten und schnell auf Anomalien reagieren. Aber versuchen Sie, Alarmmüdigkeit zu vermeiden. Sorgen Sie für ein Gleichgewicht zwischen automatisierten Warnmeldungen und menschlicher Aufsicht, damit wichtige Probleme nicht übersehen werden, und konzentrieren Sie sich auf die Ergebnisse und nicht auf die Systemkennzahlen. 

2. Echtzeit-Einblicke: Gehen Sie über das Logging von Problemen hinaus und ermöglichen Sie schnelle Entscheidungen auf Basis von Live-Daten und Echtzeit-Dashboards, die die kritischsten Geschäftstransaktionen priorisieren. Verwenden Sie Telemetriedaten (Logs, Metriken und Traces), um Ihre Leistungsdaten zu parsen.

3. End-to-End-Transparenz: Überwachen Sie die Anwendung in der gesamten Umgebung, im gesamten Benutzerfluss und auf allen Ebenen, vom Frontend bis zum Backend.

4. Nutzerzentrierter Ansatz: Priorisieren Sie die Leistung und das Erlebnis aus der Perspektive des Endnutzers, während Sie die wichtigsten Geschäftsziele berücksichtigen.

5. Real User Monitoring: Die Arbeit hört nicht auf, wenn sie in den Händen Ihrer Nutzer ist. Indem Sie deren Erfahrungen überwachen, können Sie auf Grundlage ihres Feedbacks iterieren und Verbesserungen vornehmen.

6. Kontinuierliche Verbesserung: Nutzen Sie Einblicke, um im Laufe der Zeit Optimierungen vorzunehmen und regelmäßig nicht gemeldete Probleme aufzudecken und zu beheben. Probleme sollten dynamisch angegangen werden, anstatt erst bei regelmäßigen Leistungsüberprüfungen entdeckt zu werden. 

7. Kontextweitergabe: Stellen Sie sicher, dass der Trace-Kontext durch den gesamten Anforderungspfad fließt, insbesondere über Servicegrenzen hinweg:

# Outgoing request - inject context
headers = {}
propagate.inject(headers)
response = requests.post('http://service-b/process', headers=headers)

8. Sampling-Strategie: Verwenden Sie intelligentes Sampling, um Sichtbarkeit und Leistung in Einklang zu bringen:

  • 1%–10% kopfbasiertes Sampling für stark frequentierte Dienste

  • 100 % Sampling für Fehler und langsame Anfragen durch tail-basiertes Sampling

  • Überwachen Sie den Overhead der Instrumentierung – streben Sie eine Leistungsauswirkung von weniger als 5 % an

Best Practices für die APM-Implementierung

Die richtige APM-Lösung sollte Ihren Technologie-Stack mit minimalem Instrumentierungsaufwand unterstützen. OpenTelemetry hat sich zum Industriestandard entwickelt und bietet herstellerneutrale, sprachübergreifende Instrumentierung:

@RestController
public class OrderController {
    
    @PostMapping("/orders")
    public ResponseEntity<Order> createOrder(@RequestBody OrderRequest request) {
        // Auto-instrumentation captures this endpoint automatically
        // Add custom business context
        Span.current().setAttributes(Attributes.of(
            stringKey("order.value"), String.valueOf(request.getTotal()),
            stringKey("user.tier"), request.getUserTier()
        ));
        
        return ResponseEntity.ok(processOrder(request));
    }
}

  • Do: Implementieren Sie Sampling-Strategien und überwachen Sie den Instrumentierungsaufwand in der Produktion.

  • Don't: Verwenden Sie 100 %-Stichproben für Dienste mit hohem Datenverkehr – dies wirkt sich auf die Leistung aus und lässt die Speicherkosten explodieren.

  • Fallstrick: Bei der Head-basierten Stichprobenerstellung können kritische Fehlerspuren übersehen werden. Verwenden Sie tail-basiertes Sampling, um alle Fehler zu erfassen und gleichzeitig das Volumen zu reduzieren.

Hier erfahren Sie, wie Sie es richtig machen:

  • Wählen Sie die richtige APM-Lösung aus: Das richtige APM-Tool sollte auf die Architektur einer Anwendung und die Anforderungen des Unternehmens abgestimmt sein. Die Lösung sollte ein Unternehmen mit den Tools und Funktionen ausstatten, die es zur Überwachung, Verfolgung, Messung und Analyse seiner Softwareanwendungen benötigt. Ein Unternehmen kann OpenTelemetry, ein Open-Source-Framework für Beobachtbarkeit, verwenden, um Telemetriedaten (Traces, Metriken und Logs) aus Anwendungen zu erfassen und zu sammeln. 

  • Kostenkontrolle durch Kardinalität: Attribute mit hoher Kardinalität können Metriken unbrauchbar und teuer machen:
# Good - bounded cardinality
span.set_attribute("user.tier", user.subscription_tier)  # 3-5 values
span.set_attribute("http.status_code", response.status_code)  # ~10 values

# Bad - unbounded cardinality  
span.set_attribute("user.id", user.id)  # Millions of values
span.set_attribute("request.timestamp", now())  # Infinite values
  • Richten Sie intelligentes Alerting ein, das auf SLOs anstatt auf willkürlichen Schwellenwerten basiert. Verwenden Sie Fehlerbudgets, um zu bestimmen, wann jemand benachrichtigt werden muss:
slos:
  - name: checkout_availability
    target: 99.9%
    window: 7d
  - name: checkout_latency  
    target: 95%  # 95% of requests under 500ms
    window: 7d

  • Schulen Sie Teams und fördern Sie die Zusammenarbeit. Eine APM-Strategie betrifft eine Vielzahl von Stakeholdern, nicht nur Entwickler. Binden Sie IT-Teams und andere Geschäftsinteressenten in die abteilungsübergreifende Zusammenarbeit ein. Arbeiten Sie zusammen, indem Sie APM in Ihre organisatorische Struktur integrieren. Legen Sie klare Ziele und KPIs fest, die den Geschäftsanforderungen entsprechen und die Nutzererfahrung berücksichtigen. 

  • Überprüfen und bewerten. Eine APM-Strategie entwickelt sich kontinuierlich weiter und passt sich den Anforderungen von Anwendungen und Unternehmen an.

Monitoring-Strategien im APM

Ein wichtiger Aspekt einer erfolgreichen Strategie zur Verwaltung der Anwendungsleistung ist die Überlegung, wie und wann die verschiedenen Überwachungsansätze eingesetzt werden sollen. Die Berücksichtigung einer Kombination von Überwachungsstrategien ist von entscheidender Bedeutung, da verschiedene Komponenten einer Anwendung, wie z. B. die Benutzerfreundlichkeit oder die Infrastruktur, maßgeschneiderte Ansätze erfordern, um Probleme effektiv zu erkennen und zu beheben. Eine breit gefächerte Strategie sorgt für eine umfassende Abdeckung, schnellere Analysen, eine ununterbrochene Anwendungsleistung und zufriedenere Endbenutzer.


Es gibt verschiedene Ansätze für das Monitoring, die in Betracht gezogen werden können: 
  • Monitoring in Echtzeit: Verfolgt kontinuierlich die Live-Systemleistung mit einer Granularität von weniger als einer Sekunde. Implementieren Sie benutzerdefinierte Metriken für die Geschäftslogik neben technischen Metriken:
order_processing_duration = Histogram(
    "order_processing_seconds",
    "Time to process orders", 
    ["payment_method", "order_size"]
)

with order_processing_duration.labels(
    payment_method=payment.method,
    order_size=get_size_bucket(order.total)
).time():
    process_order(order)
  • Synthetisches Monitoring: Simuliert Nutzerinteraktionen, um Probleme zu erkennen, bevor echte Nutzer betroffen sind. Kritisch für externe Abhängigkeiten:
// Synthetic check for critical user flow
const syntheticCheck = async () => {
    const span = tracer.startSpan('synthetic.checkout_flow');
    try {
        await loginUser();
        await addItemToCart();
        await completePurchase();
        span.setStatus({code: SpanStatusCode.OK});
    } catch (error) {
        span.recordException(error);
        span.setStatus({code: SpanStatusCode.ERROR});
        throw error;
    } finally {
        span.end();
    }
};

  • Tiefgehende Diagnosen und Profilerstellung: Hilft bei der Behebung von komplexen Leistungsengpässen, zu denen auch Plugins oder Tools von Drittanbietern gehören können. Durch die Anwendungsprofilierung können Sie Ihre Daten genauer untersuchen und analysieren, wie sie sich entsprechend ihrer Funktionen verhalten.

  • Verteiltes Tracing: Unerlässlich für Microservices-Architekturen. Handhaben Sie die Weitergabe von Kontexten über asynchrone Grenzen hinweg sorgfältig:
# Event-driven systems - propagate context through messages
def publish_order_event(order_data):
    headers = {}
    propagate.inject(headers)
    
    message = {
        'data': order_data,
        'trace_headers': headers  # Preserve trace context
    }
    kafka_producer.send('order-events', message)

APM Datenanalyse und Einblicke

Monitoring und Datenerfassung sind nur der Anfang. Unternehmen müssen verstehen, wie sie Daten zum Anwendungsleistungsmanagement für Optimierung und Entscheidungsfindung interpretieren.

Das Erkennen von Trends und Mustern hilft Teams, Probleme proaktiv zu erkennen. Nutzen Sie Korrelationsanalysen, um Benutzerbeschwerden mit der Backend-Leistung zu verknüpfen. Hier sehen Sie ein Beispiel mit ES|QL (Abfragesprache von Elastic):

FROM traces-apm*
| WHERE user.id == "user_12345" 
  AND @timestamp >= "2024-06-06T09:00:00" 
  AND @timestamp <= "2024-06-06T10:00:00"
| EVAL duration_ms = transaction.duration.us / 1000
| KEEP trace.id, duration_ms, transaction.name, service.name, transaction.result
| WHERE duration_ms > 2000
| SORT duration_ms DESC
| LIMIT 10

Erkennung von Engpässen: APM deckt gängige Performance-Anti-Patterns auf, wie z. B. n+1-Probleme, die im folgenden Code zu sehen sind. Verwenden Sie APM, um den Code zu optimieren:

# N+1 query problem detected by APM
def get_user_orders_slow(user_id):
    user = User.query.get(user_id)
    orders = []
    for order_id in user.order_ids:  # Each iteration = 1 DB query
        orders.append(Order.query.get(order_id))
    return orders

# Optimized after APM analysis
def get_user_orders_fast(user_id):
    return Order.query.filter(Order.user_id == user_id).all()  # Single query

Die Korrelation von Metriken und die Verknüpfung von Nutzerbeschwerden mit Backend-Leistungsdaten, einschließlich historischer Daten, zeigt, wie verschiedene Teile des Systems interagieren. Dies kann Teams dabei helfen, die Ursachen genau zu Diagnose und die vollen Auswirkungen von Leistungsproblemen zu verstehen.

Die Automatisierung der Ursachenanalyse und der Einsatz von KI-/Machine-Learning-basierten Tools wie AIOps helfen, Diagnosen und Problemlösungen zu beschleunigen, indem sie die Problemquelle ermitteln, die Betriebsausfallzeit reduzieren und Ressourcen freisetzen.

Es ist wichtig, sich für zukünftige Entscheidungen ein ganzheitliches Bild Ihrer Daten zu machen. Je mehr Daten Sie haben, desto mehr können Sie nutzen.

  • Do: Verwenden Sie verteilte Traces, um den spezifischen Dienst und Vorgang zu identifizieren, der die Verlangsamung verursacht.

  • Don't: Gehen Sie davon aus, dass Korrelation Kausalität bedeutet – überprüfen Sie dies mit Profilerstellungsdaten auf Codeebene.

  • Fallstrick: Altsysteme erscheinen oft als Blackboxes in Traces. Verwenden Sie Log-Korrelation und synthetische Spans, um die Sichtbarkeit zu pflegen.

Erweiterte Implementierungsmuster

Komplexe Produktionsumgebungen stellen einzigartige Herausforderungen dar, die fortschrittliche Implementierungsstrategien erfordern. Dieser Abschnitt behandelt praktische Ansätze für den Umgang mit polyglotten Architekturen, die Integration von Altsystemen und anspruchsvolle Korrelationsanalysen.

Kontextverbreitung in polyglotten Umgebungen: Die Aufrechterhaltung des Trace-Kontexts über verschiedene Sprachen und Frameworks hinweg erfordert besondere Aufmerksamkeit für die Verbreitungsmechanismen:

// Java - Auto-propagation with Spring Cloud
@PostMapping("/orders")
public ResponseEntity<Order> createOrder(@RequestBody OrderRequest request) {
    Span.current().setAttributes(Attributes.of(
        stringKey("order.type"), request.getOrderType(),
        longKey("order.value"), request.getTotalValue()));
    
    // OpenFeign automatically propagates context to downstream services
    return paymentClient.processPayment(request.getPaymentData());}
// Go - Manual context extraction and propagation
func processHandler(w http.ResponseWriter, r *http.Request) {
    ctx := otel.GetTextMapPropagator().Extract(r.Context(), 
                                              propagation.HeaderCarrier(r.Header))
    ctx, span := tracer.Start(ctx, "process_payment")
    defer span.End()
    // Continue with trace context maintained}

Legacy Systemintegration: Erstellen Sie Brücken zur Beobachtbarkeit für Systeme, die nicht direkt instrumentiert werden können:

# Synthetic spans with correlation IDs for mainframe calls
with tracer.start_as_current_span("mainframe.account_lookup") as span:
    correlation_id = format(span.get_span_context().trace_id, '032x')
    
    logger.info("CICS call started", extra={
        "correlation_id": correlation_id,
        "trace_id": span.get_span_context().trace_id
    })
    
    result = call_mainframe_service(account_data, correlation_id)
    span.set_attribute("account.status", result.status)

Erweiterte Ablaufverfolgungsanalyse mit ES|QL: Verknüpfen Sie Nutzerbeschwerden mit der Backend-Leistung mithilfe der Abfragesprache von Elastic:

-- Find slow requests during complaint timeframe
FROM traces-apm*
| WHERE user.id == "user_12345" AND @timestamp >= "2024-06-06T09:00:00"
| EVAL duration_ms = transaction.duration.us / 1000
| WHERE duration_ms > 2000
| STATS avg_duration = AVG(duration_ms) BY service.name, transaction.name
| SORT avg_duration DESC

-- Correlate errors across service boundaries
FROM traces-apm*
| WHERE trace.id == "44b3c2c06e15d444a770b87daab45c0a"
| EVAL is_error = CASE(transaction.result == "error", 1, 0)
| STATS error_rate = SUM(is_error) / COUNT(*) * 100 BY service.name
| WHERE error_rate > 0

Ereignisgesteuerte Architekturmuster: Explizites Weitergeben des Kontexts über Nachrichtenheader für die asynchrone Verarbeitung:

# Producer - inject context into message
headers = {}
propagate.inject(headers)
message = {
    'data': order_data,
    'trace_headers': headers  # Preserve trace context
}
await kafka_producer.send('order-events', message)

# Consumer - extract and continue trace
trace_headers = message.get('trace_headers', {})
context = propagate.extract(trace_headers)
with tracer.start_as_current_span("order.process", context=context):
    await process_order(message['data'])

  • Do: Verwenden Sie ES|QL für komplexe Trace-Analysen, die herkömmliche Dashboards nicht bewältigen können.

  • Don't: Versuchen Sie nicht, Legacy-Systeme direkt zu instrumentieren – verwenden Sie Korrelations-IDs und synthetische Spannen.

  • Fallstrick: Nachrichten-Warteschlangen und asynchrone Verarbeitung unterbrechen den Trace-Kontext, es sei denn, er wird explizit über Header weitergegeben.

  • Wichtiger Einblick: Eine perfekte Instrumentierung ist nicht immer möglich. Die strategische Verwendung von Korrelations-IDs, synthetischen Spannen und intelligenten Abfragen bietet umfassende Beobachtbarkeit auch in komplexen, hybriden Umgebungen.

APM zur Leistungsoptimierung mit Elastic Observability

Elastic Observability ermöglicht die nahtlose Implementierung einer Application Performance Management-Strategie, indem es einheitliche Beobachtbarkeit bietet und Anwendungsleistungsdaten mit Logs, Metriken und Traces auf einer einzigen leistungsstarken Platform kombiniert. Die Datenerfassung mit Elastic's Distributions of OpenTelemetry (EDOT) ermöglicht einen schnellen und einfachen Einstieg in die APM-Datenerfassung. 

Entwickler können Warnmeldungen für Anomalien einrichten, verteiltes Tracing verwenden, um bestimmte Services oder Transaktionen zu optimieren, die Latenz zu reduzieren und die Leistungsstabilität mit Elastic durch Lastausgleich und Caching zu verbessern. 

Durch Code-Profiling können Teams Leistungsengpässe, ineffiziente Codepfade, Speicherlecks oder ressourcenintensive Vorgänge identifizieren, die zu einer Verlangsamung von Anwendungen führen. Unternehmen können individuelle Dashboards erstellen, um KPIs zu verfolgen und so letztendlich bessere Geschäftsergebnisse zu erzielen.

Erkunden Sie Elastic Observability Labs für weitere technische Inhalte zur Beobachtbarkeit.

Zusätzliche APM-Ressourcen 

Die Entscheidung über die Veröffentlichung der in diesem Blogeintrag beschriebenen Leistungsmerkmale und Features sowie deren Zeitpunkt liegt allein bei Elastic. Es ist möglich, dass noch nicht verfügbare Leistungsmerkmale oder Features nicht rechtzeitig oder überhaupt nicht veröffentlicht werden.