PlayerId値を含むログファイルがあります。一部のプレーヤーには、ファイルに複数のエントリがあります。ログファイルに1つまたは複数のエントリがあるかどうかに関係なく、一意のプレーヤーの正確な数を取得したいと思います。
以下のクエリを使用すると、497件のレコードがスキャンされ、346個の一意の行が見つかります(346は必要な数です)クエリ:
fields @timestamp, @message
| sort @timestamp desc
| filter @message like /(playerId)/
| parse @message "\"playerId\": \"*\"" as playerId
| stats count(playerId) as CT by playerId
代わりにcount_distinctを使用するようにクエリを変更すると、必要なものが正確に得られます。以下の例:
fields @timestamp, @message
| sort @timestamp desc
| filter @message like /(playerId)/
| parse @message "\"playerId\": \"*\"" as playerId
| stats count_distinct(playerId) as CT
ただし、count_distinctの問題は、クエリがより大きなタイムフレーム/より多くのレコードに拡大すると、エントリの数が数千、数万になることです。 Insightsのcount_distinct動作の性質により、数値が近似値になるため、これには問題があります...
「フィールドの一意の値の数を返します。フィールドのカーディナリティが非常に高い(多くの一意の値が含まれている)場合、count_distinctから返される値は概算です。」.
ドキュメント: https://docs.aws.Amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html
正確な数が必要なので、これは受け入れられません。クエリを少し遊んで、count_distinct()ではなくcount()を使用する答えは正しいと思いますが、1つの数値に到達できませんでした...機能しない例...考え?
例1:
fields @timestamp, @message
| sort @timestamp desc
| filter @message like /(playerId)/
| parse @message "\"playerId\": \"*\"" as playerId
| stats count(playerId) as CT by playerId
| stats count(*)
クエリを理解できません。
明確にするために、数値を示す単一の行で返される正確な数を探しています。
「1」にハードコードされたダミーフィールドを導入するとどうなるでしょうか。アイデアは、同じplayerId
が複数回発生しても「1」のままになるように最小値を取得することです。そして、このフィールドを合計します。
ログエントリは次のようになります。
[1]"playerId": "1b45b168-00ed-42fe-a977-a8553440fe1a"
クエリ:
fields @timestamp, @message
| sort @timestamp desc
| filter @message like /(playerId)/
| parse @message "[*]\"playerId\": \"*\"" as dummyValue, playerId
| stats sum(min(dummyValue)) by playerId as CT
使用される参照: