[JAVA] Ce que j'ai fait pour générer les journaux d'application dans l'environnement flexible GAE.

Sortie de journal dans l'environnement flexible de GoogleAppengine

Tout le monde, lorsque vous créez une application, crachez-vous les journaux sur le stockage sur le serveur d'applications? ??

Dans GAE / go (environnement standard), si vous utilisez google.golang.org / appengine / log, il sera affiché dans la visionneuse de journal, vous pouvez facilement filtrer le journal, etc.," What a wonderful !! " Je pense que j'ai été impressionné.

スクリーンショット_2016-12-06_17_44_49.png

Cependant, GAE / FE n'a pas généré de sortie vers la visionneuse de journal sans rien faire.

J'ai eu beaucoup de problèmes et j'ai pu sortir comme prévu, donc je vais l'écrire en détail car cela peut être utile pour quelqu'un un jour, y compris diverses enquêtes.

Stratégie de sortie du journal (première génération)

La première méthode de sortie de journal à laquelle j'ai pensé était d'utiliser l'API StackDriver Logging (v2) moi-même. → ici

Lors de l'utilisation de cette méthode, il est nécessaire de trier la destination de sortie (destination de connexion API) lors de la frappe dans l'environnement de développement local, de la frappe dans l'environnement de préparation, de la frappe dans l'environnement de production et d'une demande Puisqu'il n'est pas bon de frapper l'API plusieurs fois avec, il semble nécessaire de créer un mécanisme pour tamponner l'écriture dans la portée de la requête et exécuter l'API de journalisation.

Dans une telle situation, fluentd s'exécute dans l'environnement FE, et j'ai eu l'information que le fichier craché dans le format approprié est sorti vers la visionneuse de journal dans le format approprié, et la stratégie de sortie de journal va immédiatement à la deuxième génération.

Stratégie de sortie du journal (deuxième génération)

Un agent est installé dans l'environnement FE et un mécanisme de sortie des journaux est préparé.

`Pour connecter votre application d'environnement flexible App Engine à Stackdriver Error Reporting, envoyez des données structurées dans un fichier journal personnalisé. ''

ʻL'agent Stackdriver Logging est installé et configuré par défaut dans l'application App Engine Flexible Environment. ''

https://cloud.google.com/error-reporting/docs/setup/app-engine-flexible-environment

Je vois, j'en suis reconnaissant. Selon les informations, en sortant vers un fichier fixe dans un format fixe, vous pouvez le collecter correctement. Quand.

Quel est le fichier fixe et le format fixe?

Je comprends qu'il existe un mécanisme de sortie, mais je ne connais pas la destination de sortie et la forme du JSON à sortir ...

J'ai fait référence à des documents tels que Utilisation de la journalisation cloud dans les applications App Engine, mais cela ne fonctionne pas subtilement.

N'est-il pas plus rapide d'abandonner le document à partir de ce moment et d'étudier régulièrement le code source et l'environnement? J'ai ressenti cela, alors je suis passé à cette méthode.

Tout d'abord, saisissez l'environnement tout en examinant le référentiel de paramètres autour du conteneur de l'environnement FE appelé Managed VM Sidecar Containers.

Les instances de l'environnement FE peuvent être connectées ssh.

Écrivez le code → déployez → attendez jusqu'à ce que vous réalisiez que vous pouvez vous connecter à ssh. C'était une pénitence, mais si vous pouvez vous connecter, celle-ci. Je vais enquêter sur diverses choses.

Cliquez sur «Instance» d'appengine puis sur «SSH» de l'instance pour lancer le terminal sur le navigateur. スクリーンショット_2016-12-06_18_23_01.png

La destination connectée par le terminal sera une instance de l'environnement FE. (C'est peut-être une instance GCE?) Vérifions le conteneur en cours d'exécution avec la commande suivante.

$ sudo docker ps
CONTAINER ID        IMAGE                                                                                                                         COMMAND                  CREATED             STATUS              PORTS                                        NAMES
61096f77d1a5        gcr.io/google_appengine/nginx-proxy                                                                                           "/var/lib/nginx/bin/s"   About an hour ago   Up About an hour    8080/tcp, 8090/tcp, 0.0.0.0:8443->8443/tcp   thirsty_brattain
3e176f20673a        us.gcr.io/fe-stud/appengine/default.20161206t152342@sha256:330d6b553033c80ad0313fe3c2fd713bdaec873197d00193b6f8a32beda0ca73   "/docker-entrypoint.b"   About an hour ago   Up About an hour    8080/tcp                                     gaeapp
73675d907c83        gcr.io/google_appengine/api-proxy                                                                                             "/proxy"                 About an hour ago   Up About an hour                                                 api
5430f456d28c        gcr.io/google_appengine/fluentd-logger                                                                                        "/opt/google-fluentd/"   About an hour ago   Up About an hour                                                 stupefied_heisenberg

L'instance d'environnement FE a quatre conteneurs s'exécutant sur Docker, et il semble que le conteneur fluentd récupère et envoie le journal lorsque le journal est craché depuis le gaeapp (application) vers le répertoire d'instance hôte partagé. スクリーンショット 2016-12-06 18.12.06.png

Comme il est fluide, le fichier journal à collecter est défini dans File in Github.

/fluentd_logger/managed_vms.conf

C'est comme suit.

Modèle de fichier
/var/log/app_engine/app/app*.log
/var/log/app_engine/app/app*.json
/var/log/app_engine/app/request*.log
/var/log/app_engine/app/STDOUT*.log
/var/log/app_engine/app/STDERR*.log
/var/log/app_engine/app/custom_logs/*.log
/var/log/app_engine/app/custom_logs/*.json
/var/log/app_engine/monitoring/*.log
/var/log/syslog

Je me demande si c'est l'objectif standard. Notez que c'est le chemin à l'intérieur du conteneur fluentd! (J'étais un peu accro à la croyance que le même chemin serait dans le conteneur gaeapp ...)

Voici comment je suis devenu accro. Table de correspondance des chemins de répertoire

Le chemin que le conteneur gaeapp monte Répertoire de journal dans l'instance d'hôte Chemin monté par conteneur fluentd
/var/log/app_engine /var/log/app_engine/app /var/log/app_engine/app

As-tu remarqué? Oui, le chemin du répertoire du journal de l'instance hôte et le conteneur de fluentd sont identiques, mais pour une raison quelconque, le chemin du répertoire du journal de gaeapp est différent. .. ..

Donc, même si je regarde le fichier de paramètres fluentd et que je sort le fichier journal dans gaeapp pour ce répertoire, fluentd ne le récupère pas ... (larmes.

Je pense que c'est une bonne idée de mettre cette zone dans un conteneur fluide et de l'essayer tout en suivant le journal.

Pour entrer dans le conteneur fluentd sur l'instance hôte

$ sudo docker exec -it stupefied_heisenberg bash

Entrez dans le conteneur avec

# tail -f /var/log/google-fluentd/google-fluentd.log

Vous pouvez le voir sur. Au fait, si le journal est correctement récupéré par fluentd

2016-12-06 07:47:25 +0000 [info]: following tail of /var/log/app_engine/app/app.json
2016-12-06 07:54:25 +0000 [info]: following tail of /var/log/app_engine/app/app.log.json

Un journal comme celui-ci est généré. (Notez qu'il n'est sorti que la première fois que le fichier est trouvé.)

Quel est le format JSON requis pour la sortie? ??

Tout d'abord, comment un journal qui n'est pas au format JSON est-il généré par le visualiseur de journaux?

Les journaux de texte sont générés sous forme de texte lors de la sortie dans un fichier avec l'extension * .log. Ce qui diffère du journal au format JSON, c'est que des informations telles que le niveau de journal ne peuvent pas être ajoutées.

Exemple de sortie app.log スクリーンショット 2016-12-06 18.46.25.png Désolé pour l'image allongée. .. Lors de la sortie sous forme de texte (le contenu est au format JSON dans l'exemple), il est sorti sans le niveau de journalisation (icône à gauche).

Je veux toujours le niveau de journalisation lors de la sortie de l'application. Par conséquent, le format JSON requis pour la sortie est indiqué ci-dessous.

Pour sortir un journal au format JSON et le sortir proprement dans la visionneuse de journal. (final?)

Utilisez JsonFormatter.java et LogContext.java dans appengine-java-vm-runtime pour formater le JSON. ..

Même lorsque vous l'utilisez dans d'autres langues, la méthode de format dans JsonFormatter.java n'effectue pas un traitement aussi difficile, donc je pense que vous pouvez l'implémenter en vous référant à cela.

Ainsi, la conclusion est l'exemple de format JSON, qui se présente comme suit.

{
  "timestamp":{"seconds":1481005920,"nanos":927000000},
  "severity":"ERROR",
  "thread":"qtp1347137144-13",
  "message":"TestLogger: === TEST LOG ==="
}

Au fait, lorsque vous utilisez le précédent JsonFormatter, vous utiliserez java.util.logging.LogRecord, mais en guise de mise en garde, vous devez entrer le nom de l'enregistreur en utilisant LogRecord # setLoggerName. Cela ne cause pas d'erreur même si je ne le saisis pas, mais le message JSON ressemble à `" null: === TEST LOG === "ʻet ce n'est pas cool.

Exemple de code approximatif

Level level = Level.SEVERE; //Niveau de journal, équivalent à Erreur
LogRecord record = new LogRecord(level, "=== TEST LOG ===");
record.setLoggerName("TestLogger");
JsonFormatter formatter = new JsonFormatter();
String logString = formatter.format(record); //Vous pouvez afficher cette chaîne sous forme de ligne dans le fichier json.

Si vous pouvez vous préparer jusqu'à présent, vous pourrez cracher du JSON dans un fichier et le sortir proprement dans la visionneuse de journal. スクリーンショット_2016-12-06_18_57_25.png L'exemple est affiché au niveau d'erreur, il y a donc une icône qui ne semble pas être juste une chose [! !! ]

Méthode de sortie en Java (Annexe)

Lors de l'utilisation avec Scala (Java), je voudrais sortir en utilisant slf4j / logback etc., mais j'ai pu sortir par la méthode suivante.

Ajoutez ʻappengine-java-logging et ʻappengine-managed-runtime au projet pom.xml

pom.xml


<!-- https://mvnrepository.com/artifact/com.google.appengine/appengine-java-logging -->
<dependency>
    <groupId>com.google.appengine</groupId>
    <artifactId>appengine-java-logging</artifactId>
    <version>1.9.31</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.appengine/appengine-managed-runtime -->
<dependency>
    <groupId>com.google.appengine</groupId>
    <artifactId>appengine-managed-runtime</artifactId>
    <version>1.9.31</version>
</dependency>

Appelez VmRuntimeFileLogHandler # init quelque part dans votre application.

Cela spécifie en interne les paramètres de sortie du journal.

VmRuntimeFileLogHandler.java


// ~~ snip ~~
    private static String fileLogPattern() {
        String pattern = System.getenv("APP_ENGINE_LOG_CONFIG_PATTERN");
        if(pattern != null) {
            return pattern;
        } else {
            String directory = System.getProperty("com.google.apphosting.logs", "/var/log/app_engine");
            pattern = System.getProperty("com.google.apphosting.vmruntime.VmRuntimeFileLogHandler.pattern");
            return pattern != null?(pattern.startsWith("/")?pattern:directory + "/" + pattern):directory + "/" + "app.%g.log.json";
        }
    }
// ~~ snip ~~

Vous pouvez publier le contenu spécifié dans logback.xml etc. en vous référant à cette classe. Dans ce cas, vous n'avez pas besoin d'appeler VmRuntimeFileLogHandler # init.

Générer un enregistreur et sortir un journal

LogSample.java


Logger logger = Logger.getLogger("com");  //Génération d'enregistreurs

logger.warning("= WARNING TEST ="); //Sortie de journal

Définissez logging.properties selon vos besoins

.level=ALL

com.level=SEVERE

Merci

Nous tenons à remercier @soundTricker pour nous avoir fourni diverses informations et consultations concernant la sortie des journaux dans l'environnement FE.

Recommended Posts

Ce que j'ai fait pour générer les journaux d'application dans l'environnement flexible GAE.
Ce que j'ai fait pour établir une connexion SSH à l'environnement VPS Ubuntu
Ce que j'ai fait pour économiser la mémoire Python
[Python] Ce que j'ai fait pour faire un test unitaire
Ce que j'ai fait lors de la mise à jour de Python 2.6 vers 2.7
Ce à quoi j'étais accro lors de la création d'applications Web dans un environnement Windows
Je souhaite développer des applications Android sur Android (débogage)
Ce que j'ai fait pour accélérer la tâche de recherche de chaînes
Ce que j'ai fait pour accueillir le Python2 EOL en toute confiance
J'ai essayé de créer un environnement serveur qui fonctionne sous Windows 10
J'ai essayé de créer un environnement de MkDocs sur Amazon Linux
Notez ce que vous avez fait pour utiliser Flycheck avec Python
Je ne sais pas comment obtenir les paramètres de requête dans GAE / P
J'ai essayé de résumer ce qui était sorti avec Qiita avec Word cloud
Ce que j'ai fait quand je voulais rendre Python plus rapide -Édition Numba-
H29.2.27 ~ 3.5 Résumé de ce que j'ai fait
Ce que j'ai fait pour garder une trace de l'humidité et de la température des archives
[Chez Coder] Ce que j'ai fait pour atteindre le rang vert en Python