Bonnes pratiques en matière de gestion des données applicatives : guide des actions à effectuer et à éviter à l’intention des professionnels

blog-APM_Best_Practices.jpg

La gestion des performances applicatives (APM) est la pratique consistant à suivre, mesurer et analyser régulièrement les performances et la disponibilité des applications logicielles. Cette gestion vous permet d’obtenir une visibilité sur les environnements de microservices complexes, qui peuvent submerger les équipes d’ingénierie de la fiabilité des sites (SRE). Les informations générées créent une expérience utilisateur optimale et permettent d’atteindre les résultats souhaités pour l’entreprise. Il s’agit d’un processus complexe, mais l’objectif est simple : s’assurer qu’une application fonctionne correctement et répond aux attentes des utilisateurs et des entreprises. 

Une compréhension claire du fonctionnement d'une application et une pratique proactive de la gestion des performances applicatives sont cruciales pour assurer la maintenance des applications logicielles à haute performance. Il ne doit pas s’agir d’une réflexion secondaire. Elle doit être envisagée dès le départ. Lorsqu’elle est mise en œuvre de manière proactive, elle peut être intégrée au fonctionnement des logiciels en incorporant des composants de suivi directement dans l’application.

Qu'est-ce que la gestion des performances applicatives ?

La gestion des performances applicatives intègre le suivi, l’analyse et la gestion continues des performances du back-end et du front-end d’une application. Le suivi des applications est en pleine expansion et évolue, mais la stratégie de gestion des données applicatives ne doit pas être créée de manière isolée. Il est essentiel de faire participer de nombreuses parties prenantes, des experts métier, des développeurs d’applications et des équipes opérationnelles. Une stratégie de gestion des données applicatives réussie va au-delà de la disponibilité ou de la santé des serveurs et se concentre sur les objectifs de niveau de service (SLO) avant qu’ils ne deviennent un problème pour les utilisateurs. 

La mise en œuvre d'une gestion des données applicatives moderne implique d'instrumenter vos applications pour collecter trois types de données télémétriques : les traces (flux de requêtes), les indicateurs (mesures agrégées) et les journaux (évènements discrets). Le défi n'est pas seulement de collecter des données, mais de collecter les bonnes données sans affecter les performances.

En savoir plus sur les indicateurs d'observabilité.

Il existe de nombreuses approches en termes d'instrumentation, mais la stratégie la plus efficace combine l'instrumentation automatiques (pour les cadres de travail et les bibliothèques) et l'instrumentation manuelle (pour la logique métier). L'instrumentation automatique utilisant des agents OpenTelemetry peut couvrir 80 % de vos besoins en termes d’observabilité grâce à un minimum de changements dans le code :

# 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

  • À faire : commencez par l’instrumentation automatisée, puis ajoutez des intervalles manuels pour les activités métier essentielles.

  • À éviter : instrumenter manuellement chaque appel de fonction, car cela créera une surcharge de performance et du bruit.

  • Écueil : une instrumentation excessive peut provoquer une latence 15%–20% plus importante. Évaluez votre suivi à l'aide de comparaisons de performances de référence.

Voici quelques éléments qu'une organisation ou une entreprise doit prendre en compte lors de l'élaboration d'une stratégie de gestion des performances applicatives :

  • Suivi des performances, dont l'évaluation de la latence, des objectifs de niveau de service, du temps de réponse, du débit et des volumes de requêtes

  • Suivi des erreurs, dont les exceptions, les pannes et les appels API échoués 

  • Suivi de l'infrastructure, dont l'état de santé et l'utilisation des ressources des serveurs, des conteneurs et des environnements cloud qui prennent en charge l'application

  • Indicateurs de l'expérience utilisateur, dont les temps de chargement, les performances de session, les chemins de clic et les informations relatives au navigateur ou à l'appareil (il est important de garder à l'esprit que même si les indicateurs système semblent corrects, les utilisateurs peuvent toujours rencontrer des problèmes de performance.)

Principes clés d'une gestion des données applicatives efficace

Les principes de base d'une gestion des performances applicatives efficace sont la visibilité de bout en bout (du navigateur de l'utilisateur à la base de données), le suivi et les informations en temps réel, ainsi que les informations contextuelles, avec une focalisation sur les objectifs de l'utilisateur et de l'entreprise. La gestion des performances applicatives peut améliorer l’évolutivité des applications en permettant des améliorations continues et en augmentant les performances au fil du temps.

  • À faire : mettez en place des tableaux de bord en temps réel avec des alertes basées sur les objectifs de niveau de service plutôt que sur des seuils arbitraires.

  • À éviter : uniquement se fier aux évaluations périodiques des performances ou aux alertes processeur/mémoire, instrumentez les indicateurs de l'expérience utilisateur.

  • Écueil : les fausses alertes provenant des indicateurs système de bas niveau. Concentrez-vous sur les objectifs de niveau de service orientés utilisateur qui signalent des problèmes réels.

Lors de l'élaboration d'une stratégie de gestion des données applicatives, voici quelques principes clés à prendre en compte :

1. Suivi proactif : évitez les problèmes avant qu’ils n’affectent les utilisateurs en configurant des alertes et en réagissant rapidement à toute anomalie, tout en essayant d’éviter les fausses alertes. Trouvez l’équilibre entre les alertes automatisées et la supervision humaine afin que les problèmes importants ne soient pas ignorés, en vous concentrant sur les résultats plutôt que sur les indicateurs système. 

2. Informations en temps réel : dépassez les problèmes de journalisation et permettez une prise de décision rapide basée sur des données en direct et des tableaux de bord en temps réel qui donnent la priorité aux transactions les plus importantes. Utilisez les données de télémétrie (journaux, indicateurs et traces) pour analyser vos performances.

3. Visibilité de bout en bout : surveillez l’application dans l’ensemble de l’environnement, l’ensemble du flux utilisateur et toutes les couches, du front-end au back-end.

4. Approche centrée utilisateur : privilégiez les performances et l’expérience du point de vue de l’utilisateur final, tout en tenant compte des principaux objectifs métier.

5. Suivi des utilisateurs réels : votre travail n’est pas terminé lorsque celui des utilisateurs l’est. En surveillant leur expérience, vous pouvez répéter les tests et améliorer les performances en fonction de leurs commentaires.

6. Amélioration continue : utilisez les informations pour optimiser les performances au fil du temps et découvrez et abordez régulièrement les problèmes non signalés. Les problèmes doivent être traités de manière dynamique plutôt que d'être découverts lors d'examens périodiques des performances. 

7. Propagation du contexte : veillez à ce que le contexte de traçage circule sur l'ensemble de votre parcours de demande, en particulier au-delà des limites des services :

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

8. Stratégie d’échantillonnage : utilisez un échantillonnage intelligent pour équilibrer la visibilité et les performances :

  • 1%–10% d’échantillonnage en amont pour les services à fort trafic

  • Échantillonnage à 100 % pour les erreurs et les requêtes lentes à l’aide d’un échantillonnage en aval

  • Suivez la surcharge de l'instrumentation et visez un impact <5 % sur les performances

Bonnes pratiques pour la mise en œuvre de la gestion des données applicatives

La bonne solution de gestion des données applicatives doit prendre en charge votre suite technologique avec un effort d'instrumentation minimal. OpenTelemetry est devenu la norme du secteur, car il fournit une instrumentation neutre qui fonctionne avec tous les langages :

@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));
    }
}

  • À faire : mettre en œuvre des stratégies d'échantillonnage et surveiller la surcharge de l'instrumentation en production.

  • À éviter : utiliser un échantillonnage de 100 % pour les services à fort trafic : vous affecterez les performances et ferez exploser les coûts de stockage.

  • Écueil : l’échantillonnage en amont peut laisser passer des traces d’erreur critiques. Utilisez l’échantillonnage en aval pour détecter toutes les erreurs tout en réduisant le volume.

Voici comment bien le faire :

  • Sélectionnez la bonne solution de gestion des données applicatives : le bon outil de gestion doit s’harmoniser avec l’architecture de l’application et les besoins de l’entreprise. La solution doit lui fournir les outils et les capacités nécessaires pour surveiller, suivre, mesurer et analyser ses applications logicielles. Une entreprise peut utiliser OpenTelemetry, un cadre de travail d’observabilité open source, pour instrumenter et collecter des données de télémétrie (traces, indicateurs et journaux) à partir d’applications. 

  • Gérez la cardinalité pour contrôler les coûts : les attributs à cardinalité élevée peuvent rendre les indicateurs inutilisables et coûteux :
# 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
  • Configurez des alertes intelligentes basées sur les objectifs de niveau de service plutôt que sur des seuils arbitraires. Utilisez des budgets d'erreur pour déterminer quand il faut alerter quelqu'un :
slos:
  - name: checkout_availability
    target: 99.9%
    window: 7d
  - name: checkout_latency  
    target: 95%  # 95% of requests under 500ms
    window: 7d

  • Formez les équipes et faites la promotion de la collaboration. Une stratégie de gestion des performances applicatives a un impact sur un large éventail de parties prenantes, pas seulement sur les développeurs. Assurez-vous d'impliquer les équipes informatiques et les autres parties prenantes de l'entreprise dans une collaboration inter-services. Collaborez en intégrant la gestion des performances applicatives dans votre structure organisationnelle. Veuillez vous assurer de définir des objectifs clairs et des indicateurs clés de performance (KPI) qui correspondent aux besoins de l'entreprise et tiennent compte de l'expérience utilisateur. 

  • Révisez et évaluez. Une stratégie de gestion des performances applicatives continue d'évoluer et de changer parallèlement aux besoins des applications et de l'entreprise.

Stratégies de suivi dans la gestion des performances applicatives

Un aspect clé d'une stratégie réussie de gestion des performances applicatives est de considérer comment et quand utiliser différentes approches de suivi. Il est crucial d’envisager une combinaison de stratégies de suivi, car les divers composants d'une application, tels que l'expérience utilisateur ou l'infrastructure, nécessitent des approches sur mesure pour détecter et résoudre les problèmes efficacement. Une stratégie diversifiée assure une couverture complète, une analyse plus rapide, des performances d'application plus fluides et des utilisateurs finaux plus satisfaits.


Il existe différentes approches de suivi à prendre en compte : 
  • Suivi en temps réel : suivi continu des performances du système en direct avec une précision inférieure à la seconde. Mettez en œuvre des indicateurs personnalisés pour la logique métier en parallèle des indicateurs techniques :
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)
  • Suivi synthétique : simule les interactions des utilisateurs pour détecter les problèmes avant que les utilisateurs réels ne soient affectés. Essentiel pour les dépendances externes :
// 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();
    }
};

  • Diagnostics et profilage approfondis : aide à résoudre les goulots d'étranglement complexes des performances, qui peuvent inclure des plug-ins ou des outils tiers. Grâce au profilage d'application, vous pouvez approfondir vos données et analyser leurs performances selon leurs fonctions.

  • Traçage distribué : essentiel pour les architectures de microservices. Gérez soigneusement la propagation du contexte au niveau des limites asynchrones :
# 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)

Analyse et informations des données de gestion des performances applicatives

Le suivi et la collecte de données ne sont qu’un début. Les entreprises doivent comprendre comment interpréter les données de gestion des performances applicatives pour les ajuster et prendre des décisions.

Identifier les tendances et les modèles aide les équipes à détecter les problèmes de manière proactive. Utilisez l’analyse de corrélation pour relier les plaintes des utilisateurs aux performances du back-end. Voyez un exemple ici en utilisant ES|QL (langage de requête d’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

Détection des goulots d'étranglement : la gestion des performances applicatives révèle des anti-modèles de performance courants, tels que les problèmes n+1, visibles dans le code ci-dessous. Utilisez la gestion des performances applicatives pour optimiser le code :

# 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

La corrélation des indicateurs et la mise en relation des plaintes des utilisateurs avec les données de performance du back-end, y compris les données historiques, révèlent comment les différentes parties du système interagissent. Cela peut aider les équipes à diagnostiquer avec précision les causes profondes et à comprendre l’impact complet des problèmes de performance.

L’automatisation de l’ analyse des causes profondes et l’utilisation d’outils basés sur l’IA/l’apprentissage automatique, tels que AIOps, permet d’accélérer les diagnostics et la résolution en identifiant la source des problèmes, en réduisant les temps d’indisponibilité et en libérant des ressources.

Il est important d'utiliser une vision globale de vos données pour éclairer vos décisions futures. Plus vous avez de données, plus vous pouvez en tirer parti.

  • À faire : utilisez des traces distribuées pour identifier le service et l’activité spécifiques à l’origine des ralentissements.

  • À éviter : supposer que la corrélation signifie la causalité : vérifiez avec des données de profilage au niveau du code.

  • Écueil : les systèmes hérités apparaissent souvent comme des boîtes noires dans les traces. Utilisez la corrélation des journaux et des intervalles synthétiques pour maintenir la visibilité.

Modèles avancés de mise en oeuvre

Les environnements de production complexes présentent des défis uniques qui nécessitent des stratégies de mise en œuvre avancées. Cette section aborde des approches pratiques pour gérer les architectures polyglottes, l'intégration des systèmes hérités et l'analyse de corrélation sophistiquée.

Propagation du contexte dans les environnements polyglottes : assurer la maintenance du contexte de traçage dans différents langages et cadres de travail nécessite une attention explicite aux mécanismes de propagation :

// 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}

Intégration desystèmes existants : créez des ponts d'observabilité pour les systèmes qui ne peuvent pas être directement instrumentés :

# 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)

Analyse avancée des traces avec ES|QL : reliez les plaintes des utilisateurs aux performances du back-end à l'aide du langage de requête 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

Modèles d'architecture pilotée par les évènements : propagez explicitement le contexte via les en-têtes de messages pour un traitement asynchrone :

# 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'])

  • À faire : utiliser ES|QL pour une analyse complexe des traces que les tableaux de bord traditionnels ne peuvent pas gérer.

  • À éviter : essayer d'instrumenter directement les systèmes existants : utilisez des identifiants de corrélation et des intervalles synthétiques.

  • Écueil : les files d’attentes des messages et le traitement asynchrone rompent le contexte de traçage à moins qu'ils ne soient explicitement propagés par les en-têtes.

  • Informations clés : une instrumentation parfaite n’est pas toujours possible. L’utilisation stratégique des identifiants de corrélation, des intervalles synthétiques et des requêtes intelligentes permet une observabilité complète, même dans des environnements complexes et hybrides.

Gestion des performances applicatives pour l'optimisation des performances avec Elastic Observability

Elastic Observability facilite la mise en œuvre d’une stratégie de gestion des performances applicatives en offrant une observabilité unifiée, combinant les données de performance des applications avec les journaux, les indicateurs et les traces sur une plateforme puissante et unique. La collecte de données grâce aux distributions d'OpenTelemetry (EDOT) d’Elastic permet de commencer rapidement et facilement à collecter des données de gestion des performances applicatives. 

Les développeurs peuvent configurer des alertes pour les anomalies, utiliser le traçage distribué pour optimiser des services ou des transactions spécifiques, réduire la latence et améliorer la stabilité des performances avec Elastic grâce à l'équilibrage de charge et à la mise en cache. 

Grâce au profilage de code, les équipes peuvent identifier les points d’accès de performance, les chemins de code inefficaces, les fuites de mémoire ou les opérations gourmandes en ressources qui ralentissent les applications. Les entreprises peuvent créer des tableaux de bord personnalisés pour suivre les indicateurs clés de performance, ce qui donnera au final de meilleurs résultats.

Découvrez Elastic Observability Labs pour plus de contenu technique relatif à l'observabilité.

Ressources supplémentaires en matière de gestion des données applicatives 

La publication et la date de publication de toute fonctionnalité ou fonction décrite dans le présent article restent à la seule discrétion d'Elastic. Toute fonctionnalité ou fonction qui n'est actuellement pas disponible peut ne pas être livrée à temps ou ne pas être livrée du tout.