logstash-logger-yajl 0.27.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +1156 -0
  5. data/.travis.yml +26 -0
  6. data/Appraisals +23 -0
  7. data/CHANGELOG.md +203 -0
  8. data/Gemfile +6 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +880 -0
  11. data/Rakefile +23 -0
  12. data/gemfiles/rails_3.2.gemfile +9 -0
  13. data/gemfiles/rails_4.0.gemfile +9 -0
  14. data/gemfiles/rails_4.1.gemfile +9 -0
  15. data/gemfiles/rails_4.2.gemfile +9 -0
  16. data/gemfiles/rails_5.0.gemfile +9 -0
  17. data/gemfiles/rails_5.1.gemfile +9 -0
  18. data/lib/logstash-event.rb +1 -0
  19. data/lib/logstash-logger.rb +11 -0
  20. data/lib/logstash-logger/buffer.rb +336 -0
  21. data/lib/logstash-logger/configuration.rb +29 -0
  22. data/lib/logstash-logger/device.rb +67 -0
  23. data/lib/logstash-logger/device/aws_stream.rb +94 -0
  24. data/lib/logstash-logger/device/balancer.rb +40 -0
  25. data/lib/logstash-logger/device/base.rb +73 -0
  26. data/lib/logstash-logger/device/connectable.rb +131 -0
  27. data/lib/logstash-logger/device/file.rb +23 -0
  28. data/lib/logstash-logger/device/firehose.rb +42 -0
  29. data/lib/logstash-logger/device/io.rb +11 -0
  30. data/lib/logstash-logger/device/kafka.rb +57 -0
  31. data/lib/logstash-logger/device/kinesis.rb +44 -0
  32. data/lib/logstash-logger/device/multi_delegator.rb +36 -0
  33. data/lib/logstash-logger/device/redis.rb +69 -0
  34. data/lib/logstash-logger/device/socket.rb +21 -0
  35. data/lib/logstash-logger/device/stderr.rb +13 -0
  36. data/lib/logstash-logger/device/stdout.rb +14 -0
  37. data/lib/logstash-logger/device/tcp.rb +86 -0
  38. data/lib/logstash-logger/device/udp.rb +12 -0
  39. data/lib/logstash-logger/device/unix.rb +18 -0
  40. data/lib/logstash-logger/formatter.rb +51 -0
  41. data/lib/logstash-logger/formatter/base.rb +73 -0
  42. data/lib/logstash-logger/formatter/cee.rb +11 -0
  43. data/lib/logstash-logger/formatter/cee_syslog.rb +22 -0
  44. data/lib/logstash-logger/formatter/json.rb +11 -0
  45. data/lib/logstash-logger/formatter/json_lines.rb +11 -0
  46. data/lib/logstash-logger/formatter/logstash_event.rb +6 -0
  47. data/lib/logstash-logger/logger.rb +106 -0
  48. data/lib/logstash-logger/multi_logger.rb +153 -0
  49. data/lib/logstash-logger/railtie.rb +51 -0
  50. data/lib/logstash-logger/silenced_logging.rb +83 -0
  51. data/lib/logstash-logger/tagged_logging.rb +40 -0
  52. data/lib/logstash-logger/version.rb +3 -0
  53. data/lib/logstash/event.rb +272 -0
  54. data/lib/logstash/namespace.rb +15 -0
  55. data/lib/logstash/util.rb +105 -0
  56. data/lib/logstash/util/fieldreference.rb +49 -0
  57. data/logstash-logger.gemspec +42 -0
  58. data/samples/example.crt +16 -0
  59. data/samples/example.key +15 -0
  60. data/samples/file.conf +11 -0
  61. data/samples/redis.conf +12 -0
  62. data/samples/ssl.conf +15 -0
  63. data/samples/syslog.conf +10 -0
  64. data/samples/tcp.conf +11 -0
  65. data/samples/udp.conf +11 -0
  66. data/samples/unix.conf +11 -0
  67. data/spec/configuration_spec.rb +27 -0
  68. data/spec/constructor_spec.rb +30 -0
  69. data/spec/device/balancer_spec.rb +31 -0
  70. data/spec/device/connectable_spec.rb +74 -0
  71. data/spec/device/file_spec.rb +15 -0
  72. data/spec/device/firehose_spec.rb +41 -0
  73. data/spec/device/io_spec.rb +13 -0
  74. data/spec/device/kafka_spec.rb +32 -0
  75. data/spec/device/kinesis_spec.rb +41 -0
  76. data/spec/device/multi_delegator_spec.rb +31 -0
  77. data/spec/device/redis_spec.rb +52 -0
  78. data/spec/device/socket_spec.rb +15 -0
  79. data/spec/device/stderr_spec.rb +16 -0
  80. data/spec/device/stdout_spec.rb +31 -0
  81. data/spec/device/tcp_spec.rb +120 -0
  82. data/spec/device/udp_spec.rb +9 -0
  83. data/spec/device/unix_spec.rb +23 -0
  84. data/spec/device_spec.rb +97 -0
  85. data/spec/formatter/base_spec.rb +125 -0
  86. data/spec/formatter/cee_spec.rb +15 -0
  87. data/spec/formatter/cee_syslog_spec.rb +43 -0
  88. data/spec/formatter/json_lines_spec.rb +14 -0
  89. data/spec/formatter/json_spec.rb +10 -0
  90. data/spec/formatter/logstash_event_spec.rb +10 -0
  91. data/spec/formatter_spec.rb +79 -0
  92. data/spec/logger_spec.rb +128 -0
  93. data/spec/logstash_event_spec.rb +139 -0
  94. data/spec/multi_logger_spec.rb +59 -0
  95. data/spec/rails_spec.rb +91 -0
  96. data/spec/silenced_logging_spec.rb +31 -0
  97. data/spec/spec_helper.rb +111 -0
  98. data/spec/syslog_spec.rb +32 -0
  99. data/spec/tagged_logging_spec.rb +32 -0
  100. metadata +385 -0
@@ -0,0 +1,83 @@
1
+ # Adapted from:
2
+ # https://github.com/rails/activerecord-session_store/blob/master/lib/active_record/session_store/extension/logger_silencer.rb
3
+ # https://github.com/rails/rails/pull/16885
4
+
5
+ require 'thread'
6
+
7
+ # Add support for Rails-style logger silencing. Thread-safe and no dependencies.
8
+ #
9
+ # Setup:
10
+ # logger = Logger.new(STDOUT)
11
+ # logger.extend(LogStashLogger::SilencedLogging)
12
+ #
13
+ # Usage:
14
+ #
15
+ # logger.silence do
16
+ # ...
17
+ # end
18
+ #
19
+ module LogStashLogger
20
+ module SilencedLogging
21
+ def self.extended(logger)
22
+ class << logger
23
+ attr_accessor :silencer
24
+ alias_method :level_without_thread_safety, :level
25
+ alias_method :level, :level_with_thread_safety
26
+ alias_method :add_without_thread_safety, :add
27
+ alias_method :add, :add_with_thread_safety
28
+
29
+ Logger::Severity.constants.each do |severity|
30
+ instance_eval <<-EOT, __FILE__, __LINE__ + 1
31
+ def #{severity.downcase}? # def debug?
32
+ Logger::#{severity} >= level # DEBUG >= level
33
+ end # end
34
+ EOT
35
+ end
36
+ end
37
+
38
+ logger.instance_eval do
39
+ self.silencer = true
40
+ end
41
+ end
42
+
43
+ def thread_level
44
+ Thread.current[thread_hash_level_key]
45
+ end
46
+
47
+ def thread_level=(level)
48
+ Thread.current[thread_hash_level_key] = level
49
+ end
50
+
51
+ def level_with_thread_safety
52
+ thread_level || level_without_thread_safety
53
+ end
54
+
55
+ def add_with_thread_safety(severity, message = nil, progname = nil, &block)
56
+ if (defined?(@logdev) && @logdev.nil?) || (severity || UNKNOWN) < level
57
+ true
58
+ else
59
+ add_without_thread_safety(severity, message, progname, &block)
60
+ end
61
+ end
62
+
63
+ # Silences the logger for the duration of the block.
64
+ def silence(temporary_level = Logger::ERROR)
65
+ if silencer
66
+ begin
67
+ self.thread_level = temporary_level
68
+ yield self
69
+ ensure
70
+ self.thread_level = nil
71
+ end
72
+ else
73
+ yield self
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def thread_hash_level_key
80
+ @thread_hash_level_key ||= :"ThreadSafeLogger##{object_id}@level"
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,40 @@
1
+ module LogStashLogger
2
+ # Shamelessly copied from ActiveSupport::TaggedLogging
3
+ module TaggedLogging
4
+ def tagged(*tags)
5
+ formatter.tagged(*tags) { yield self }
6
+ end
7
+
8
+ def flush
9
+ formatter.clear_tags!
10
+ super if defined?(super)
11
+ end
12
+
13
+ module Formatter
14
+ def tagged(*tags)
15
+ new_tags = push_tags(*tags)
16
+ yield self
17
+ ensure
18
+ pop_tags(new_tags.size)
19
+ end
20
+
21
+ def push_tags(*tags)
22
+ tags.flatten.reject{ |t| t.nil? || t.empty? }.tap do |new_tags|
23
+ current_tags.concat new_tags
24
+ end
25
+ end
26
+
27
+ def pop_tags(size = 1)
28
+ current_tags.pop size
29
+ end
30
+
31
+ def clear_tags!
32
+ current_tags.clear
33
+ end
34
+
35
+ def current_tags
36
+ Thread.current[:logstash_logger_tags] ||= []
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module LogStashLogger
2
+ VERSION = "0.27.0"
3
+ end
@@ -0,0 +1,272 @@
1
+ require "yajl"
2
+ require "time"
3
+ require "date"
4
+ require "logstash/namespace"
5
+ require "logstash/util/fieldreference"
6
+
7
+ # Use a custom serialization for jsonifying Time objects.
8
+ # TODO(sissel): Put this in a separate file.
9
+ class Time
10
+ def to_json(*args)
11
+ return iso8601(3).to_json(*args)
12
+ end
13
+
14
+ def inspect
15
+ return to_json
16
+ end
17
+ end
18
+
19
+ # the logstash event object.
20
+ #
21
+ # An event is simply a tuple of (timestamp, data).
22
+ # The 'timestamp' is an ISO8601 timestamp. Data is anything - any message,
23
+ # context, references, etc that are relevant to this event.
24
+ #
25
+ # Internally, this is represented as a hash with only two guaranteed fields.
26
+ #
27
+ # * "@timestamp" - an ISO8601 timestamp representing the time the event
28
+ # occurred at.
29
+ # * "@version" - the version of the schema. Currently "1"
30
+ #
31
+ # They are prefixed with an "@" symbol to avoid clashing with your
32
+ # own custom fields.
33
+ #
34
+ # When serialized, this is represented in JSON. For example:
35
+ #
36
+ # {
37
+ # "@timestamp": "2013-02-09T20:39:26.234Z",
38
+ # "@version": "1",
39
+ # message: "hello world"
40
+ # }
41
+ class LogStash::Event
42
+ class DeprecatedMethod < StandardError; end
43
+
44
+ public
45
+ def initialize(data={})
46
+ @cancelled = false
47
+
48
+ @data = data
49
+ if data.include?("@timestamp")
50
+ t = data["@timestamp"]
51
+ if t.is_a?(String)
52
+ data["@timestamp"] = Time.parse(t).gmtime
53
+ end
54
+ else
55
+ data["@timestamp"] = ::Time.now.utc
56
+ end
57
+ data["@version"] = "1" if !@data.include?("@version")
58
+ end # def initialize
59
+
60
+ # Add class methods on inclusion.
61
+ public
62
+ def self.included(klass)
63
+ klass.extend(ClassMethods)
64
+ end # def included
65
+
66
+ module ClassMethods
67
+ public
68
+ def from_json(json)
69
+ return self.new(Yajl.load(json))
70
+ end # def from_json
71
+ end
72
+
73
+ public
74
+ def cancel
75
+ @cancelled = true
76
+ end # def cancel
77
+
78
+ public
79
+ def uncancel
80
+ @cancelled = false
81
+ end # def uncancel
82
+
83
+ public
84
+ def cancelled?
85
+ return @cancelled
86
+ end # def cancelled?
87
+
88
+ # Create a deep-ish copy of this event.
89
+ public
90
+ def clone
91
+ copy = {}
92
+ @data.each do |k,v|
93
+ # TODO(sissel): Recurse if this is a hash/array?
94
+ copy[k] = v.clone
95
+ end
96
+ return self.class.new(copy)
97
+ end # def clone
98
+
99
+ if RUBY_ENGINE == "jruby"
100
+ public
101
+ def to_s
102
+ return self.sprintf("%{+yyyy-MM-dd'T'HH:mm:ss.SSSZ} %{host} %{message}")
103
+ end # def to_s
104
+ else
105
+ public
106
+ def to_s
107
+ return self.sprintf("#{self["@timestamp"].iso8601} %{host} %{message}")
108
+ end # def to_s
109
+ end
110
+
111
+ public
112
+ def timestamp; return @data["@timestamp"]; end # def timestamp
113
+ def timestamp=(val); return @data["@timestamp"] = val; end # def timestamp=
114
+
115
+ def unix_timestamp
116
+ raise DeprecatedMethod
117
+ end # def unix_timestamp
118
+
119
+ def ruby_timestamp
120
+ raise DeprecatedMethod
121
+ end # def unix_timestamp
122
+
123
+ # field-related access
124
+ public
125
+ def [](str)
126
+ if str[0,1] == "+"
127
+ else
128
+ return LogStash::Util::FieldReference.exec(str, @data)
129
+ end
130
+ end # def []
131
+
132
+ public
133
+ def []=(str, value)
134
+ r = LogStash::Util::FieldReference.exec(str, @data) do |obj, key|
135
+ obj[key] = value
136
+ end
137
+
138
+ # The assignment can fail if the given field reference (str) does not exist
139
+ # In this case, we'll want to set the value manually.
140
+ if r.nil?
141
+ # TODO(sissel): Implement this in LogStash::Util::FieldReference
142
+ if str[0,1] != "["
143
+ return @data[str] = value
144
+ end
145
+
146
+ # No existing element was found, so let's set one.
147
+ *parents, key = str.scan(/(?<=\[)[^\]]+(?=\])/)
148
+ obj = @data
149
+ parents.each do |p|
150
+ if obj.include?(p)
151
+ obj = obj[p]
152
+ else
153
+ obj[p] = {}
154
+ obj = obj[p]
155
+ end
156
+ end
157
+ obj[key] = value
158
+ end
159
+ return value
160
+ end # def []=
161
+
162
+ public
163
+ def fields
164
+ raise DeprecatedMethod
165
+ end
166
+
167
+ public
168
+ def to_json(*args)
169
+ return Yajl.dump(@data, *args)
170
+ end # def to_json
171
+
172
+ def to_hash
173
+ return @data
174
+ end # def to_hash
175
+
176
+ public
177
+ def overwrite(event)
178
+ @data = event.to_hash
179
+ end
180
+
181
+ public
182
+ def include?(key)
183
+ return !self[key].nil?
184
+ end # def include?
185
+
186
+ # Append an event to this one.
187
+ public
188
+ def append(event)
189
+ # non-destructively merge that event with ourselves.
190
+ LogStash::Util.hash_merge(@data, event.to_hash)
191
+ end # append
192
+
193
+ # Remove a field or field reference. Returns the value of that field when
194
+ # deleted
195
+ public
196
+ def remove(str)
197
+ return LogStash::Util::FieldReference.exec(str, @data) do |obj, key|
198
+ next obj.delete(key)
199
+ end
200
+ end # def remove
201
+
202
+ # sprintf. This could use a better method name.
203
+ # The idea is to take an event and convert it to a string based on
204
+ # any format values, delimited by %{foo} where 'foo' is a field or
205
+ # metadata member.
206
+ #
207
+ # For example, if the event has type == "foo" and source == "bar"
208
+ # then this string:
209
+ # "type is %{type} and source is %{host}"
210
+ # will return
211
+ # "type is foo and source is bar"
212
+ #
213
+ # If a %{name} value is an array, then we will join by ','
214
+ # If a %{name} value does not exist, then no substitution occurs.
215
+ #
216
+ # TODO(sissel): It is not clear what the value of a field that
217
+ # is an array (or hash?) should be. Join by comma? Something else?
218
+ public
219
+ def sprintf(format)
220
+ format = format.to_s
221
+ if format.index("%").nil?
222
+ return format
223
+ end
224
+
225
+ return format.gsub(/%\{[^}]+\}/) do |tok|
226
+ # Take the inside of the %{ ... }
227
+ key = tok[2 ... -1]
228
+
229
+ if key == "+%s"
230
+ # Got %{+%s}, support for unix epoch time
231
+ next @data["@timestamp"].to_i
232
+ elsif key[0,1] == "+"
233
+ t = @data["@timestamp"]
234
+ formatter = org.joda.time.format.DateTimeFormat.forPattern(key[1 .. -1])\
235
+ .withZone(org.joda.time.DateTimeZone::UTC)
236
+ #next org.joda.time.Instant.new(t.tv_sec * 1000 + t.tv_usec / 1000).toDateTime.toString(formatter)
237
+ # Invoke a specific Instant constructor to avoid this warning in JRuby
238
+ # > ambiguous Java methods found, using org.joda.time.Instant(long)
239
+ org.joda.time.Instant.java_class.constructor(Java::long).new_instance(
240
+ t.tv_sec * 1000 + t.tv_usec / 1000
241
+ ).to_java.toDateTime.toString(formatter)
242
+ else
243
+ value = self[key]
244
+ case value
245
+ when nil
246
+ tok # leave the %{foo} if this field does not exist in this event.
247
+ when Array
248
+ value.join(",") # Join by ',' if value is an array
249
+ when Hash
250
+ value.to_json # Convert hashes to json
251
+ else
252
+ value # otherwise return the value
253
+ end # case value
254
+ end # 'key' checking
255
+ end # format.gsub...
256
+ end # def sprintf
257
+
258
+ # Shims to remove after event v1 is the default.
259
+ def tags=(value); self["tags"] = value; end
260
+ def tags; return self["tags"]; end
261
+ def message=(value); self["message"] = value; end
262
+ def source=(value); self["source"] = value; end
263
+ def type=(value); self["type"] = value; end
264
+ def type; return self["type"]; end
265
+ def fields; return self.to_hash; end
266
+
267
+ def tag(value)
268
+ # Generalize this method for more usability
269
+ self["tags"] ||= []
270
+ self["tags"] << value unless self["tags"].include?(value)
271
+ end
272
+ end # class LogStash::Event
@@ -0,0 +1,15 @@
1
+ #$: << File.join(File.dirname(__FILE__), "..", "..", "vendor", "bundle")
2
+
3
+ module LogStash
4
+ module Inputs; end
5
+ module Outputs; end
6
+ module Filters; end
7
+ module Search; end
8
+ module Config; end
9
+ module File; end
10
+ module Web; end
11
+ module Util; end
12
+ module PluginMixins; end
13
+
14
+ SHUTDOWN = :shutdown
15
+ end # module LogStash
@@ -0,0 +1,105 @@
1
+ require "logstash/namespace"
2
+
3
+ module LogStash::Util
4
+ UNAME = case RbConfig::CONFIG["host_os"]
5
+ when /^linux/; "linux"
6
+ else; RbConfig::CONFIG["host_os"]
7
+ end
8
+
9
+ PR_SET_NAME = 15
10
+ def self.set_thread_name(name)
11
+ if RUBY_ENGINE == "jruby"
12
+ # Keep java and ruby thread names in sync.
13
+ Java::java.lang.Thread.currentThread.setName(name)
14
+ end
15
+ Thread.current[:name] = name
16
+
17
+ if UNAME == "linux"
18
+ require "logstash/util/prctl"
19
+ # prctl PR_SET_NAME allows up to 16 bytes for a process name
20
+ # since MRI 1.9, JRuby, and Rubinius use system threads for this.
21
+ LibC.prctl(PR_SET_NAME, name[0..16], 0, 0, 0)
22
+ end
23
+ end # def set_thread_name
24
+
25
+ # Merge hash 'src' into 'dst' nondestructively
26
+ #
27
+ # Duplicate keys will become array values
28
+ #
29
+ # [ src["foo"], dst["foo"] ]
30
+ def self.hash_merge(dst, src)
31
+ src.each do |name, svalue|
32
+ if dst.include?(name)
33
+ dvalue = dst[name]
34
+ if dvalue.is_a?(Hash) && svalue.is_a?(Hash)
35
+ dvalue = hash_merge(dvalue, svalue)
36
+ elsif svalue.is_a?(Array)
37
+ if dvalue.is_a?(Array)
38
+ # merge arrays without duplicates.
39
+ dvalue |= svalue
40
+ else
41
+ dvalue = [dvalue] | svalue
42
+ end
43
+ else
44
+ if dvalue.is_a?(Array)
45
+ dvalue << svalue unless dvalue.include?(svalue)
46
+ else
47
+ dvalue = [dvalue, svalue] unless dvalue == svalue
48
+ end
49
+ end
50
+
51
+ dst[name] = dvalue
52
+ else
53
+ # dst doesn't have this key, just set it.
54
+ dst[name] = svalue
55
+ end
56
+ end
57
+
58
+ return dst
59
+ end # def self.hash_merge
60
+
61
+ # Merge hash 'src' into 'dst' nondestructively
62
+ #
63
+ # Duplicate keys will become array values
64
+ # Arrays merged will simply be appended.
65
+ #
66
+ # [ src["foo"], dst["foo"] ]
67
+ def self.hash_merge_with_dups(dst, src)
68
+ src.each do |name, svalue|
69
+ if dst.include?(name)
70
+ dvalue = dst[name]
71
+ if dvalue.is_a?(Hash) && svalue.is_a?(Hash)
72
+ dvalue = hash_merge(dvalue, svalue)
73
+ elsif svalue.is_a?(Array)
74
+ if dvalue.is_a?(Array)
75
+ # merge arrays without duplicates.
76
+ dvalue += svalue
77
+ else
78
+ dvalue = [dvalue] + svalue
79
+ end
80
+ else
81
+ if dvalue.is_a?(Array)
82
+ dvalue << svalue unless dvalue.include?(svalue)
83
+ else
84
+ dvalue = [dvalue, svalue] unless dvalue == svalue
85
+ end
86
+ end
87
+
88
+ dst[name] = dvalue
89
+ else
90
+ # dst doesn't have this key, just set it.
91
+ dst[name] = svalue
92
+ end
93
+ end
94
+
95
+ return dst
96
+ end # def self.hash_merge
97
+
98
+ def self.hash_merge_many(*hashes)
99
+ dst = {}
100
+ hashes.each do |hash|
101
+ hash_merge_with_dups(dst, hash)
102
+ end
103
+ return dst
104
+ end # def hash_merge_many
105
+ end # module LogStash::Util