[PYTHON] Une histoire que j'ai corrigée lorsque j'ai obtenu le journal Lambda de Cloudwatch Logs

C'est le 21e jour du cloudpack Ara Convenient Calendar 2017!


J'utilisais Python pour obtenir les journaux Lambda à partir de Cloudwatch Logs. Quand j'ai essayé de l'obtenir récemment, j'ai eu une erreur, alors j'ai essayé de la réparer un peu.


Histoire il y a environ six mois

Auparavant, je pensais transférer les journaux Lambda dans Cloudwatch Logs vers un serveur (EC2) pour les entreprises et enquêter sur diverses choses. Obtenir les journaux de CloudWatch Logs (j'ai essayé de spécifier la période) Je l'ai fait en référence et je l'ai utilisé pour étudier le système en cours de développement. Cela a été très utile. Merci beaucoup! Nous aimerions profiter de cette occasion pour vous remercier.

Le problème survient après son utilisation après une longue période

Je ne l'ai pas utilisé depuis un moment

De l'utilisateur

Obtenez un journal de cette heure de la journée pendant un moment

Cela dit, il est difficile de tout retirer à la fois de la console. Utilisez-vous celui que vous avez fait avant? J'ai essayé de l'utiliser après un long moment. .. .. Ça ne finit jamais. Même si vous spécifiez 1 minute, cela ne se termine pas. Pourquoi pas? !! J'ai essayé d'insérer le journal et de le chercher. .. ..

** Essayer de prendre à partir d'un flux à terme. .. .. ** **

Cela fait environ 3 mois qu'il a commencé à fonctionner, et avec quelques journaux. C'est un journal balayé de toute la période, ce qui prend du temps. C'était dans un tel état.

Rénovation

Je ne pouvais pas l'obtenir tel quel ... J'ai donc décidé de le réparer, j'ai recherché diverses choses et j'ai finalement examiné le document du SDK. De la méthode pour obtenir le flux de journal describe_log_streams En tant qu'argument de J'ai remarqué que je peux spécifier le nom du flux de journal comme préfixe. Boto 3 Documentation - describe_log_streams Pour les journaux Lambda, vous pouvez affiner en spécifiant la date ici! Alors, ajoutez une date à l'argument d'exécution (concentrez-vous sur la vitesse de développement), Implémentation d'une modification à ajouter à l'argument de describe_log_streams Courir! ... Cela s'est terminé en un clin d'œil (mais pas si vite).

Source après rénovation

getCwLogs.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import sys
import codecs
import boto3
import time
from datetime import datetime
from datetime import timedelta

sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
log_group = sys.argv[1]
date = datetime.now().strftime("%Y%m%d-%H%M%S")
#Répertoire de sortie
log_directory_base ='./cwlogs'
slice = log_group[0:1]
if (slice == '/'):
    log_directory = log_directory_base + "%s/%s" % (log_group, date)
else:
    log_directory = log_directory_base + "/%s/%s" % (log_group, date)

def validate():
    if(len(sys.argv) != 5):
        print '[ ERROR ] Few arguments.'
        print 'Please specify the argument.'
        print 'First: LogGroupName, Second: StartTime, Third: EndTime, Fourth: profileName., Fifth: logPrefixName'
        sys.exit()
    try:
        epoc = datetime(1970, 1, 1)
        global starttime
        starttime  = int((datetime.strptime(sys.argv[2], '%Y-%m-%dT%H:%M:%S') - epoc).total_seconds()) * 1000
        global endtime
        endtime  = int((datetime.strptime(sys.argv[3], '%Y-%m-%dT%H:%M:%S') - epoc).total_seconds()) * 1000
        durationtime = int(endtime - starttime)
        print 'durationtime "%s"' % durationtime
        if 86400000 < durationtime:
            print '[ ERROR ] Too long duration.'
            print 'Max duration is 1 day.'
            sys.exit()
        global log_stream_name_prefix
        log_stream_name_prefix = sys.argv[4]
    except ValueError:
        print '[ ERROR ] Failed StartTime or EndTime format.'
        print 'Date Format is "%Y-%m-%dT%H:%M:%S".'
        sys.exit()

def find_streams(token, log_stream_name_prefix):
    def is_valid_stream(stream):
        return starttime < stream.get('lastIngestionTime')
    try:
        if token is None:
            data =  cwlogs.describe_log_streams(logGroupName = log_group, logStreamNamePrefix = log_stream_name_prefix)
        else:
            data =  cwlogs.describe_log_streams(logGroupName = log_group, logStreamNamePrefix = log_stream_name_prefix, nextToken = token)

    except ValueError:
        print '[ ERROR ] Failed LogGroupName is invalid.'
        print '"%s" is not found.' % log_group
        sys.exit()

    streams = filter(is_valid_stream, data['logStreams'])
    if 'nextToken' not in data:
        return streams
    time.sleep(0.5)
    streams.extend(find_streams(data['nextToken'], log_stream_name_prefix))
    return streams

def find_events(token, last_token, stream):
    print 'logGroupName = "%s", logStreamName = "%s", startTime = "%s", endTime = "%s"' % (log_group, stream, starttime, endtime)
    if token is None:
        data = cwlogs.get_log_events(logGroupName = log_group, logStreamName = stream, startTime = starttime, endTime = endtime, startFromHead = True)
    else:
        data = cwlogs.get_log_events(logGroupName = log_group, logStreamName = stream, startTime = starttime, endTime = endtime, startFromHead = True, nextToken = token)

    events = data['events']
    if events:
        write_logs(events, stream)
        del events[:]
    if data['nextForwardToken'] != last_token:
        time.sleep(0.5)
        find_events(data['nextForwardToken'], token, stream)

def write_logs(events, stream):
    streams = stream.split(']');
    if (len(streams) > 1):
        #Journal Lambda
        with codecs.open("%s/%s.log" % (log_directory, streams[1]), "a", "utf-8") as f:
            for e in events:
                f.write("%s\n" % e['message'])
    else:
        #Autres journaux
        with codecs.open("%s/%s.log" % (log_directory, streams[0]), "a", "utf-8") as f:
            for e in events:
                f.write("%s\n" % e['message'])

def main():
    validate()
    global cwlogs
    cwlogs = boto3.client('logs')
    streams = [stream['logStreamName'] for stream in find_streams(None, log_stream_name_prefix)]
    os.makedirs("%s/" %)
    print(log_directory)

    for stream in streams:
        find_events(None, None, stream)

if __name__ == '__main__':
    main()


cmd


#Pour Lambda
python getCWLogs.py log nom du groupe date et heure de début(UTC)Date et heure de fin(UTC)Nom du flux de journal première date
#Autre que Lambda(Passerelle API)dans le cas de
python getCWLogs.py log nom du groupe date et heure de début(UTC)Date et heure de fin(UTC)Nom du flux de journal

Utilisation actuelle

Je l'utilise lorsque je veux obtenir le journal Lambda pendant un certain temps, le rechercher avec grep ou l'agréger avec Excel (il deviendra).


Je l'ai écrit pendant un moment, mais Est-ce utile pour d'autres personnes? C'était une histoire typique.

Recommended Posts

Une histoire que j'ai corrigée lorsque j'ai obtenu le journal Lambda de Cloudwatch Logs
Une histoire à laquelle j'étais accro à appeler Lambda depuis AWS Lambda.
Une histoire qui a souffert d'une différence de système d'exploitation lors de la tentative d'implémentation d'un article
Une histoire à laquelle j'étais accro après la communication SFTP avec python
Une histoire qui était pratique lorsque j'ai essayé d'utiliser le module d'adresse IP python
Une histoire bloquée lors de la tentative de mise à niveau de la version Python avec GCE
Fonction Lambda (version python) qui décompresse et génère des éléments dans CloudWatch Logs lorsqu'un fichier compressé est téléchargé vers s3
J'ai un UnicodeDecodeError lorsque je pip installé sur ubuntu
Une histoire à laquelle j'étais accro chez np.where
J'ai un sqlite3.OperationalError
Une histoire qui a disparu quand j'ai spécifié un chemin commençant par tilda (~) en python open
python Extraction de condition de la liste que j'oublie souvent
[Python] Exportez régulièrement de CloudWatch Logs vers S3 avec Lambda
Une histoire qui n'a pas fonctionné lorsque j'ai essayé de me connecter avec le module de requêtes Python
Déplacer régulièrement les journaux CloudWatch vers S3 avec Lambda
J'ai un TypeError: l'objet 'int' n'est pas itérable lors de l'utilisation de keras
L'histoire de l'erreur de hachage est apparue lors de l'utilisation de Pipenv
Je suis tombé sur une expression lambda alors que je m'inquiétais de la fonctionnalisation
J'ai créé un bot Discord en Python qui se traduit quand il réagit
J'ai essayé de développer un formateur qui génère des journaux Python en JSON
J'ai fait une simple minuterie qui peut être démarrée depuis le terminal
Un rappel de ce que je suis resté coincé lors du démarrage d'Atcoder avec python
[Serveur Web] Une histoire où j'ai enquêté parce que je ne pouvais pas accéder à nginx
J'ai écrit un bot Slack qui notifie les informations de retard avec AWS Lambda