Problèmes de mise à niveau de Node.js 22
Les problèmes suivants sont spécifiques à la mise à niveau des moniteurs vers Node.js 22.
Handles ouverts non gérés
Symptôme : Le monitor échoue lors de la validation ou de l'exécution Cause : Node.js 22 est plus strict concernant les cycles de vie des processus
Le problème le plus courant lors de la mise à niveau vers Node.js 22 est la présence de handles ouverts non gérés. Si vos scripts de moniteur contiennent des handles ouverts non gérés (tels que des promesses non résolues, des minuteurs persistants ou des connexions réseau non fermées), vos moniteurs échoueront.
Les types courants de handles ouverts incluent :
- Promesses non résolues: Assurez-vous que toutes les promesses sont correctement attendues ou gérées
- Timers résiduels: Effacer tous les appels
setTimeoutetsetInterval - Connexions non fermées: Fermez toutes les connexions réseau, les connexions aux bases de données et les descripteurs de fichiers.
- Connexions HTTP/HTTPS: consommer correctement les données de réponse et fermer les connexions
Les connexions HTTP/HTTPS restent ouvertes
Symptôme : Le monitor se bloque ou expire Cause : Données de réponse non consommées ou keepAlive activé
Solution A : Consommer les données de réponse
Pour utiliser http ou https, écoutez l'événement data. Sinon, la connexion HTTPS reste ouverte.
const https = require('https');
https.get('https://example.com', (res) => { console.log('Status Code:', res.statusCode); // Consume the response data res.on('data', (d) => { process.stdout.write(d); });}).on('error', (e) => { console.error('Error:', e);});Solution B : Désactiver keepAlive
Définissez l'option keepAlive sur false pour fermer les connexions HTTP une fois la requête terminée.
const https = require('https');const { Agent } = require('https'); // or http for HTTP requests
const options = { hostname: 'example.com', path: '/', method: 'GET', agent: new Agent({ keepAlive: false }), // Disable keepAlive};
const req = https.request(options, (res) => { console.log(`Status: ${res.statusCode}`); res.on('data', (d) => { process.stdout.write(d); });});
req.on('error', (e) => { console.error(e);});
req.end();Ressources de flux non nettoyées
Symptôme : Fuites de ressources ou moniteurs bloqués Cause : Flux non détruits dans les blocs finally
Solution
Nettoyez les flux dans un bloc finally pour garantir la libération correcte des ressources.
const got = require('got');
let downloadStream = got.stream("https://example.com/test.txt");
try { // Your stream processing logic here} finally { if (downloadStream) { downloadStream.destroy(); }}Sockets non détruites correctement
Symptôme : La validation du monitor échoue avec l'erreur "open handles" Cause : Nettoyage de socket manquant dans les chemins de code de succès
Détruire correctement les sockets dans tous les chemins de code.
Code problématique
// ❌ Problematic code - Socket not closed in success caseconst req = https.request(options, (res) => { try { const cert = res.socket.getPeerCertificate();
if (cert && Object.keys(cert).length > 0) { const validTo = cert.valid_to || cert.validTo; console.log("Raw certificate valid_to:", validTo); resolve({ validTo: validTo }); } else { reject(new Error("Could not get certificate information")); } } catch (err) { res.destroy(); if (res.socket) res.socket.destroy(); reject(err); }});Approche recommandée
Ajouter une fonctionnalité de nettoyage pour tous les chemins de code :
// ✅ Better approach - Proper cleanup in all casesconst req = https.request(options, (res) => { try { const cert = res.socket.getPeerCertificate();
// Always destroy the response and socket const cleanup = () => { try { res.destroy(); if (res.socket && !res.socket.destroyed) { res.socket.destroy(); } } catch (e) { console.log("Cleanup warning:", e.message); } };
if (cert && Object.keys(cert).length > 0) { const validTo = cert.valid_to || cert.validTo; console.log("Raw certificate valid_to:", validTo); cleanup(); resolve({ validTo: validTo }); } else { cleanup(); reject(new Error("Could not get certificate information")); } } catch (err) { res.destroy(); if (res.socket) res.socket.destroy(); reject(err); }});Temporisateurs non effacés
Symptôme : Le monitor ne termine pas son exécution Cause : setTimeout/setInterval non effacé
Code problématique
// ❌ Problematic codesetTimeout(() => { console.log('This might cause issues');}, 5000);Approche recommandée
Effacer le minuteur une fois terminé :
// ✅ Better approachconst timerId = setTimeout(() => { console.log('This is properly handled');}, 1000);
// Clear the timer when doneclearTimeout(timerId);Promesses non résolues
Symptôme : Le script semble se terminer mais la validation échoue Cause : Les promesses ne sont pas correctement attendues ou gérées
Solution : Assurez-vous que toutes les promesses ont .then(), .catch() ou sont awaited.
Problèmes de mise à niveau du runtime Chrome
Les problèmes suivants sont spécifiques à la mise à niveau des moniteurs de navigateur scripté vers des environnements d'exécution Chrome plus récents.
Navigateur scripté : les tentatives d'interaction avec les éléments échouent
Symptôme : findElement et d'autres méthodes échouent dans le nouveau runtime mais fonctionnent dans l'ancien runtime Cause : Différences de gestion des promesses entre les versions de Selenium WebDriver
Lors de la validation d'un moniteur créé dans un runtime plus ancien sur le runtime Chrome 100 (ou version ultérieure), findElement et d'autres méthodes pour trouver et interagir avec les éléments de la page peuvent échouer en raison de différences dans la gestion des promesses. Si le monitor réussit dans un ancien runtime, échoue dans le nouveau runtime, et que l'élément est présent dans la capture d'écran, améliorez votre logique de gestion des promesses.
Le gestionnaire de promesses et le contrôle de flux Sélénium Webdriver permettaient à certaines fonctions de s'exécuter dans l'ordre dans les environnements d'exécution legacy , sans gérer les promesses. Cette fonctionnalité a été supprimée dans sélénium Webdriver 4.0 et n'est plus disponible dans l'environnement d'exécution. Toutes les fonctions asynchrones et les promesses doivent être gérées avec la chaîne de promesses await ou .then . Cela garantira que les fonctions de script s'exécuteront dans l'ordre prévu.
Code problématique
Le gestionnaire de promesses et le flux de contrôle pourraient permettre à ce script partiel de se terminer avec succès, même si $browser.get retourne une promesse et que la promesse n'est pas gérée correctement :
// ❌ Problematic code - Promises not handled$browser.get('http://example.com');
$browser.findElement($driver.By.css('h1'));Approche recommandée
Dans le runtime Chrome 100 (ou version ultérieure), toutes les méthodes qui renvoient une promesse doivent utiliser la syntaxe await ou .then pour séquencer correctement les étapes. L'utilisation d'await est recommandée en raison de sa syntaxe plus claire et de sa facilité d'utilisation, mais les chaînes de promesses .then sont également toujours prises en charge.
// ✅ Better approach - Using awaitawait $browser.get('http://example.com');
let el = await $browser.findElement($driver.By.css('h1'));Navigateur scripté : avertissements d'obsolescence ($browser et $driver
Symptôme : Des avertissements de dépréciation apparaissent dans les logs de monitoring Cause : Utilisation d'une ancienne image d'environnement d'exécution de navigateur Node
Les avertissements de dépréciation pour $browser et $driver ont été supprimés à partir de la version 2.0.29 ou ultérieure du runtime du navigateur. Vous ne recevez plus ces avertissements lorsque vous utilisez des emplacements publics. Mettez à jour votre image d'exécution de navigateur Node si vous recevez ces avertissements lors de l'utilisation d'emplacements privés.
Navigateur scripté : waitForAndFindElement et waitForPendingRequests
Symptôme : Méthodes non disponibles lors de l'utilisation de $selenium et $webDriver Cause : Méthodes personnalisées New Relic non incluses dans les API de base de Selenium WebDriver 4.1
Les méthodes waitForAndFindElement et waitForPendingRequests sont des méthodes personnalisées New Relic qui sont fournies dans les environnements d'exécution de navigateur scripté Chrome 72 et versions antérieures. Ils peuvent toujours être utilisés avec $driver et $browser dans les runtimes Chrome 100 et plus récents, mais ne sont pas disponibles lors de l'utilisation directe des API Selenium WebDriver 4.1 avec $selenium et $webDriver. Ce changement aligne mieux l'implémentation de Selenium WebDriver de New Relic sur l'implémentation de base de Selenium WebDriver.
Pour continuer à utiliser waitForAndFindElement ou waitForPendingRequests dans le nouveau runtime, collez les exemples de code dans vos moniteurs.
Problèmes de mise à niveau du runtime de l'API
Les problèmes suivants sont spécifiques à la mise à niveau des moniteurs d'API scriptés vers des runtimes Node.js plus récents.
API scriptée : différences entre request et got
Symptôme : Les scripts d'API utilisant les fonctionnalités du module request échouent dans le nouvel environnement d'exécution Cause : Migration du module request déprécié vers le module got
Les environnements d'exécution d'API scriptés Node.js 10 et antérieurs utilisaient le module Node.js request pour fournir un objet $http qui pouvait être utilisé pour tester les API.
Les runtimes d'API scriptée Node.js 16 et versions ultérieures utilisent got au lieu de request. Le module request a été déprécié en 2020 et n'est plus inclus dans les nouveaux environnements d'exécution basés sur une API ou un navigateur. L'objet $http offre une expérience personnalisée de type requesttout en s'appuyant sur got pour assurer la rétrocompatibilité pour les cas d'utilisation de base, tout en évitant l'utilisation d'un module déprécié. Tous les cas d'utilisation avancés de request ne sont pas pris en charge. Des exemples de scripts et un guide de conversion sont disponibles.
Conseil
L'objet $http renvoie également l'expérience de type requestpour tous les clients essayant d'utiliser request directement dans les runtimes d'API scriptée Node.js 16 et versions ultérieures.
API scriptée : jeton inattendu JSON.parse
Symptôme : Erreurs de jeton inattendu lors de l'utilisation de JSON.parse Cause : Corps de la réponse déjà analysé automatiquement lorsque le content-type est application/json
Tenter d'utiliser la fonction JSON.parse lors de l'interaction avec le corps de la réponse produit des erreurs de jeton inattendu dans les moniteurs d'API scriptés utilisant le runtime Node.js 16 et versions ultérieures. Si l'en-tête de réponse content-type est application/json, l'objet $http renvoie du JSON parsé dans le corps de la réponse. Les appels supplémentaires tentant d'utiliser JSON.parse pour analyser le corps de la réponse échouent avec cette erreur car le corps de la réponse a déjà été analysé.
Si l'en-tête de réponse content-type n'est pas application/json, le corps de la réponse n'est pas automatiquement analysé et vous devez utiliser la fonction JSON.parse.
API scriptée : HEAD ou GET
Symptôme : Les requêtes HTTP HEAD ou GET échouent avec des erreurs liées au corps Cause : Le nouveau runtime applique la spécification HTTP qui interdit les corps dans les requêtes HEAD/GET
Vous ne pouvez pas inclure de corps de requête avec une requête HTTP HEAD ou GET. Le module request utilisé par le runtime Node 10 et les versions antérieures le permettait, mais cela causera des erreurs dans le nouveau runtime. Les suggestions les plus courantes incluent :
- N'incluez pas de corps dans votre requête, même s'il est vide.
- Évitez les options inutiles sur votre demande
HEADouGET, commejson: true
API scriptée : différences entre les chaînes de requête (qs)
Symptôme : Les options de chaîne de requête ne fonctionnent pas dans le nouveau runtime Cause : Le nom de l'option est passé de qs: à searchParams:
Dans les runtimes Node 10 ou antérieurs, les configurations de chaîne de requête étaient transmises à l'aide de l'option qs:. Pour le runtime Node 16, utilisez plutôt l'option searchParams:. Seul le nom de l'option doit changer. Le contenu de la chaîne de requête n'a pas besoin d'être mis à jour.
API scriptée : différences entre les pots à cookies
Symptôme : La gestion des cookies avec jar: true ne fonctionne pas Cause : L'implémentation du cookie jar a changé dans le runtime Node 16
Dans les environnements d'exécution Node 10 ou antérieurs, vous pouvez utiliser l'option jar: true pour stocker les cookies dans un pot à cookies entre requests.
Dans l'environnement d'exécution Node 16, vous devez créer un pot de cookies à l'aide du module tough-cookie , puis faire référence à ce pot de cookies dans votre requête. Si vous avez créé un pot à biscuits nommé cookies, faites-y référence dans vos options comme cookieJar: cookies
API scriptée : différences de forme
Symptôme : Les requêtes basées sur des formulaires échouent ou se comportent différemment Cause : Différences entre les modules request et got pour la gestion des formulaires
En raison des différences entre le module request utilisé pour l'objet $http dans Node 10 et les environnements d'exécution plus anciens et le module got utilisé pour l'objet $http dans l'environnement d'exécution Node 16, vous pouvez rencontrer des problèmes avec requests utilisant des formulaires dans le moniteur d'API.
Si c'est le cas, utilisez le module form-data pour créer et inclure votre formulaire avec votre requête, comme illustré dans cet exemple partiel :
const FormData = require('form-data');
let form = new FormData();form.set('fieldName1','value1');form.set('fieldName2','value2');
let req = { headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'multipart/form-data', }, body: form}Différences entre les versions du module UUID
Symptôme : Erreurs d'importation de module avec le module uuid Cause : Syntaxe du module uuid mise à jour dans le runtime Node 16
L'environnement d'exécution Node 16 inclut une version plus récente du module uuid qui force l'utilisation de la syntaxe require mise à jour.
Node 10 et versions antérieures : const uuid = require('uuid');
Nœud 16 (en supposant l'utilisation de uuidv4) : const { v4: uuidv4 } = require('uuid');