logstash-filter-opensearch-manticore 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +2 -0
- data/CONTRIBUTORS +17 -0
- data/Gemfile +11 -0
- data/LICENSE +202 -0
- data/NOTICE.TXT +5 -0
- data/README.md +98 -0
- data/docs/index.asciidoc +336 -0
- data/lib/logstash/filters/opensearch/patches/_opensearch_transport_connections_selector.rb +52 -0
- data/lib/logstash/filters/opensearch/patches/_opensearch_transport_http_manticore.rb +44 -0
- data/lib/logstash/filters/opensearch.rb +281 -0
- data/logstash-filter-opensearch-manticore.gemspec +29 -0
- data/spec/filters/fixtures/opensearch_7.x_hits_total_as_object.json +70 -0
- data/spec/filters/fixtures/query_template.json +7 -0
- data/spec/filters/fixtures/query_template_unicode.json +7 -0
- data/spec/filters/fixtures/request_error.json +25 -0
- data/spec/filters/fixtures/request_size0_agg.json +19 -0
- data/spec/filters/fixtures/request_x_1.json +67 -0
- data/spec/filters/fixtures/request_x_10.json +500 -0
- data/spec/filters/integration/opensearch_spec.rb +61 -0
- data/spec/filters/opensearch_spec.rb +431 -0
- data/spec/opensearch_helper.rb +43 -0
- metadata +139 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
# Copyright OpenSearch Contributors
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
|
4
|
+
require 'opensearch'
|
5
|
+
require 'opensearch/transport/transport/connections/selector'
|
6
|
+
|
7
|
+
# elasticsearch-transport versions prior to 7.2.0 suffered of a race condition on accessing
|
8
|
+
# the connection pool. This issue was fixed (in 7.2.0) with
|
9
|
+
# https://github.com/elastic/elasticsearch-ruby/commit/15f9d78591a6e8823948494d94b15b0ca38819d1
|
10
|
+
#
|
11
|
+
# This plugin, at the moment, is using elasticsearch >= 5.0.5
|
12
|
+
# When this requirement ceases, this patch could be removed.
|
13
|
+
module OpenSearch
|
14
|
+
module Transport
|
15
|
+
module Transport
|
16
|
+
module Connections
|
17
|
+
module Selector
|
18
|
+
|
19
|
+
# "Round-robin" selector strategy (default).
|
20
|
+
#
|
21
|
+
class RoundRobin
|
22
|
+
include Base
|
23
|
+
|
24
|
+
# @option arguments [Connections::Collection] :connections Collection with connections.
|
25
|
+
#
|
26
|
+
def initialize(arguments = {})
|
27
|
+
super
|
28
|
+
@mutex = Mutex.new
|
29
|
+
@current = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the next connection from the collection, rotating them in round-robin fashion.
|
33
|
+
#
|
34
|
+
# @return [Connections::Connection]
|
35
|
+
#
|
36
|
+
def select(options={})
|
37
|
+
@mutex.synchronize do
|
38
|
+
conns = connections
|
39
|
+
if @current && (@current < conns.size-1)
|
40
|
+
@current += 1
|
41
|
+
else
|
42
|
+
@current = 0
|
43
|
+
end
|
44
|
+
conns[@current]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright OpenSearch Contributors
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
|
4
|
+
# encoding: utf-8
|
5
|
+
require "opensearch"
|
6
|
+
require "opensearch/transport/transport/http/manticore"
|
7
|
+
|
8
|
+
|
9
|
+
# elasticsearch-transport 7.2.0 - 7.14.0 had a bug where setting http headers
|
10
|
+
# ES::Client.new ..., transport_options: { headers: { 'Authorization' => ... } }
|
11
|
+
# would be lost https://github.com/elastic/elasticsearch-ruby/issues/1428
|
12
|
+
#
|
13
|
+
# NOTE: needs to be idempotent as filter OpenSearch plugin might apply the same patch!
|
14
|
+
#
|
15
|
+
# @private
|
16
|
+
module OpenSearch
|
17
|
+
module Transport
|
18
|
+
module Transport
|
19
|
+
module HTTP
|
20
|
+
class Manticore
|
21
|
+
|
22
|
+
def apply_headers(request_options, options)
|
23
|
+
headers = (options && options[:headers]) || {}
|
24
|
+
headers[CONTENT_TYPE_STR] = find_value(headers, CONTENT_TYPE_REGEX) || DEFAULT_CONTENT_TYPE
|
25
|
+
|
26
|
+
# this code is necessary to grab the correct user-agent header
|
27
|
+
# when this method is invoked with apply_headers(@request_options, options)
|
28
|
+
# from https://github.com/opensearch-project/opensearch-ruby/blob/main/opensearch-transport/lib/opensearch/transport/transport/http/manticore.rb#L122-L123
|
29
|
+
transport_user_agent = nil
|
30
|
+
if (options && options[:transport_options] && options[:transport_options][:headers])
|
31
|
+
transport_headers = options[:transport_options][:headers]
|
32
|
+
transport_user_agent = find_value(transport_headers, USER_AGENT_REGEX)
|
33
|
+
end
|
34
|
+
|
35
|
+
headers[USER_AGENT_STR] = transport_user_agent || find_value(headers, USER_AGENT_REGEX) || user_agent_header
|
36
|
+
headers[ACCEPT_ENCODING] = GZIP if use_compression?
|
37
|
+
(request_options[:headers] ||= {}).merge!(headers) # this line was changed
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,281 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/filters/base"
|
3
|
+
require "logstash/namespace"
|
4
|
+
require "logstash/json"
|
5
|
+
require "logstash/util/safe_uri"
|
6
|
+
java_import "java.util.concurrent.ConcurrentHashMap"
|
7
|
+
require "opensearch"
|
8
|
+
require "opensearch/transport/transport/http/manticore"
|
9
|
+
require_relative "opensearch/patches/_opensearch_transport_http_manticore"
|
10
|
+
require_relative "opensearch/patches/_opensearch_transport_connections_selector"
|
11
|
+
|
12
|
+
|
13
|
+
class LogStash::Filters::OpenSearch < LogStash::Filters::Base
|
14
|
+
config_name "opensearch"
|
15
|
+
|
16
|
+
DEFAULT_HOST = ::LogStash::Util::SafeURI.new("//localhost:9200")
|
17
|
+
|
18
|
+
# List of opensearch hosts to use for querying.
|
19
|
+
config :hosts, :validate => :array, :default => [ DEFAULT_HOST ]
|
20
|
+
|
21
|
+
# Comma-delimited list of index names to search; use `_all` or empty string to perform the operation on all indices.
|
22
|
+
# Field substitution (e.g. `index-name-%{date_field}`) is available
|
23
|
+
config :index, :validate => :string, :default => ""
|
24
|
+
|
25
|
+
# OpenSearch query string. Read the OpenSearch query string documentation.
|
26
|
+
# for more info at: https://www.elastic.co/guide/en/opensearch/reference/master/query-dsl-query-string-query.html#query-string-syntax
|
27
|
+
config :query, :validate => :string
|
28
|
+
|
29
|
+
# File path to opensearch query in DSL format. Read the OpenSearch query documentation
|
30
|
+
# for more info at: https://www.elastic.co/guide/en/opensearch/reference/current/query-dsl.html
|
31
|
+
config :query_template, :validate => :string
|
32
|
+
|
33
|
+
# Comma-delimited list of `<field>:<direction>` pairs that define the sort order
|
34
|
+
config :sort, :validate => :string, :default => "@timestamp:desc"
|
35
|
+
|
36
|
+
# Array of fields to copy from old event (found via opensearch) into new event
|
37
|
+
config :fields, :validate => :array, :default => {}
|
38
|
+
|
39
|
+
# Hash of docinfo fields to copy from old event (found via opensearch) into new event
|
40
|
+
config :docinfo_fields, :validate => :hash, :default => {}
|
41
|
+
|
42
|
+
# Hash of aggregation names to copy from opensearch response into Logstash event fields
|
43
|
+
config :aggregation_fields, :validate => :hash, :default => {}
|
44
|
+
|
45
|
+
# Basic Auth - username
|
46
|
+
config :user, :validate => :string
|
47
|
+
|
48
|
+
# Basic Auth - password
|
49
|
+
config :password, :validate => :password
|
50
|
+
|
51
|
+
# Cloud ID, from the Elastic Cloud web console. If set `hosts` should not be used.
|
52
|
+
#
|
53
|
+
# For more info, check out the https://www.elastic.co/guide/en/logstash/current/connecting-to-cloud.html#_cloud_id[Logstash-to-Cloud documentation]
|
54
|
+
config :cloud_id, :validate => :string
|
55
|
+
|
56
|
+
# Cloud authentication string ("<username>:<password>" format) is an alternative for the `user`/`password` configuration.
|
57
|
+
#
|
58
|
+
# For more info, check out the https://www.elastic.co/guide/en/logstash/current/connecting-to-cloud.html#_cloud_auth[Logstash-to-Cloud documentation]
|
59
|
+
config :cloud_auth, :validate => :password
|
60
|
+
|
61
|
+
# Authenticate using OpenSearch API key.
|
62
|
+
# format is id:api_key (as returned by https://www.elastic.co/guide/en/opensearch/reference/current/security-api-create-api-key.html[Create API key])
|
63
|
+
config :api_key, :validate => :password
|
64
|
+
|
65
|
+
# SSL
|
66
|
+
config :ssl, :validate => :boolean, :default => false
|
67
|
+
|
68
|
+
# SSL Certificate Authority file
|
69
|
+
config :ca_file, :validate => :path
|
70
|
+
|
71
|
+
# Whether results should be sorted or not
|
72
|
+
config :enable_sort, :validate => :boolean, :default => true
|
73
|
+
|
74
|
+
# How many results to return
|
75
|
+
config :result_size, :validate => :number, :default => 1
|
76
|
+
|
77
|
+
# Tags the event on failure to look up geo information. This can be used in later analysis.
|
78
|
+
config :tag_on_failure, :validate => :array, :default => ["_opensearch_lookup_failure"]
|
79
|
+
|
80
|
+
attr_reader :clients_pool
|
81
|
+
|
82
|
+
def register
|
83
|
+
@clients_pool = java.util.concurrent.ConcurrentHashMap.new
|
84
|
+
|
85
|
+
#Load query if it exists
|
86
|
+
if @query_template
|
87
|
+
if File.zero?(@query_template)
|
88
|
+
raise "template is empty"
|
89
|
+
end
|
90
|
+
file = File.open(@query_template, 'r')
|
91
|
+
@query_dsl = file.read
|
92
|
+
end
|
93
|
+
|
94
|
+
validate_authentication
|
95
|
+
|
96
|
+
@transport_options = {:headers => {}}
|
97
|
+
@transport_options[:headers].merge!(setup_basic_auth(user, password))
|
98
|
+
@transport_options[:headers].merge!({'user-agent' => prepare_user_agent })
|
99
|
+
@transport_options[:request_timeout] = @request_timeout_seconds unless @request_timeout_seconds.nil?
|
100
|
+
@transport_options[:connect_timeout] = @connect_timeout_seconds unless @connect_timeout_seconds.nil?
|
101
|
+
@transport_options[:socket_timeout] = @socket_timeout_seconds unless @socket_timeout_seconds.nil?
|
102
|
+
|
103
|
+
@hosts = setup_hosts
|
104
|
+
@ssl_options = setup_ssl
|
105
|
+
|
106
|
+
test_connection!
|
107
|
+
end # def register
|
108
|
+
|
109
|
+
def filter(event)
|
110
|
+
matched = false
|
111
|
+
begin
|
112
|
+
params = {:index => event.sprintf(@index) }
|
113
|
+
|
114
|
+
if @query_dsl
|
115
|
+
query = LogStash::Json.load(event.sprintf(@query_dsl))
|
116
|
+
params[:body] = query
|
117
|
+
else
|
118
|
+
query = event.sprintf(@query)
|
119
|
+
params[:q] = query
|
120
|
+
params[:size] = result_size
|
121
|
+
params[:sort] = @sort if @enable_sort
|
122
|
+
end
|
123
|
+
|
124
|
+
@logger.debug("Querying opensearch for lookup", :params => params)
|
125
|
+
|
126
|
+
results = get_client.search(params)
|
127
|
+
raise "OpenSearch query error: #{results["_shards"]["failures"]}" if results["_shards"].include? "failures"
|
128
|
+
|
129
|
+
event.set("[@metadata][total_hits]", extract_total_from_hits(results['hits']))
|
130
|
+
|
131
|
+
resultsHits = results["hits"]["hits"]
|
132
|
+
if !resultsHits.nil? && !resultsHits.empty?
|
133
|
+
matched = true
|
134
|
+
@fields.each do |old_key, new_key|
|
135
|
+
old_key_path = extract_path(old_key)
|
136
|
+
set = resultsHits.map do |doc|
|
137
|
+
extract_value(doc["_source"], old_key_path)
|
138
|
+
end
|
139
|
+
event.set(new_key, set.count > 1 ? set : set.first)
|
140
|
+
end
|
141
|
+
@docinfo_fields.each do |old_key, new_key|
|
142
|
+
old_key_path = extract_path(old_key)
|
143
|
+
set = resultsHits.map do |doc|
|
144
|
+
extract_value(doc, old_key_path)
|
145
|
+
end
|
146
|
+
event.set(new_key, set.count > 1 ? set : set.first)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
resultsAggs = results["aggregations"]
|
151
|
+
if !resultsAggs.nil? && !resultsAggs.empty?
|
152
|
+
matched = true
|
153
|
+
@aggregation_fields.each do |agg_name, ls_field|
|
154
|
+
event.set(ls_field, resultsAggs[agg_name])
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
rescue => e
|
159
|
+
if @logger.trace?
|
160
|
+
@logger.warn("Failed to query opensearch for previous event", :index => @index, :query => query, :event => event.to_hash, :error => e.message, :backtrace => e.backtrace)
|
161
|
+
elsif @logger.debug?
|
162
|
+
@logger.warn("Failed to query opensearch for previous event", :index => @index, :error => e.message, :backtrace => e.backtrace)
|
163
|
+
else
|
164
|
+
@logger.warn("Failed to query opensearch for previous event", :index => @index, :error => e.message)
|
165
|
+
end
|
166
|
+
@tag_on_failure.each{|tag| event.tag(tag)}
|
167
|
+
else
|
168
|
+
filter_matched(event) if matched
|
169
|
+
end
|
170
|
+
end # def filter
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def new_client
|
175
|
+
# NOTE: could pass cloud-id/cloud-auth to client but than we would need to be stricter on ES version requirement
|
176
|
+
# and also LS parsing might differ from ES client's parsing so for consistency we do not pass cloud options ...
|
177
|
+
OpenSearch::Client.new(
|
178
|
+
:hosts => @hosts,
|
179
|
+
:transport_options => @transport_options,
|
180
|
+
:transport_class => ::OpenSearch::Transport::Transport::HTTP::Manticore,
|
181
|
+
:ssl => @ssl_options
|
182
|
+
)
|
183
|
+
end
|
184
|
+
|
185
|
+
def get_client
|
186
|
+
@clients_pool.computeIfAbsent(Thread.current, lambda { |x| new_client })
|
187
|
+
end
|
188
|
+
|
189
|
+
# get an array of path elements from a path reference
|
190
|
+
def extract_path(path_reference)
|
191
|
+
return [path_reference] unless path_reference.start_with?('[') && path_reference.end_with?(']')
|
192
|
+
|
193
|
+
path_reference[1...-1].split('][')
|
194
|
+
end
|
195
|
+
|
196
|
+
# given a Hash and an array of path fragments, returns the value at the path
|
197
|
+
# @param source [Hash{String=>Object}]
|
198
|
+
# @param path [Array{String}]
|
199
|
+
# @return [Object]
|
200
|
+
def extract_value(source, path)
|
201
|
+
path.reduce(source) do |memo, old_key_fragment|
|
202
|
+
break unless memo.include?(old_key_fragment)
|
203
|
+
memo[old_key_fragment]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Given a "hits" object from an OpenSearch response, return the total number of hits in
|
208
|
+
# the result set.
|
209
|
+
# @param hits [Hash{String=>Object}]
|
210
|
+
# @return [Integer]
|
211
|
+
def extract_total_from_hits(hits)
|
212
|
+
total = hits['total']
|
213
|
+
|
214
|
+
# OpenSearch 7.x produces an object containing `value` and `relation` in order
|
215
|
+
# to enable unambiguous reporting when the total is only a lower bound; if we get
|
216
|
+
# an object back, return its `value`.
|
217
|
+
return total['value'] if total.kind_of?(Hash)
|
218
|
+
|
219
|
+
total
|
220
|
+
end
|
221
|
+
|
222
|
+
def hosts_default?(hosts)
|
223
|
+
# NOTE: would be nice if pipeline allowed us a clean way to detect a config default :
|
224
|
+
hosts.is_a?(Array) && hosts.size == 1 && hosts.first.equal?(DEFAULT_HOST)
|
225
|
+
end
|
226
|
+
|
227
|
+
def validate_authentication
|
228
|
+
authn_options = 0
|
229
|
+
authn_options += 1 if @cloud_auth
|
230
|
+
authn_options += 1 if (@api_key && @api_key.value)
|
231
|
+
authn_options += 1 if (@user || (@password && @password.value))
|
232
|
+
|
233
|
+
if authn_options > 1
|
234
|
+
raise LogStash::ConfigurationError, 'Multiple authentication options are specified, please only use one of user/password, cloud_auth or api_key'
|
235
|
+
end
|
236
|
+
|
237
|
+
if @api_key && @api_key.value && @ssl != true
|
238
|
+
raise(LogStash::ConfigurationError, "Using api_key authentication requires SSL/TLS secured communication using the `ssl => true` option")
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def setup_hosts
|
243
|
+
@hosts = Array(@hosts).map { |host| host.to_s } # potential SafeURI#to_s
|
244
|
+
if @ssl
|
245
|
+
@hosts.map do |h|
|
246
|
+
host, port = h.split(":")
|
247
|
+
{ :host => host, :scheme => 'https', :port => port }
|
248
|
+
end
|
249
|
+
else
|
250
|
+
@hosts
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def setup_ssl
|
255
|
+
return { :ssl => true, :ca_file => @ca_file } if @ssl && @ca_file
|
256
|
+
return { :ssl => true, :verify => false } if @ssl # Setting verify as false if ca_file is not provided
|
257
|
+
end
|
258
|
+
|
259
|
+
def setup_basic_auth(user, password)
|
260
|
+
return {} unless user && password && password.value
|
261
|
+
|
262
|
+
token = ::Base64.strict_encode64("#{user}:#{password.value}")
|
263
|
+
{ 'Authorization' => "Basic #{token}" }
|
264
|
+
end
|
265
|
+
|
266
|
+
def prepare_user_agent
|
267
|
+
os_name = java.lang.System.getProperty('os.name')
|
268
|
+
os_version = java.lang.System.getProperty('os.version')
|
269
|
+
os_arch = java.lang.System.getProperty('os.arch')
|
270
|
+
jvm_vendor = java.lang.System.getProperty('java.vendor')
|
271
|
+
jvm_version = java.lang.System.getProperty('java.version')
|
272
|
+
|
273
|
+
plugin_version = Gem.loaded_specs["logstash-filter-opensearch-manticore"].version
|
274
|
+
# example: logstash/7.14.1 (OS=Linux-5.4.0-84-generic-amd64; JVM=AdoptOpenJDK-11.0.11) logstash-input-opensearch/4.10.0
|
275
|
+
"logstash/#{LOGSTASH_VERSION} (OS=#{os_name}-#{os_version}-#{os_arch}; JVM=#{jvm_vendor}-#{jvm_version}) logstash-#{@plugin_type}-#{config_name}/#{plugin_version}"
|
276
|
+
end
|
277
|
+
|
278
|
+
def test_connection!
|
279
|
+
get_client.client.ping
|
280
|
+
end
|
281
|
+
end #class LogStash::Filters::OpenSearch
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
|
3
|
+
s.name = 'logstash-filter-opensearch-manticore'
|
4
|
+
s.version = '0.1.0'
|
5
|
+
s.licenses = ['Apache License (2.0)']
|
6
|
+
s.summary = "Copies fields from previous log events in OpenSearch to current events "
|
7
|
+
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
|
8
|
+
s.authors = ["Anton Klyba"]
|
9
|
+
s.email = 'anarhyst266@gmail.com'
|
10
|
+
s.homepage = "https://github.com/Anarhyst266/logstash-filter-opensearch-manticore"
|
11
|
+
s.require_paths = ["lib"]
|
12
|
+
|
13
|
+
# Files
|
14
|
+
s.files = Dir["lib/**/*","spec/**/*","*.gemspec","*.md","CONTRIBUTORS","Gemfile","LICENSE","NOTICE.TXT", "vendor/jar-dependencies/**/*.jar", "vendor/jar-dependencies/**/*.rb", "VERSION", "docs/**/*"]
|
15
|
+
|
16
|
+
# Tests
|
17
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
18
|
+
|
19
|
+
# Special flag to let us know this is actually a logstash plugin
|
20
|
+
s.metadata = { "logstash_plugin" => "true", "logstash_group" => "filter" }
|
21
|
+
|
22
|
+
# Gem dependencies
|
23
|
+
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
|
24
|
+
s.add_runtime_dependency 'opensearch-ruby'
|
25
|
+
s.add_runtime_dependency 'manticore', "~> 0.6"
|
26
|
+
|
27
|
+
s.add_development_dependency 'logstash-devutils'
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
{
|
2
|
+
"took": 49,
|
3
|
+
"timed_out": false,
|
4
|
+
"_shards": {
|
5
|
+
"total": 155,
|
6
|
+
"successful": 155,
|
7
|
+
"failed": 0
|
8
|
+
},
|
9
|
+
"hits": {
|
10
|
+
"total": {
|
11
|
+
"value": 13476,
|
12
|
+
"relation": "eq"
|
13
|
+
},
|
14
|
+
"max_score": 1,
|
15
|
+
"hits": [{
|
16
|
+
"_index": "logstash-2014.08.26",
|
17
|
+
"_type": "logs",
|
18
|
+
"_id": "AVVY76L_AW7v0kX8KXo4",
|
19
|
+
"_score": 1,
|
20
|
+
"_source": {
|
21
|
+
"request": "/doc/index.html?org/opensearch/action/search/SearchResponse.html",
|
22
|
+
"agent": "\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\"",
|
23
|
+
"geoip": {
|
24
|
+
"timezone": "America/Los_Angeles",
|
25
|
+
"ip": "66.249.73.185",
|
26
|
+
"latitude": 37.386,
|
27
|
+
"continent_code": "NA",
|
28
|
+
"city_name": "Mountain View",
|
29
|
+
"country_code2": "US",
|
30
|
+
"country_name": "United States",
|
31
|
+
"dma_code": 807,
|
32
|
+
"country_code3": "US",
|
33
|
+
"region_name": "California",
|
34
|
+
"location": [-122.0838,
|
35
|
+
37.386
|
36
|
+
],
|
37
|
+
"postal_code": "94035",
|
38
|
+
"longitude": -122.0838,
|
39
|
+
"region_code": "CA"
|
40
|
+
},
|
41
|
+
"auth": "-",
|
42
|
+
"ident": "-",
|
43
|
+
"verb": "GET",
|
44
|
+
"useragent": {
|
45
|
+
"os": "Other",
|
46
|
+
"major": "2",
|
47
|
+
"minor": "1",
|
48
|
+
"name": "Googlebot",
|
49
|
+
"os_name": "Other",
|
50
|
+
"device": "Spider"
|
51
|
+
},
|
52
|
+
"message": "66.249.73.185 - - [26/Aug/2014:21:22:13 +0000] \"GET /doc/index.html?org/opensearch/action/search/SearchResponse.html HTTP/1.1\" 404 294 \"-\" \"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\"",
|
53
|
+
"referrer": "\"-\"",
|
54
|
+
"@timestamp": "2014-08-26T21:22:13.000Z",
|
55
|
+
"response": 404,
|
56
|
+
"bytes": 294,
|
57
|
+
"clientip": "66.249.73.185",
|
58
|
+
"@version": "1",
|
59
|
+
"host": "skywalker",
|
60
|
+
"httpversion": "1.1",
|
61
|
+
"timestamp": "26/Aug/2014:21:22:13 +0000"
|
62
|
+
}
|
63
|
+
}]
|
64
|
+
},
|
65
|
+
"aggregations": {
|
66
|
+
"bytes_avg": {
|
67
|
+
"value": 294
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
{
|
2
|
+
"took": 16,
|
3
|
+
"timed_out": false,
|
4
|
+
"_shards": {
|
5
|
+
"total": 155,
|
6
|
+
"successful": 100,
|
7
|
+
"failed": 55,
|
8
|
+
"failures": [
|
9
|
+
{
|
10
|
+
"shard": 0,
|
11
|
+
"index": "logstash-2014.08.26",
|
12
|
+
"node": "YI1MT0H-Q469pFgAVTXI2g",
|
13
|
+
"reason": {
|
14
|
+
"type": "search_parse_exception",
|
15
|
+
"reason": "No mapping found for [@timestamp] in order to sort on"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
]
|
19
|
+
},
|
20
|
+
"hits": {
|
21
|
+
"total": 0,
|
22
|
+
"max_score": null,
|
23
|
+
"hits": []
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"took": 49,
|
3
|
+
"timed_out": false,
|
4
|
+
"_shards": {
|
5
|
+
"total": 155,
|
6
|
+
"successful": 155,
|
7
|
+
"failed": 0
|
8
|
+
},
|
9
|
+
"hits": {
|
10
|
+
"total": 13476,
|
11
|
+
"max_score": 1,
|
12
|
+
"hits": []
|
13
|
+
},
|
14
|
+
"aggregations": {
|
15
|
+
"bytes_avg": {
|
16
|
+
"value": 294
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,67 @@
|
|
1
|
+
{
|
2
|
+
"took": 49,
|
3
|
+
"timed_out": false,
|
4
|
+
"_shards": {
|
5
|
+
"total": 155,
|
6
|
+
"successful": 155,
|
7
|
+
"failed": 0
|
8
|
+
},
|
9
|
+
"hits": {
|
10
|
+
"total": 13476,
|
11
|
+
"max_score": 1,
|
12
|
+
"hits": [{
|
13
|
+
"_index": "logstash-2014.08.26",
|
14
|
+
"_type": "logs",
|
15
|
+
"_id": "AVVY76L_AW7v0kX8KXo4",
|
16
|
+
"_score": 1,
|
17
|
+
"_source": {
|
18
|
+
"request": "/doc/index.html?org/opensearch/action/search/SearchResponse.html",
|
19
|
+
"agent": "\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\"",
|
20
|
+
"geoip": {
|
21
|
+
"timezone": "America/Los_Angeles",
|
22
|
+
"ip": "66.249.73.185",
|
23
|
+
"latitude": 37.386,
|
24
|
+
"continent_code": "NA",
|
25
|
+
"city_name": "Mountain View",
|
26
|
+
"country_code2": "US",
|
27
|
+
"country_name": "United States",
|
28
|
+
"dma_code": 807,
|
29
|
+
"country_code3": "US",
|
30
|
+
"region_name": "California",
|
31
|
+
"location": [-122.0838,
|
32
|
+
37.386
|
33
|
+
],
|
34
|
+
"postal_code": "94035",
|
35
|
+
"longitude": -122.0838,
|
36
|
+
"region_code": "CA"
|
37
|
+
},
|
38
|
+
"auth": "-",
|
39
|
+
"ident": "-",
|
40
|
+
"verb": "GET",
|
41
|
+
"useragent": {
|
42
|
+
"os": "Other",
|
43
|
+
"major": "2",
|
44
|
+
"minor": "1",
|
45
|
+
"name": "Googlebot",
|
46
|
+
"os_name": "Other",
|
47
|
+
"device": "Spider"
|
48
|
+
},
|
49
|
+
"message": "66.249.73.185 - - [26/Aug/2014:21:22:13 +0000] \"GET /doc/index.html?org/opensearch/action/search/SearchResponse.html HTTP/1.1\" 404 294 \"-\" \"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\"",
|
50
|
+
"referrer": "\"-\"",
|
51
|
+
"@timestamp": "2014-08-26T21:22:13.000Z",
|
52
|
+
"response": 404,
|
53
|
+
"bytes": 294,
|
54
|
+
"clientip": "66.249.73.185",
|
55
|
+
"@version": "1",
|
56
|
+
"host": "skywalker",
|
57
|
+
"httpversion": "1.1",
|
58
|
+
"timestamp": "26/Aug/2014:21:22:13 +0000"
|
59
|
+
}
|
60
|
+
}]
|
61
|
+
},
|
62
|
+
"aggregations": {
|
63
|
+
"bytes_avg": {
|
64
|
+
"value": 294
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|