web-dev-qa-db-fra.com

Comment enregistrer les erreurs JS d'un client dans kibana?

J'ai une application Web soutenue dans NodeJS et logstash/elasticsearch/kibana pour gérer les journaux système comme (access_error.log, messages.log etc).

Pour le moment, je dois également enregistrer toutes les erreurs côté client JavaScript dans kibana. Quelle est la meilleure façon de procéder?

EDIT: Je dois ajouter des informations supplémentaires à cette question. Comme @Jackie Xu fournit une solution partielle à mon problème et comme suit de mon commentaire:

Je suis le plus intéressé à réaliser la gestion des erreurs côté serveur. Je pense que ce n'est pas efficace d'écrire chaque erreur dans un fichier. Je recherche les meilleures pratiques pour augmenter les performances.

J'ai besoin de gérer les enregistrements d'erreurs js côté serveur plus efficaces que de simplement écrire dans un fichier. Pouvez-vous fournir des scénarios comment augmenter les performances de journalisation côté serveur?

27
Erik

Quand vous dites client, je suppose ici que vous voulez dire un client de journalisation et non un client web.

Tout d'abord, prenez l'habitude de consigner vos erreurs dans un format commun. Logstash aime la cohérence, donc si vous mettez du texte et du JSON dans le même journal de sortie, vous rencontrerez des problèmes. Astuce: connectez-vous JSON. C'est génial et incroyablement flexible.

Le processus global se déroulera comme suit:

  1. Une erreur se produit dans votre application
  2. Consigner l'erreur dans un fichier, un socket ou sur un réseau
  3. Dire à logstash comment obtenir (saisir) cette erreur (c'est-à-dire à partir d'un fichier, écouter sur le réseau, etc.)
  4. Dites à logstash d'envoyer (sortie) l'erreur à Elasticsearch (qui peut s'exécuter sur la même machine)

Dans votre application, essayez d'utiliser l'enregistreur bunyan pour le nœud. https://github.com/trentm/node-bunyan

application de nœud index.js

var bunyan = require('bunyan');
var log = bunyan.createLogger({
  name: 'myapp',
  streams: [{
    level: 'info',
    stream: process.stdout // log INFO and above to stdout
  }, {
    level: 'error',
    path: '/var/log/myapp-error.log' // log ERROR and above to a file
  }]
});

// Log stuff like this
log.info({status: 'started'}, 'foo bar message');

// Also, in express you can catch all errors like this
app.use(function(err, req, res, next) {
   log.error(err);
   res.send(500, 'An error occurred');
});

Ensuite, vous devez configurer logstash pour lire ces fichiers journaux JSON et les envoyer à Elasticsearch/Kibana. Créez un fichier appelé myapp.conf et essayez ce qui suit:

logstash config myapp.conf

# Input can read from many places, but here we're just reading the app error log
input {
    file {
        type => "my-app"
        path => [ "/var/log/myapp/*.log" ]
        codec => "json"
    }   
}

# Output can go many places, here we send to elasticsearch (pick one below)
output {

  elasticsearch {
    # Do this if elasticsearch is running somewhere else
    Host => "your.elasticsearch.hostname"
    # Do this if elasticsearch is running on the same machine
    Host => "localhost"
    # Do this if you want to run an embedded elastic search in logstash
    embedded => true   
  }

}

Ensuite, démarrez/redémarrez logstash en tant que tel: bin/logstash agent -f myapp.conf web

Accédez à elasticsearch sur http://your-elasticsearch-Host:9292 pour voir les journaux arriver.

39
methai

Si je comprends bien, le problème que vous avez ne concerne pas l'envoi de vos journaux au serveur (ou si c'était @ Jackie-x fourni quelques conseils), mais plutôt la façon de les envoyer à elastiscsearch le plus efficacement.

En fait, la grande majorité des utilisateurs de la pile classique Logstash/Elasticsearch/Kibana sont habitués à avoir une application qui se connecte à un fichier, puis utilisez le plug-in de Logstash pour lire des fichiers pour analyser ce fichier et envoyer le résultat à ElasticSearch. Puisque @ methai a donné une bonne explication à ce sujet, je n'irai pas plus loin de cette façon.

Mais ce que je voudrais apporter, c'est que:

Vous n'êtes pas obligé d'utiliser Logstash.
En fait, le rôle principal de Logstash est de collecter les journaux, de les analyser pour identifier leur structure et leur champ récurrent, et enfin de les produire au format JSON afin qu'ils puissent être envoyés à ElasticSearch. Mais comme vous manipulez déjà le javascript côté client, on peut facilement imaginer que vous parlez directement au serveur Elasticsearch. Par exemple, une fois que vous avez détecté une exception javascript, vous pouvez procéder comme suit:

var xhr = new XMLHttpRequest();
xhr.open("PUT", http://your-elasticsearch-Host:9292, true);
var data = {
    lineNumber: lineNumber,
    message: message,
    url: url
}
xhr.send(JSON.stringify(data));

En faisant cela, vous parlez directement du client au serveur ElasticSearch. Je ne peux pas imaginer un moyen plus simple et plus rapide de le faire (mais notez que ce n'est qu'une théorie, je ne me suis jamais essayé, donc la réalité pourrait être plus complexe, surtout si vous voulez que des champs spéciaux comme les horodatages de date soient générés;)). Dans un contexte de production, vous aurez probablement des problèmes de sécurité, probablement un serveur proxy entre le client et le serveur ES, mais le principe est là.

Si vous voulez absolument utiliser Logstash, vous n'êtes pas obligé d'utiliser une entrée de fichier
Si, dans le but d'harmoniser, de faire la même chose que tout le monde, ou d'utiliser la configuration avancée d'analyse syntaxique de logstash que vous souhaitez respecter, vous devriez jeter un œil à toutes les entrées alternatives à l'entrée de fichier de base. Par exemple, j'avais l'habitude d'utiliser un tuyau moi-même, avec un processus chargé de collecter les journaux et de les envoyer à la sortie standard. Il y a aussi la possibilité de lire sur un socket TCP ouvert, et bien plus, vous pouvez même ajouter le vôtre.

4
Aldian

Vous devez d'abord détecter toutes les erreurs côté client (et les envoyer à votre serveur):

window.onerror = function (message, url, lineNumber) {

    // Send error to server for storage
    yourAjaxImplementation('http://domain.com/error-logger/', {
        lineNumber: lineNumber,
        message: message,
        url: url
    })

    // Allow default error handling, set to true to disable
    return false

}

Ensuite, vous pouvez utiliser NodeJS pour écrire ces messages d'erreur dans un journal. Logstash peut les collecter, puis vous pouvez utiliser Kibana pour les visualiser.

Notez que selon Mozilla window.onerror ne semble pas fonctionner pour chaque erreur. Vous voudrez peut-être passer à quelque chose comme Sentry (si vous ne voulez pas payer, vous pouvez directement obtenir la source de GitHub ).

3
Aeveus

Les erreurs de journalisation via la journalisation de fichiers intégrée par défaut permettent de conserver vos erreurs et permettent également à votre noyau d'optimiser les écritures pour vous.

Si vous pensez vraiment que ce n'est pas assez rapide (vous obtenez autant d'erreurs?), Vous pouvez simplement les mettre en redis.

Logstash a une entrée redis pub/sub afin que vous puissiez stocker les erreurs dans redis et logstash les retirera et les stockera dans votre cas dans elasticsearch.

Je suppose que logstash/es sont sur un autre serveur, sinon cela ne sert à rien, il doit également stocker les données sur le disque, et ce n'est pas aussi efficace que d'écrire un fichier journal.

Quelle que soit la solution que vous choisissez, vous souhaiterez stocker les données, par exemple. l'écrire sur le disque. L'ajout uniquement à un seul fichier (journal) est très efficace et lorsque vous conservez des données, la seule façon d'en gérer davantage est de les répartir sur plusieurs disques/nœuds.

1
Paul Scheltema