J'ai reçu une facture de 1 200 $ d'Amazon pour les services Cloudwatch le mois dernier (en particulier pour 2 TB d'ingestion de données de journal dans "AmazonCloudWatch PutLogEvents")), alors que je m'attendais à quelques dizaines de dollars. connecté à la section Cloudwatch de la console AWS, et peut voir que l'un de mes groupes de journaux a utilisé environ 2 To de données, mais il y a des milliers de flux de journaux différents dans ce groupe de journaux, comment puis-je savoir lequel a utilisé cette quantité de données?
Sur la console CloudWatch, utilisez les métriques IncomingBytes pour trouver la quantité de données ingérées par chaque groupe de journaux pour une période donnée en octets non compressés à l'aide de la page Métriques. Suivez les étapes ci-dessous -
De cette façon, vous verrez la quantité de données ingérées par chaque groupe de journaux et vous aurez une idée de quel groupe de journaux ingère combien.
Vous pouvez également obtenir le même résultat à l'aide de l'AWS CLI. Un exemple de scénario dans lequel vous souhaitez simplement connaître la quantité totale de données ingérées par les groupes de journaux pendant 30 jours, par exemple, vous pouvez utiliser la commande CLI get-metric-statistics
exemple de commande CLI -
aws cloudwatch get-metric-statistics --metric-name IncomingBytes --start-time 2018-05-01T00:00:00Z --end-time 2018-05-30T23:59:59Z --period 2592000 --namespace AWS/Logs --statistics Sum --region us-east-1
exemple de sortie -
{
"Datapoints": [
{
"Timestamp": "2018-05-01T00:00:00Z",
"Sum": 1686361672.0,
"Unit": "Bytes"
}
],
"Label": "IncomingBytes"
}
Pour trouver la même chose pour un groupe de journaux particulier, vous pouvez modifier la commande pour prendre en charge des dimensions telles que -
aws cloudwatch get-metric-statistics --metric-name IncomingBytes --start-time 2018-05-01T00:00:00Z --end-time 2018-05-30T23:59:59Z --period 2592000 --namespace AWS/Logs --statistics Sum --region us-east-1 --dimensions Name=LogGroupName,Value=test1
Un par un, vous pouvez exécuter cette commande sur tous les groupes de journaux et vérifier quel groupe de journaux est responsable de la majeure partie de la facture des données ingérées et prendre des mesures correctives.
REMARQUE: modifiez les paramètres spécifiques à votre environnement et à vos besoins.
La solution fournie par OP fournit des données pour la quantité de journaux stockés qui sont différents des journaux ingérés.
Quelle est la différence?
Les données ingérées par mois ne sont pas identiques aux octets de stockage de données. Une fois les données ingérées dans CloudWatch, elles sont archivées par CloudWatch qui inclut 26 octets de métadonnées par événement de journal et sont compressées à l'aide de la compression gzip de niveau 6. Ainsi, les octets de stockage se réfèrent à l'espace de stockage utilisé par Cloudwatch pour stocker les journaux après leur ingestion.
Référence: https://docs.aws.Amazon.com/cli/latest/reference/cloudwatch/get-metric-statistics.html
Nous avions un lambda enregistrant Go de données en raison d'un enregistrement accidentel. Voici un script python basé sur boto3 basé sur les informations des réponses ci-dessus qui analyse tous les groupes de journaux et imprime tout groupe avec des journaux supérieurs à 1 Go au cours des 7 derniers jours. Cela m'a aidé plus qu'à essayer pour utiliser le tableau de bord AWS qui était lent à mettre à jour.
#!/usr/bin/env python3
# Outputs all loggroups with > 1GB of incomingBytes in the past 7 days
import boto3
from datetime import datetime as dt
from datetime import timedelta
logs_client = boto3.client('logs')
cloudwatch_client = boto3.client('cloudwatch')
end_date = dt.today().isoformat(timespec='seconds')
start_date = (dt.today() - timedelta(days=7)).isoformat(timespec='seconds')
print("looking from %s to %s" % (start_date, end_date))
paginator = logs_client.get_paginator('describe_log_groups')
pages = paginator.paginate()
for page in pages:
for json_data in page['logGroups']:
log_group_name = json_data.get("logGroupName")
cw_response = cloudwatch_client.get_metric_statistics(
Namespace='AWS/Logs',
MetricName='IncomingBytes',
Dimensions=[
{
'Name': 'LogGroupName',
'Value': log_group_name
},
],
StartTime= start_date,
EndTime=end_date,
Period=3600 * 24 * 7,
Statistics=[
'Sum'
],
Unit='Bytes'
)
if len(cw_response.get("Datapoints")):
stats_data = cw_response.get("Datapoints")[0]
stats_sum = stats_data.get("Sum")
sum_GB = stats_sum / (1000 * 1000 * 1000)
if sum_GB > 1.0:
print("%s = %.2f GB" % (log_group_name , sum_GB))
D'accord, je suis répondant à ma propre question ici, mais c'est parti (avec toutes les autres réponses bienvenues):
Vous pouvez utiliser une combinaison d'outils AWS CLI, le package csvfix CSV et une feuille de calcul pour résoudre ce problème.
Malheureusement, dans la console Cloudwatch, vous ne pouvez pas trier les flux par "octets stockés" (qui vous indiqueraient lesquels sont les plus importants). S'il y a trop de flux dans le groupe de journaux à parcourir dans la console, vous devez les vider d'une manière ou d'une autre. Pour cela, vous pouvez utiliser l'outil AWS CLI:
$ aws logs describe-log-streams --log-group-name test01-ecs
La commande ci-dessus vous donnera une sortie JSON (en supposant que votre outil AWS CLI est défini sur la sortie JSON - définissez-le sur output = json
dans ~/.aws/config
sinon) et cela ressemblera à ceci:
{ "logStreams": [ { "creationTime": 1479218045690, "arn": "arn:aws:logs:eu-west-1:902720333704:log-group:test01-ecs:log-stream:test-spec/test-spec/0307d251-7764-459e-a68c-da47c3d9ecd9", "logStreamName": "test-spec/test-spec/0308d251-7764-4d9f-b68d-da47c3e9ebd8", "storedBytes": 7032 } ] }
Dirigez cette sortie vers un fichier JSON - dans mon cas, le fichier avait une taille de 31 Mo:
$ aws logs describe-log-streams --log-group-name test01-ecs >> ./cloudwatch-output.json
Utilisez le package in2csv (partie de csvfix ) pour convertir le fichier JSON en fichier CSV qui peut facilement être importé dans un feuille de calcul, en veillant à définir la clé logStreams à utiliser pour importer sur:
$ in2csv cloudwatch-output.json --key logStreams >> ./cloudwatch-output.csv
Importez le fichier CSV résultant dans une feuille de calcul (j'utilise LibreOffice moi-même car il semble excellent pour traiter le CSV) en vous assurant que les octets stockés est importé sous forme d'entier.
Dans mon cas, cela a fonctionné - il s'est avéré que l'un de mes flux de journaux (avec les journaux d'un tube TCP pipe dans une instance de redis) était 4 000 fois la taille de tous les autres flux combinés!
Bien que l'auteur de la question et d'autres personnes aient répondu à la question dans le bon sens, j'essaierai d'avoir une solution générique qui pourrait être appliquée sans connaître l'exact log-group-name qui cause aussi beaucoup de journaux.
Pour ce faire, nous pouvons pas utiliser la fonction describe-log-streams car cela nécessiterait - log-group-name et comme je l'ai dit plus tôt, je ne connais pas la valeur de mon nom de groupe de journaux.
Nous pouvons utiliser la fonction describe-log-groups car cette fonction ne nécessite aucun paramètre.
Notez que Je suppose que vous avez le drapeau requis (--region) configuré dans le fichier ~/.aws/config et votre instance EC2 a la permission requise pour exécuter ceci commander.
aws logs describe-log-groups
Cette commande répertorierait tous les groupes de journaux de votre compte aws. L'échantillon de sortie de ce serait
{
"logGroups": [
{
"metricFilterCount": 0,
"storedBytes": 62299573,
"arn": "arn:aws:logs:ap-southeast-1:855368385138:log-group:RDSOSMetrics:*",
"retentionInDays": 30,
"creationTime": 1566472016743,
"logGroupName": "/aws/lambda/us-east-1.test"
}
]
}
Si vous êtes intéressé par un modèle de préfixe spécifique uniquement pour le groupe de journaux, vous pouvez utiliser - log-group-name-prefix comme ceci
aws logs describe-log-groups --log-group-name-prefix /aws/lambda
Le JSON de sortie de cette commande serait également similaire à la sortie ci-dessus.
Si vous avez trop de groupes de journaux dans votre compte, l'analyse de la sortie de celui-ci devient difficile et nous avons besoin d'un utilitaire de ligne de commande pour donner un bref aperçu du résultat. Nous utiliserons l'utilitaire de ligne de commande 'jq' pour obtenir la chose souhaitée. L'intention est d'obtenir quel groupe de journaux a produit le plus de journaux et donc de provoquer plus d'argent.
A partir du JSON de sortie, les champs dont nous avons besoin pour notre analyse seraient "logGroupName" et "storedBytes". Donc, en prenant ces 2 champs dans la commande 'jq'.
aws logs describe-log-groups --log-group-name-prefix /aws/
| jq -M -r '.logGroups[] | "{\"logGroupName\":\"\(.logGroupName)\",
\"storedBytes\":\(.storedBytes)}"'
Utiliser '\' dans la commande pour faire l'échappement car nous voulons que la sortie soit au format JSON seulement pour utiliser la fonction sort_by de jq. L'exemple de sortie de ceci serait quelque chose comme ci-dessous:
{"logGroupName":"/aws/lambda/test1","storedBytes":3045647212}
{"logGroupName":"/aws/lambda/projectTest","storedBytes":200165401}
{"logGroupName":"/aws/lambda/projectTest2","storedBytes":200}
Notez que le résultat de sortie ne serait pas trié sur storedBytes, nous voulons donc les trier afin d'obtenir quel groupe de journaux est le plus problématique.
nous utiliserons la fonction sort_by de jq pour accomplir cela. L'exemple de commande serait comme ceci
aws logs describe-log-groups --log-group-name-prefix /aws/
| jq -M -r '.logGroups[] | "{\"logGroupName\":\"\(.logGroupName)\",
\"storedBytes\":\(.storedBytes)}"'
| jq -s -c 'sort_by(.storedBytes) | .[]'
Cela produirait le résultat ci-dessous pour l'échantillon de sortie ci-dessus
{"logGroupName":"/aws/lambda/projectTest2","storedBytes":200}
{"logGroupName":"/aws/lambda/projectTest","storedBytes":200165401}
{"logGroupName":"/aws/lambda/test1","storedBytes":3045647212}
Les éléments du bas de cette liste sont ceux qui ont le plus de journal associé. Vous pouvez définir la propriété Expire Events After sur une période finie, disons 1 mois pour ces groupes de journaux.
Si vous voulez savoir quelle est la somme de tous les octets de journal, vous pouvez utiliser la fonction 'map' et 'add' de jq comme ci-dessous.
aws logs describe-log-groups --log-group-name-prefix /aws/
| jq -M -r '.logGroups[] | "{\"logGroupName\":\"\(.logGroupName)\",
\"storedBytes\":\(.storedBytes)}"'
| jq -s -c 'sort_by(.storedBytes) | .[]'
| jq -s 'map(.storedBytes) | add '
La sortie de cette commande pour l'exemple de sortie ci-dessus serait
3245812813
La réponse est devenue longue, mais j'espère que cela aidera à déterminer le groupe de journaux le plus problématique dans cloudwatch.
Vous pouvez également cliquer sur l'engrenage de l'engrenage dans le tableau de bord des journaux de cloudwatch et choisir la colonne d'octets stockés.
J'ai également cliqué sur tout ce qui disait "ne jamais expirer" et changé les journaux pour expirer.
tilisez l'engrenage des journaux cloudwatch et sélectionnez la colonne "Octets stockés"