フィールド抽出

フィールド抽出の目的はシンプルです。データ内に多くの情報を含むフィールドがありますが、必要な部分だけを抽出したいのです。

利用可能なオプションは2つあります:

  • Grokは、再利用可能なエイリアス式をサポートする正規表現の方言です。Grokは正規表現(regex)の上に位置しているため、通常の正規表現もgrokで有効です。
  • Dissectは、区切り文字を使用して一致パターンを定義し、テキストから構造化されたフィールドを抽出します。grokとは異なり、dissectは正規表現を使用しません。
  1. #### Python
  2. ``````python
  3. resp = client.indices.create(
  4. index="my-index",
  5. mappings={
  6. "properties": {
  7. "@timestamp": {
  8. "format": "strict_date_optional_time||epoch_second",
  9. "type": "date"
  10. },
  11. "message": {
  12. "type": "wildcard"
  13. }
  14. }
  15. },
  16. )
  17. print(resp)
  18. `

Ruby

  1. response = client.indices.create(
  2. index: 'my-index',
  3. body: {
  4. mappings: {
  5. properties: {
  6. "@timestamp": {
  7. format: 'strict_date_optional_time||epoch_second',
  8. type: 'date'
  9. },
  10. message: {
  11. type: 'wildcard'
  12. }
  13. }
  14. }
  15. }
  16. )
  17. puts response

Js

  1. const response = await client.indices.create({
  2. index: "my-index",
  3. mappings: {
  4. properties: {
  5. "@timestamp": {
  6. format: "strict_date_optional_time||epoch_second",
  7. type: "date",
  8. },
  9. message: {
  10. type: "wildcard",
  11. },
  12. },
  13. },
  14. });
  15. console.log(response);

コンソール

  1. PUT /my-index/
  2. {
  3. "mappings": {
  4. "properties": {
  5. "@timestamp": {
  6. "format": "strict_date_optional_time||epoch_second",
  7. "type": "date"
  8. },
  9. "message": {
  10. "type": "wildcard"
  11. }
  12. }
  13. }
  14. }

フィールドをマッピングした後、ログデータからいくつかのレコードをElasticsearchにインデックスします。次のリクエストは、bulk APIを使用して、生のログデータをmy-indexにインデックスします。すべてのログデータをインデックスする代わりに、小さなサンプルを使用してランタイムフィールドを試すことができます。

Python

  1. resp = client.bulk(
  2. index="my-index",
  3. refresh=True,
  4. operations=[
  5. {
  6. "index": {}
  7. },
  8. {
  9. "timestamp": "2020-04-30T14:30:17-05:00",
  10. "message": "40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
  11. },
  12. {
  13. "index": {}
  14. },
  15. {
  16. "timestamp": "2020-04-30T14:30:53-05:00",
  17. "message": "232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
  18. },
  19. {
  20. "index": {}
  21. },
  22. {
  23. "timestamp": "2020-04-30T14:31:12-05:00",
  24. "message": "26.1.0.0 - - [30/Apr/2020:14:31:12 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
  25. },
  26. {
  27. "index": {}
  28. },
  29. {
  30. "timestamp": "2020-04-30T14:31:19-05:00",
  31. "message": "247.37.0.0 - - [30/Apr/2020:14:31:19 -0500] \"GET /french/splash_inet.html HTTP/1.0\" 200 3781"
  32. },
  33. {
  34. "index": {}
  35. },
  36. {
  37. "timestamp": "2020-04-30T14:31:22-05:00",
  38. "message": "247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"
  39. },
  40. {
  41. "index": {}
  42. },
  43. {
  44. "timestamp": "2020-04-30T14:31:27-05:00",
  45. "message": "252.0.0.0 - - [30/Apr/2020:14:31:27 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
  46. },
  47. {
  48. "index": {}
  49. },
  50. {
  51. "timestamp": "2020-04-30T14:31:28-05:00",
  52. "message": "not a valid apache log"
  53. }
  54. ],
  55. )
  56. print(resp)

Ruby

  1. response = client.bulk(
  2. index: 'my-index',
  3. refresh: true,
  4. body: [
  5. {
  6. index: {}
  7. },
  8. {
  9. timestamp: '2020-04-30T14:30:17-05:00',
  10. message: '40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
  11. },
  12. {
  13. index: {}
  14. },
  15. {
  16. timestamp: '2020-04-30T14:30:53-05:00',
  17. message: '232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
  18. },
  19. {
  20. index: {}
  21. },
  22. {
  23. timestamp: '2020-04-30T14:31:12-05:00',
  24. message: '26.1.0.0 - - [30/Apr/2020:14:31:12 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
  25. },
  26. {
  27. index: {}
  28. },
  29. {
  30. timestamp: '2020-04-30T14:31:19-05:00',
  31. message: '247.37.0.0 - - [30/Apr/2020:14:31:19 -0500] "GET /french/splash_inet.html HTTP/1.0" 200 3781'
  32. },
  33. {
  34. index: {}
  35. },
  36. {
  37. timestamp: '2020-04-30T14:31:22-05:00',
  38. message: '247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] "GET /images/hm_nbg.jpg HTTP/1.0" 304 0'
  39. },
  40. {
  41. index: {}
  42. },
  43. {
  44. timestamp: '2020-04-30T14:31:27-05:00',
  45. message: '252.0.0.0 - - [30/Apr/2020:14:31:27 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736'
  46. },
  47. {
  48. index: {}
  49. },
  50. {
  51. timestamp: '2020-04-30T14:31:28-05:00',
  52. message: 'not a valid apache log'
  53. }
  54. ]
  55. )
  56. puts response

Js

  1. const response = await client.bulk({
  2. index: "my-index",
  3. refresh: "true",
  4. operations: [
  5. {
  6. index: {},
  7. },
  8. {
  9. timestamp: "2020-04-30T14:30:17-05:00",
  10. message:
  11. '40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
  12. },
  13. {
  14. index: {},
  15. },
  16. {
  17. timestamp: "2020-04-30T14:30:53-05:00",
  18. message:
  19. '232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
  20. },
  21. {
  22. index: {},
  23. },
  24. {
  25. timestamp: "2020-04-30T14:31:12-05:00",
  26. message:
  27. '26.1.0.0 - - [30/Apr/2020:14:31:12 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
  28. },
  29. {
  30. index: {},
  31. },
  32. {
  33. timestamp: "2020-04-30T14:31:19-05:00",
  34. message:
  35. '247.37.0.0 - - [30/Apr/2020:14:31:19 -0500] "GET /french/splash_inet.html HTTP/1.0" 200 3781',
  36. },
  37. {
  38. index: {},
  39. },
  40. {
  41. timestamp: "2020-04-30T14:31:22-05:00",
  42. message:
  43. '247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] "GET /images/hm_nbg.jpg HTTP/1.0" 304 0',
  44. },
  45. {
  46. index: {},
  47. },
  48. {
  49. timestamp: "2020-04-30T14:31:27-05:00",
  50. message:
  51. '252.0.0.0 - - [30/Apr/2020:14:31:27 -0500] "GET /images/hm_bg.jpg HTTP/1.0" 200 24736',
  52. },
  53. {
  54. index: {},
  55. },
  56. {
  57. timestamp: "2020-04-30T14:31:28-05:00",
  58. message: "not a valid apache log",
  59. },
  60. ],
  61. });
  62. console.log(response);

コンソール

  1. POST /my-index/_bulk?refresh
  2. {"index":{}}
  3. {"timestamp":"2020-04-30T14:30:17-05:00","message":"40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
  4. {"index":{}}
  5. {"timestamp":"2020-04-30T14:30:53-05:00","message":"232.0.0.0 - - [30/Apr/2020:14:30:53 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
  6. {"index":{}}
  7. {"timestamp":"2020-04-30T14:31:12-05:00","message":"26.1.0.0 - - [30/Apr/2020:14:31:12 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
  8. {"index":{}}
  9. {"timestamp":"2020-04-30T14:31:19-05:00","message":"247.37.0.0 - - [30/Apr/2020:14:31:19 -0500] \"GET /french/splash_inet.html HTTP/1.0\" 200 3781"}
  10. {"index":{}}
  11. {"timestamp":"2020-04-30T14:31:22-05:00","message":"247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"}
  12. {"index":{}}
  13. {"timestamp":"2020-04-30T14:31:27-05:00","message":"252.0.0.0 - - [30/Apr/2020:14:31:27 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"}
  14. {"index":{}}
  15. {"timestamp":"2020-04-30T14:31:28-05:00","message":"not a valid apache log"}

ログメッセージからIPアドレスを抽出する(Grok)

  1. スクリプトは、Apacheログの構造を理解する`````%{COMMONAPACHELOG}`````ログパターンに一致します。パターンが一致する場合(`````clientip != null`````)、スクリプトは一致したIPアドレスの値を出力します。パターンが一致しない場合、スクリプトはクラッシュせずにフィールド値をそのまま返します。
  2. #### Python
  3. ``````python
  4. resp = client.indices.put_mapping(
  5. index="my-index",
  6. runtime={
  7. "http.clientip": {
  8. "type": "ip",
  9. "script": "\n String clientip=grok('%{COMMONAPACHELOG}').extract(doc[\"message\"].value)?.clientip;\n if (clientip != null) emit(clientip); \n "
  10. }
  11. },
  12. )
  13. print(resp)
  14. `

Js

  1. const response = await client.indices.putMapping({
  2. index: "my-index",
  3. runtime: {
  4. "http.clientip": {
  5. type: "ip",
  6. script:
  7. "\n String clientip=grok('%{COMMONAPACHELOG}').extract(doc[\"message\"].value)?.clientip;\n if (clientip != null) emit(clientip); \n ",
  8. },
  9. },
  10. });
  11. console.log(response);

コンソール

  1. PUT my-index/_mappings
  2. {
  3. "runtime": {
  4. "http.clientip": {
  5. "type": "ip",
  6. "script": """
  7. String clientip=grok('%{COMMONAPACHELOG}').extract(doc["message"].value)?.clientip;
  8. if (clientip != null) emit(clientip);
  9. """
  10. }
  11. }
  12. }
この条件は、メッセージのパターンが一致しなくてもスクリプトが何も出力しないことを保証します。

特定のIPアドレスを検索するための簡単なクエリを定義し、関連するすべてのフィールドを返すことができます。検索APIのfieldsパラメータを使用して、http.clientipランタイムフィールドを取得します。

Python

  1. resp = client.search(
  2. index="my-index",
  3. query={
  4. "match": {
  5. "http.clientip": "40.135.0.0"
  6. }
  7. },
  8. fields=[
  9. "http.clientip"
  10. ],
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index',
  3. body: {
  4. query: {
  5. match: {
  6. 'http.clientip' => '40.135.0.0'
  7. }
  8. },
  9. fields: [
  10. 'http.clientip'
  11. ]
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.search({
  2. index: "my-index",
  3. query: {
  4. match: {
  5. "http.clientip": "40.135.0.0",
  6. },
  7. },
  8. fields: ["http.clientip"],
  9. });
  10. console.log(response);

コンソール

  1. GET my-index/_search
  2. {
  3. "query": {
  4. "match": {
  5. "http.clientip": "40.135.0.0"
  6. }
  7. },
  8. "fields" : ["http.clientip"]
  9. }
  1. [](#13f015769493c2dc4e56ea54945b1975)
  2. #### コンソール-結果
  3. ``````console-result
  4. {
  5. "hits" : {
  6. "total" : {
  7. "value" : 1,
  8. "relation" : "eq"
  9. },
  10. "max_score" : 1.0,
  11. "hits" : [
  12. {
  13. "_index" : "my-index",
  14. "_id" : "Rq-ex3gBA_A0V6dYGLQ7",
  15. "_score" : 1.0,
  16. "_source" : {
  17. "timestamp" : "2020-04-30T14:30:17-05:00",
  18. "message" : "40.135.0.0 - - [30/Apr/2020:14:30:17 -0500] \"GET /images/hm_bg.jpg HTTP/1.0\" 200 24736"
  19. },
  20. "fields" : {
  21. "http.clientip" : [
  22. "40.135.0.0"
  23. ]
  24. }
  25. }
  26. ]
  27. }
  28. }
  29. `

文字列を解析してフィールドの一部を抽出する(Dissect)

前の例のようにログパターンに一致させるのではなく、単に捨てたい文字列の部分を含むdissectパターンを定義できます。

たとえば、このセクションの最初にあるログデータにはmessageフィールドが含まれています。このフィールドには、いくつかのデータが含まれています:

Js

  1. "message" : "247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"

ランタイムフィールドでdissectパターンを定義して、前の例の304であるHTTPレスポンスコードを抽出できます。

Python

  1. resp = client.indices.put_mapping(
  2. index="my-index",
  3. runtime={
  4. "http.response": {
  5. "type": "long",
  6. "script": "\n String response=dissect('%{clientip} %{ident} %{auth} [%{@timestamp}] \"%{verb} %{request} HTTP/%{httpversion}\" %{response} %{size}').extract(doc[\"message\"].value)?.response;\n if (response != null) emit(Integer.parseInt(response));\n "
  7. }
  8. },
  9. )
  10. print(resp)

Js

  1. const response = await client.indices.putMapping({
  2. index: "my-index",
  3. runtime: {
  4. "http.response": {
  5. type: "long",
  6. script:
  7. '\n String response=dissect(\'%{clientip} %{ident} %{auth} [%{@timestamp}] "%{verb} %{request} HTTP/%{httpversion}" %{response} %{size}\').extract(doc["message"].value)?.response;\n if (response != null) emit(Integer.parseInt(response));\n ',
  8. },
  9. },
  10. });
  11. console.log(response);

コンソール

  1. PUT my-index/_mappings
  2. {
  3. "runtime": {
  4. "http.response": {
  5. "type": "long",
  6. "script": """
  7. String response=dissect('%{clientip} %{ident} %{auth} [%{@timestamp}] "%{verb} %{request} HTTP/%{httpversion}" %{response} %{size}').extract(doc["message"].value)?.response;
  8. if (response != null) emit(Integer.parseInt(response));
  9. """
  10. }
  11. }
  12. }

次に、http.responseランタイムフィールドを使用して特定のHTTPレスポンスを取得するクエリを実行できます:

Python

  1. resp = client.search(
  2. index="my-index",
  3. query={
  4. "match": {
  5. "http.response": "304"
  6. }
  7. },
  8. fields=[
  9. "http.response"
  10. ],
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index',
  3. body: {
  4. query: {
  5. match: {
  6. 'http.response' => '304'
  7. }
  8. },
  9. fields: [
  10. 'http.response'
  11. ]
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.search({
  2. index: "my-index",
  3. query: {
  4. match: {
  5. "http.response": "304",
  6. },
  7. },
  8. fields: ["http.response"],
  9. });
  10. console.log(response);

コンソール

  1. GET my-index/_search
  2. {
  3. "query": {
  4. "match": {
  5. "http.response": "304"
  6. }
  7. },
  8. "fields" : ["http.response"]
  9. }

レスポンスには、HTTPレスポンスが304である単一のドキュメントが含まれています:

コンソール-結果

  1. {
  2. "hits" : {
  3. "total" : {
  4. "value" : 1,
  5. "relation" : "eq"
  6. },
  7. "max_score" : 1.0,
  8. "hits" : [
  9. {
  10. "_index" : "my-index",
  11. "_id" : "Sq-ex3gBA_A0V6dYGLQ7",
  12. "_score" : 1.0,
  13. "_source" : {
  14. "timestamp" : "2020-04-30T14:31:22-05:00",
  15. "message" : "247.37.0.0 - - [30/Apr/2020:14:31:22 -0500] \"GET /images/hm_nbg.jpg HTTP/1.0\" 304 0"
  16. },
  17. "fields" : {
  18. "http.response" : [
  19. 304
  20. ]
  21. }
  22. }
  23. ]
  24. }
  25. }

区切り文字でフィールド内の値を分割する(Dissect)

前の例のようにフィールドの一部を抽出したいが、特定の値で分割したいとします。dissectパターンを使用して、必要な情報のみを抽出し、そのデータを特定の形式で返すことができます。

たとえば、Elasticsearchからのガーベジコレクション(gc)ログデータがこの形式であるとします:

Txt

  1. [2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K
  1. #### Python
  2. ``````python
  3. resp = client.bulk(
  4. index="my-index",
  5. refresh=True,
  6. operations=[
  7. {
  8. "index": {}
  9. },
  10. {
  11. "gc": "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K"
  12. },
  13. {
  14. "index": {}
  15. },
  16. {
  17. "gc": "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] class space used 15255K, capacity 16726K, committed 16844K, reserved 1048576K"
  18. },
  19. {
  20. "index": {}
  21. },
  22. {
  23. "gc": "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] Metaspace used 115409K, capacity 119541K, committed 120248K, reserved 1153024K"
  24. },
  25. {
  26. "index": {}
  27. },
  28. {
  29. "gc": "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] class space used 14503K, capacity 15894K, committed 15948K, reserved 1048576K"
  30. },
  31. {
  32. "index": {}
  33. },
  34. {
  35. "gc": "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] Metaspace used 107719K, capacity 111775K, committed 112724K, reserved 1146880K"
  36. },
  37. {
  38. "index": {}
  39. },
  40. {
  41. "gc": "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 367K, committed 384K, reserved 1048576K"
  42. }
  43. ],
  44. )
  45. print(resp)
  46. `

Ruby

  1. response = client.bulk(
  2. index: 'my-index',
  3. refresh: true,
  4. body: [
  5. {
  6. index: {}
  7. },
  8. {
  9. gc: '[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K'
  10. },
  11. {
  12. index: {}
  13. },
  14. {
  15. gc: '[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] class space used 15255K, capacity 16726K, committed 16844K, reserved 1048576K'
  16. },
  17. {
  18. index: {}
  19. },
  20. {
  21. gc: '[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] Metaspace used 115409K, capacity 119541K, committed 120248K, reserved 1153024K'
  22. },
  23. {
  24. index: {}
  25. },
  26. {
  27. gc: '[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] class space used 14503K, capacity 15894K, committed 15948K, reserved 1048576K'
  28. },
  29. {
  30. index: {}
  31. },
  32. {
  33. gc: '[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] Metaspace used 107719K, capacity 111775K, committed 112724K, reserved 1146880K'
  34. },
  35. {
  36. index: {}
  37. },
  38. {
  39. gc: '[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 367K, committed 384K, reserved 1048576K'
  40. }
  41. ]
  42. )
  43. puts response

Js

  1. const response = await client.bulk({
  2. index: "my-index",
  3. refresh: "true",
  4. operations: [
  5. {
  6. index: {},
  7. },
  8. {
  9. gc: "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K",
  10. },
  11. {
  12. index: {},
  13. },
  14. {
  15. gc: "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] class space used 15255K, capacity 16726K, committed 16844K, reserved 1048576K",
  16. },
  17. {
  18. index: {},
  19. },
  20. {
  21. gc: "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] Metaspace used 115409K, capacity 119541K, committed 120248K, reserved 1153024K",
  22. },
  23. {
  24. index: {},
  25. },
  26. {
  27. gc: "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] class space used 14503K, capacity 15894K, committed 15948K, reserved 1048576K",
  28. },
  29. {
  30. index: {},
  31. },
  32. {
  33. gc: "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] Metaspace used 107719K, capacity 111775K, committed 112724K, reserved 1146880K",
  34. },
  35. {
  36. index: {},
  37. },
  38. {
  39. gc: "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 367K, committed 384K, reserved 1048576K",
  40. },
  41. ],
  42. });
  43. console.log(response);

コンソール

  1. POST /my-index/_bulk?refresh
  2. {"index":{}}
  3. {"gc": "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K"}
  4. {"index":{}}
  5. {"gc": "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] class space used 15255K, capacity 16726K, committed 16844K, reserved 1048576K"}
  6. {"index":{}}
  7. {"gc": "[2021-03-24T20:27:24.184+0000][90239][gc,heap,exit] Metaspace used 115409K, capacity 119541K, committed 120248K, reserved 1153024K"}
  8. {"index":{}}
  9. {"gc": "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] class space used 14503K, capacity 15894K, committed 15948K, reserved 1048576K"}
  10. {"index":{}}
  11. {"gc": "[2021-04-19T15:03:21.735+0000][84408][gc,heap,exit] Metaspace used 107719K, capacity 111775K, committed 112724K, reserved 1146880K"}
  12. {"index":{}}
  13. {"gc": "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 367K, committed 384K, reserved 1048576K"}

データを再度見ると、タイムスタンプ、興味のない他のデータ、そしてusedcapacitycommittedデータがあります:

Txt

  1. [2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K
  1. #### Txt
  2. ``````txt
  3. [%{@timestamp}][%{code}][%{desc}] %{ident} used %{usize}, capacity %{csize}, committed %{comsize}, reserved %{rsize}
  4. `

dissectパターンには、変数を使用する代わりにusedcapacitycommittedの用語を含めることができます。なぜなら、正確にそれらの用語を返したいからです。また、%{usize}%{csize}%{comsize}など、返したい値に変数を割り当てます。ログデータの区切り文字はカンマなので、dissectパターンでもその区切り文字を使用する必要があります。

dissectパターンができたので、ランタイムフィールドの一部としてPainlessスクリプトに含めることができます。スクリプトは、gcフィールドを分割するためにdissectパターンを使用し、emitメソッドで定義された通りに、正確に必要な情報を返します。dissectはシンプルな構文を使用するため、必要なものを正確に指示するだけで済みます。

次のパターンは、dissectにusedの用語、空白、gc.usizeの値、およびカンマを返すように指示します。このパターンは、取得したい他のデータに対しても繰り返されます。このパターンは本番環境ではあまり役立たないかもしれませんが、データを操作したり実験したりするための柔軟性を提供します。本番環境では、emit(gc.usize)を使用して、その値を集約したり計算に使用したりすることが望ましいかもしれません。

Painless

  1. emit("used" + ' ' + gc.usize + ', ' + "capacity" + ' ' + gc.csize + ', ' + "committed" + ' ' + gc.comsize)

すべてをまとめると、検索リクエストでgc_sizeという名前のランタイムフィールドを作成できます。fieldsオプションを使用して、gc_sizeランタイムフィールドのすべての値を取得できます。このクエリには、データをグループ化するためのバケット集約も含まれています。

Python

  1. resp = client.search(
  2. index="my-index",
  3. runtime_mappings={
  4. "gc_size": {
  5. "type": "keyword",
  6. "script": "\n Map gc=dissect('[%{@timestamp}][%{code}][%{desc}] %{ident} used %{usize}, capacity %{csize}, committed %{comsize}, reserved %{rsize}').extract(doc[\"gc.keyword\"].value);\n if (gc != null) emit(\"used\" + ' ' + gc.usize + ', ' + \"capacity\" + ' ' + gc.csize + ', ' + \"committed\" + ' ' + gc.comsize);\n "
  7. }
  8. },
  9. size=1,
  10. aggs={
  11. "sizes": {
  12. "terms": {
  13. "field": "gc_size",
  14. "size": 10
  15. }
  16. }
  17. },
  18. fields=[
  19. "gc_size"
  20. ],
  21. )
  22. print(resp)

Js

  1. const response = await client.search({
  2. index: "my-index",
  3. runtime_mappings: {
  4. gc_size: {
  5. type: "keyword",
  6. script:
  7. "\n Map gc=dissect('[%{@timestamp}][%{code}][%{desc}] %{ident} used %{usize}, capacity %{csize}, committed %{comsize}, reserved %{rsize}').extract(doc[\"gc.keyword\"].value);\n if (gc != null) emit(\"used\" + ' ' + gc.usize + ', ' + \"capacity\" + ' ' + gc.csize + ', ' + \"committed\" + ' ' + gc.comsize);\n ",
  8. },
  9. },
  10. size: 1,
  11. aggs: {
  12. sizes: {
  13. terms: {
  14. field: "gc_size",
  15. size: 10,
  16. },
  17. },
  18. },
  19. fields: ["gc_size"],
  20. });
  21. console.log(response);

コンソール

  1. GET my-index/_search
  2. {
  3. "runtime_mappings": {
  4. "gc_size": {
  5. "type": "keyword",
  6. "script": """
  7. Map gc=dissect('[%{@timestamp}][%{code}][%{desc}] %{ident} used %{usize}, capacity %{csize}, committed %{comsize}, reserved %{rsize}').extract(doc["gc.keyword"].value);
  8. if (gc != null) emit("used" + ' ' + gc.usize + ', ' + "capacity" + ' ' + gc.csize + ', ' + "committed" + ' ' + gc.comsize);
  9. """
  10. }
  11. },
  12. "size": 1,
  13. "aggs": {
  14. "sizes": {
  15. "terms": {
  16. "field": "gc_size",
  17. "size": 10
  18. }
  19. }
  20. },
  21. "fields" : ["gc_size"]
  22. }

レスポンスには、dissectパターンで定義した通りにフォーマットされたgc_sizeフィールドのデータが含まれています!

コンソール-結果

  1. {
  2. "took" : 2,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 6,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 1.0,
  16. "hits" : [
  17. {
  18. "_index" : "my-index",
  19. "_id" : "GXx3H3kBKGE42WRNlddJ",
  20. "_score" : 1.0,
  21. "_source" : {
  22. "gc" : "[2021-04-27T16:16:34.699+0000][82460][gc,heap,exit] class space used 266K, capacity 384K, committed 384K, reserved 1048576K"
  23. },
  24. "fields" : {
  25. "gc_size" : [
  26. "used 266K, capacity 384K, committed 384K"
  27. ]
  28. }
  29. }
  30. ]
  31. },
  32. "aggregations" : {
  33. "sizes" : {
  34. "doc_count_error_upper_bound" : 0,
  35. "sum_other_doc_count" : 0,
  36. "buckets" : [
  37. {
  38. "key" : "used 107719K, capacity 111775K, committed 112724K",
  39. "doc_count" : 1
  40. },
  41. {
  42. "key" : "used 115409K, capacity 119541K, committed 120248K",
  43. "doc_count" : 1
  44. },
  45. {
  46. "key" : "used 14503K, capacity 15894K, committed 15948K",
  47. "doc_count" : 1
  48. },
  49. {
  50. "key" : "used 15255K, capacity 16726K, committed 16844K",
  51. "doc_count" : 1
  52. },
  53. {
  54. "key" : "used 266K, capacity 367K, committed 384K",
  55. "doc_count" : 1
  56. },
  57. {
  58. "key" : "used 266K, capacity 384K, committed 384K",
  59. "doc_count" : 1
  60. }
  61. ]
  62. }
  63. }
  64. }