kibana_url 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/kibana_url.rb +171 -0
  3. metadata +114 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: df06b756323795b501ddba29c60200ad095891bc
4
+ data.tar.gz: 4f6ae06b517c4cddb9b30e60c3280cee70f1d2e4
5
+ SHA512:
6
+ metadata.gz: 405f69e7a2f87ba94ca13556ae14c8a1346a8b438ad8b048c6dfb359e214ceeaf2f863032f83bdd93f7aa59e2463bb17398b7e13a01cfee645f506714b89999d
7
+ data.tar.gz: 9c1f8caa46a7abf423cd770d3ec97440bed772bbd43e94d00bfc85bf7a714bfe333178c10602e2a4ff945fa9ec6a446c71c5d013597eb64d53fefa1e958bf9d7
data/lib/kibana_url.rb ADDED
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+ require 'contracts'
5
+
6
+ ### EXAMPLE URL ###
7
+ # https://kibana.example.net/app/kibana#/discover?
8
+ # _g=(refreshInterval:(display:'5%20minutes',pause:!f,section:2,value:300000),
9
+ # time:(from:now-15h,mode:relative,to:now))&
10
+ # _a=(columns:!(container_name,hostname,message,metadata.application),
11
+ # index:'logs-*',interval:auto,query:(query_string:(analyze_wildcard:!t,
12
+ # query:'foo%20bar')),sort:!(time,desc))
13
+
14
+ # Constructs URLs for Kibana queries.
15
+ module KibanaUrl
16
+ include Contracts::Core
17
+ include Contracts::Builtin
18
+
19
+ class NotConfiguredError < StandardError; end
20
+
21
+ # stuff after the base URL
22
+ STANDARD_PATH = '#/discover'
23
+
24
+ # possible sort modes
25
+ SORT_MODES = %i[asc desc].freeze
26
+
27
+ # possible time scoping modes
28
+ TIME_SCOPE_MODES = %i[relative absolute].freeze
29
+ # nil to not use custom time_scoping - defaults to 15 minutes ago to now
30
+ # :relative, a time from some Time to now
31
+ # :absolute, a time from some Time to some Time.
32
+
33
+ class << self
34
+ attr_accessor :config
35
+
36
+ def configure
37
+ self.config ||= {}
38
+ yield config
39
+ end
40
+
41
+ # Generates a Kibana URL configured to particular query.
42
+ # Args:
43
+ # spout_name - key from the hash configured as index_patterns.
44
+ # columns - array of column names (Strings) to view for each log.
45
+ # query - string for the query to search on.
46
+ # sort - how the logs should be sorted. Options are:
47
+ # * log_param_name - what you are sorting on
48
+ # * mode - :asc or :desc (see SORT_MODES above)
49
+ # refresh_interval_param - number of seconds how often to refresh
50
+ # - supports Integer or Nil (default)
51
+ # time_scope - Hash to specify a custom time scope. Keys:
52
+ # * from: Time (or subclass)
53
+ # * to: Time (or subclass)
54
+ # * mode: see TIME_SCOPE_MODES above for description.
55
+ # Calling just generate(), with no args, will give a default Kibana URL.
56
+ Contract KeywordArgs[
57
+ log_spout: Optional[Symbol],
58
+ columns: Optional[ArrayOf[String]],
59
+ query: Optional[String],
60
+ sort: Optional[{ log_param_name: String, mode: Enum[*SORT_MODES] }],
61
+ refresh_interval: Optional[Maybe[Integer]],
62
+ time_scope: Optional[KeywordArgs[
63
+ mode: Enum[*TIME_SCOPE_MODES],
64
+ from: Optional[Time],
65
+ to: Optional[Time]
66
+ ]]
67
+ ] => String
68
+ def generate(
69
+ log_spout: config&.[](:index_patterns)&.keys&.first,
70
+ columns: ['_source'],
71
+ query: '*',
72
+ sort: { log_param_name: 'time', mode: :desc },
73
+ refresh_interval: nil,
74
+ time_scope: { mode: :relative }
75
+ )
76
+ if config.nil? ||
77
+ config[:index_patterns].empty? || config[:kibana_base_url].empty?
78
+ raise NotConfiguredError
79
+ end
80
+
81
+ # There are two params in Kibana URLs.
82
+ # Each have multiple arguments comma separated.
83
+ a_params = []
84
+ a_params << columns_param(columns)
85
+ a_params << spout_param(log_spout)
86
+ a_params << interval_param
87
+ a_params << query_param(query)
88
+ a_params << sort_param(sort)
89
+ a_params_str = a_params.compact.join(',') # comma delimit params
90
+
91
+ g_params = []
92
+ g_params << refresh_interval_param(refresh_interval)
93
+ g_params << time_scope_param(time_scope)
94
+ g_params_str = g_params.compact.join(',') # comma delimit params
95
+
96
+ "#{config[:kibana_base_url]}#{STANDARD_PATH}?" \
97
+ "_g=(#{g_params_str})&_a=(#{a_params_str})"
98
+ end
99
+
100
+ private
101
+
102
+ # Method to construct columns params in query.
103
+ # "columns:!(col_1,col_2,...,col_n)"
104
+ def columns_param(column_names)
105
+ column_names.map! { |name| escape(name) }
106
+ "columns:!(#{column_names.join(',')})"
107
+ end
108
+
109
+ # Method determines correct index pattern (stream from which to draw logs).
110
+ # "index:'<spout name>'"
111
+ def spout_param(spout_name)
112
+ "index:'#{config[:index_patterns][spout_name]}'"
113
+ end
114
+
115
+ # Method for interval - unclear what this does.
116
+ # "interval:auto"
117
+ def interval_param
118
+ "interval:auto"
119
+ end
120
+
121
+ # Method for query param.
122
+ # "query:(query_string:(analyze_wildcard:!t,query:'<url escaped query>'))"
123
+ def query_param(raw_query_str)
124
+ "query:(query_string:(analyze_wildcard:" \
125
+ "!t,query:'#{escape(raw_query_str)}'))"
126
+ end
127
+
128
+ # Method to set a particular sort on the logs.
129
+ # "sort:!(<log param name>,<sort mode: :desc or :asc>)"
130
+ def sort_param(log_param_name: 'time', mode: :desc)
131
+ "sort:!(#{escape(log_param_name)},#{mode})"
132
+ end
133
+
134
+ # Method to set the refresh interval.
135
+ # "refreshInterval:(display:'<num seconds string>'," \
136
+ # "pause:!f,section:1,value:<num milliseconds>)"
137
+ def refresh_interval_param(seconds)
138
+ return nil unless seconds
139
+ "refreshInterval:(display:'#{seconds}%20seconds'," \
140
+ "pause:!f,section:1,value:#{seconds * 1000})"
141
+ end
142
+
143
+ # Method to set a time scope for the query.
144
+ # Creates "time:(from:<from Time>,mode:<mode>,to:<from Time>)" or nil
145
+ def time_scope_param(
146
+ mode: :relative,
147
+ from: Time.now - (15 * 60),
148
+ to: Time.now
149
+ )
150
+ if mode == :relative
151
+ to_str = 'now'
152
+ num_seconds_ago = Time.now.to_i - from.to_i
153
+ from_str = "now-#{num_seconds_ago}s"
154
+ elsif mode == :absolute
155
+ to_str = date_time_str(to)
156
+ from_str = date_time_str(from)
157
+ end
158
+ "time:(from:'#{from_str}',mode:#{mode},to:'#{to_str}')"
159
+ end
160
+
161
+ # Translates a time into a date-time string for Kibana
162
+ def date_time_str(time)
163
+ "#{time.utc.strftime('%Y-%m-%d')}T#{time.utc.strftime('%H:%M:%S.%L')}Z"
164
+ end
165
+
166
+ # Alias for URL escaping.
167
+ def escape(str)
168
+ CGI.escape(str)
169
+ end
170
+ end
171
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kibana_url
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - coinbase
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-04-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: contracts
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.14'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.41'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.41'
69
+ - !ruby/object:Gem::Dependency
70
+ name: timecop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.7'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.7'
83
+ description: Builds complex ULRs for Kibana with all settings prefilled.
84
+ email: julian.borrey@coinbase.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - lib/kibana_url.rb
90
+ homepage: https://rubygems.org/gems/kibana_url
91
+ licenses:
92
+ - Apache-2.0
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.6.10
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Builds Kibana query URLs.
114
+ test_files: []