rubyフィルターでのHashの扱いについて

logstashのrubyフィルターを使用しています。

■inputデータ

{
	"Records": [
		{
			"eventVersion": "1.03",
			"userIdentity": {
				"type": "Root",
				"principalId": "123456789012",
				"arn": "arn:aws:iam::123456789012:root",
				"accountId": "123456789012",
				"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
				"userName": "user"
			},
			"eventTime": "2021-12-03T08:27:45Z",
			"eventSource": "ec2.amazonaws.com",
			"eventName": "TerminateInstances",
			"awsRegion": "us-west-2",
			"sourceIPAddress": "198.51.100.1",
			"userAgent": "aws-cli/1.10.10Python/2.7.9Windows/7botocore/1.4.1",
			"requestParameters": {
				"instancesSet": {
					"items": [
						{
							"instanceId": "i-1a2b3c4d"
						}
					]
				}
			},
			"responseElements": {
				"instancesSet": {
					"items": [
						{
							"instanceId": "i-1a2b3c4d",
							"currentState": {
								"code": 32,
								"name": "shutting-down"
							},
							"previousState": {
								"code": 16,
								"name": "running"
							}
						},
						{
							"instanceId": "i-2a2b3c4d",
							"currentState": {
								"code": 32,
								"name": "shutting-down2"
							},
							"previousState": {
								"code": 16,
								"name": "running2"
							}
						}
					]
				}
			},
			"requestID": "be112233-1ba5-4ae0-8e2b-1c302EXAMPLE",
			"eventID": "6e12345-2a4e-417c-aa78-7594fEXAMPLE",
			"eventType": "AwsApiCall",
			"recipientAccountId": "123456789012"
		}
	]
}

■logstashのconfファイル(抜粋)

filter {
  json {
   source => "message"
  }
  split {
      field => "Records"
  }
  ruby {
    code => "
    instanceId_tmp = []
    name_tmp = []
    TargetInstanceIdtmp= []
    hash = {}
    if !event.get('[Records][responseElements][instancesSet][items]').nil? then
        for field in event.get('[Records][responseElements][instancesSet][items]') do
             hash['instanceId'] = field['instanceId']
             hash['name'] = field['currentState']['name']
             TargetInstanceIdtmp.push(hash)
        end
        event.set('TargetInstanceId', TargetInstanceIdtmp)
   end
   "
  }
}

inputファイルの[Records][responseElements][instancesSet][items]配下をループし、['instanceId']及び['currentState']['name']を取得し、マップ型で別のフィールド(TargetInstanceId)に保持したいです。

上記のconfファイル、inputデータを使用した時のElasticsearchの登録結果は以下となります。

  "_source": {
    "TargetInstanceId": [
      {
        "instanceId": "i-2a2b3c4d",
        "name": "shutting-down2"
      },
      {
        "instanceId": "i-2a2b3c4d",
        "name": "shutting-down2"
      }
    ],

形としては想定通りなのですが、設定されている値が両方とも2回目のループ時のデータになってしまいます。期待値としては以下なのですが、このようにデータが入らない理由が分からずにおります。
原因、対処法についてご教示頂けないでしょうか。

  "_source": {
    "TargetInstanceId": [
      {
        "instanceId": "i-1a2b3c4d",
        "name": "shutting-down"
      },
      {
        "instanceId": "i-2a2b3c4d",
        "name": "shutting-down2"
      }
    ],

hash = {} の初期化の場所がよろしくないのではと思います。

filterのrubyの個所だけですが、以下のように修正すれば期待通りに動きそうです。

ruby {
    code => "
    instanceId_tmp = []
    name_tmp = []
    TargetInstanceIdtmp= []
    # hash = {}
    if !event.get('[Records][responseElements][instancesSet][items]').nil? then
        for field in event.get('[Records][responseElements][instancesSet][items]') do
             hash = {} # here!!!!!!!!!!!!!!!!!!!!!!!!!!
             hash['instanceId'] = field['instanceId']
             hash['name'] = field['currentState']['name']
             TargetInstanceIdtmp.push(hash)
        end
        event.set('TargetInstanceId', TargetInstanceIdtmp)
   end
   "
  }

実行時の結果がこちら。

    "TargetInstanceId" => [
        [0] {
                  "name" => "shutting-down",
            "instanceId" => "i-1a2b3c4d"
        },
        [1] {
                  "name" => "shutting-down2",
            "instanceId" => "i-2a2b3c4d"
        }
    ],

ご指摘の個所を修正したら期待通りの動作になりました。ありがとうございました

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.