web-dev-qa-db-ja.com

AWS Cloudwatchの請求は莫大です。どのログストリームが原因となっているかを調べるにはどうすればよいですか?

先月、AmazonからCloudwatchサービスについて$ 1,200の請求書を受け取りました(具体的には、「AmazonCloudWatch PutLogEvents」での2 TBのログデータ取り込みの場合))。数十ドルを期待していました。 AWSコンソールのCloudwatchセクションにログインし、私のロググループの1つが約2TBのデータを使用しているのを確認できますが、そのロググループには何千もの異なるログストリームがあり、どれがその量のデータを使用したかをどのように確認できますか?

17
Sam Critchley

CloudWatchコンソールで、IncomingBytesメトリックスを使用して、[メトリックス]ページを使用して、特定の期間の各ロググループによって取り込まれた非圧縮バイトのデータ量を見つけます。以下の手順に従ってください-

  1. CloudWatchメトリックスページに移動し、AWS名前空間「ログ」->「ロググループメトリックス」をクリックします。
  2. 必要なロググループのIncomingBytesメトリックを選択し、[グラフ化されたメトリック]タブをクリックしてグラフを表示します。
  3. 開始時刻と終了時刻を30日になるように変更し、期間を30日に変更します。この方法では、データポイントを1つだけ取得します。また、グラフを数値に、統計を合計に変更しました。

このようにして、各ロググループが取り込んだデータの量を確認し、どのロググループがどのくらい取り込んでいるかを把握できます。

enter image description here

AWS CLIを使用しても同じ結果を得ることができます。たとえば30日間ロググループによって取り込まれたデータの合計量を知りたいだけのシナリオの例では、get-metric-statistics CLIコマンドを使用できます。

サンプル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

サンプル出力-

{
    "Datapoints": [
        {
            "Timestamp": "2018-05-01T00:00:00Z", 
            "Sum": 1686361672.0, 
            "Unit": "Bytes"
        }
    ], 
    "Label": "IncomingBytes"
}

特定のロググループについて同じものを見つけるには、次のようなディメンションに対応するようにコマンドを変更できます-

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

1つずつ、このコマンドをすべてのロググループで実行し、どのロググループが取り込んだデータの請求の大部分を担当しているかを確認し、修正措置をとることができます。

注:ご使用の環境と要件に固有のパラメーターを変更します。

OPが提供するソリューションは、取り込まれたログとは異なる、保存されたログの量に関するデータを提供します。

違いは何ですか?

1か月に取得されるデータは、データストレージのバイト数とは異なります。データがCloudWatchに取り込まれた後、ログイベントごとに26バイトのメタデータを含むCloudWatchによってアーカイブされ、gzipレベル6圧縮を使用して圧縮されます。したがって、ストレージバイトは、ログの取り込み後にCloudwatchがログを保存するために使用するストレージスペースを指します。

リファレンス: https://docs.aws.Amazon.com/cli/latest/reference/cloudwatch/get-metric-statistics.html

39
Deepak Puthraya

私たちは偶然のチェックインのためにラムダロギングGBのデータを持っていました。上記の回答の情報に基づいたboto3ベースのpythonスクリプトは、すべてのロググループをスキャンし、過去7日間に1GBを超えるログを持つグループを出力します。これは、私が試すよりも助けになりました更新が遅いAWSダッシュボードを使用する。

#!/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))
        
10
Diego Link

さて、私は 自分の質問に答える ここですが、ここに行きます(他のすべての答えを歓迎します):

AWS CLIツール、csvfix CSVパッケージ、スプレッドシートの組み合わせを使用して、これを解決できます。

  • AWS Cloudwatch Consoleにログインし、すべてのデータを生成したロググループの名前を取得します。私の場合、「test01-ecs」と呼ばれています。
  • 残念ながらCloudwatchコンソールでは、「Stored Bytes」でストリームをソートすることはできません(どのバイトが最大であるかがわかります)。ロググループにストリームが多すぎてコンソールで確認できない場合は、何らかの方法でそれらをダンプする必要があります。これには、AWS CLIツールを使用できます。

    $ aws logs describe-log-streams --log-group-name test01-ecs

  • 上記のコマンドはJSON出力を提供し(AWS CLIツールがJSON出力に設定されていると仮定します-そうでない場合はoutput = json~/.aws/configに設定します)、次のようになります。

    { "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 } ] }

  • この出力をJSONファイルにパイプします-私の場合、ファイルのサイズは31 MBでした:

    $ aws logs describe-log-streams --log-group-name test01-ecs >> ./cloudwatch-output.json

  • in2csvパッケージ( csvfix の一部)を使用して、JSONファイルを簡単にインポートできるCSVファイルに変換しますスプレッドシート。インポートに使用するlogStreamsキーを必ず定義します。

    $ in2csv cloudwatch-output.json --key logStreams >> ./cloudwatch-output.csv

  • 結果のCSVファイルをスプレッドシートにインポートします(私は LibreOffice 自分で使用します。CSVを扱うのが得意なので)=storedBytesフィールドは整数としてインポートされます。

  • スプレッドシートのstoredBytes列をソートして、どのログストリームが最も多くのデータを生成しているかを調べます。

私の場合これはうまくいきました-それは私の壊れたログストリームの1つでした(redisインスタンスのTCPパイプからのログで))他のすべてのストリームを合わせたサイズの4,000倍でした!

6
Sam Critchley

質問の作成者や他の人々は良い方法で質問に回答しましたが、私は適用できる一般的な解決策を持っているようにしようと思います正確に知らずにロググループ名も引き起こしていますログの多く。

これを行うには、notを使用できますdescribe-log-streams関数を使用します-log-group-nameが必要になるため、前述のとおり以前、log-group-nameの値がわかりません。

describe-log-groups関数を使用できます。この関数はパラメーターを必要としないためです。

注意〜/ .aws/configファイルに必要なフラグ(--region)が設定されており、EC2インスタンスにこれを実行するために必要な権限があると想定していますコマンド。

aws logs describe-log-groups

このコマンドは、awsアカウントのすべてのロググループを一覧表示します。これのサンプル出力は次のようになります

 {
    "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"
        }
    ]
}

ロググループのみの特定のプレフィックスパターンに関心がある場合は、次のように-log-group-name-prefixを使用できます

aws logs describe-log-groups --log-group-name-prefix /aws/lambda

このコマンドの出力JSONも上記の出力に似ています。

アカウント内のロググループが多すぎる場合、これの出力の分析は困難になり、結果を簡単に把握するためのコマンドラインユーティリティが必要になります。 「jq」コマンドラインユーティリティを使用して、目的のものを取得します。意図はどのロググループが最も多くのログを生成したかを取得することであり、したがってより多くのお金が発生します。

出力JSONから、分析に必要なフィールドは「logGroupName」と「storedBytes」になります。したがって、これらの2つのフィールドを「jq」コマンドで使用します。

aws logs describe-log-groups --log-group-name-prefix /aws/ 
| jq -M -r '.logGroups[] | "{\"logGroupName\":\"\(.logGroupName)\",
\"storedBytes\":\(.storedBytes)}"'

コマンドで '\'を使用してエスケープを実行します。これは、jqのsort_by関数を使用するために、出力をJSON形式onlyにするためです。このサンプル出力は以下のようになります。

{"logGroupName":"/aws/lambda/test1","storedBytes":3045647212}
{"logGroupName":"/aws/lambda/projectTest","storedBytes":200165401}
{"logGroupName":"/aws/lambda/projectTest2","storedBytes":200}

出力結果はstoredBytesではソートされないので、どのロググループが最も問題のあるロググループであるかを取得するために、それらをソートすることに注意してください。

これを行うには、jqのsort_by関数を使用します。サンプルコマンドは次のようになります

aws logs describe-log-groups --log-group-name-prefix /aws/ 
| jq -M -r '.logGroups[] | "{\"logGroupName\":\"\(.logGroupName)\",
\"storedBytes\":\(.storedBytes)}"' 
|  jq -s -c 'sort_by(.storedBytes) | .[]'

これにより、上記のサンプル出力に対して以下の結果が生成されます

{"logGroupName":"/aws/lambda/projectTest2","storedBytes":200}
{"logGroupName":"/aws/lambda/projectTest","storedBytes":200165401}
{"logGroupName":"/aws/lambda/test1","storedBytes":3045647212}

このリストの下部にある要素は、最も多くのログが関連付けられている要素です。 Expire Events Afterプロパティを有限期間、たとえばこれらのロググループに1か月に設定できます。

すべてのログバイトの合計を知りたい場合は、以下のようにjqの「マップ」および「追加」関数を使用できます。

 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 '

上記のサンプル出力に対するこのコマンドの出力は、次のようになります。

3245812813

答えは長くなりましたが、cloudwatchで最も問題のあるロググループを特定するのに役立つことを願っています。

2

Cloudwatchログダッシュボードの歯車の歯車をクリックして、[格納されたバイト]列を選択することもできます。

また、「期限切れなし」と表示されたものをクリックして、ログを期限切れに変更しました。

cloudwatch logs gearを使用し、[Stored Bytes]列を選択します

0
jfo8000