logstash-event - initial gem2deb package.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Wed, 12 Mar 2014 09:31:33 +0000 (10:31 +0100)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Wed, 12 Mar 2014 09:31:33 +0000 (10:31 +0100)
17 files changed:
ruby-logstash-event/LICENSE [new file with mode: 0644]
ruby-logstash-event/debian/changelog [new file with mode: 0644]
ruby-logstash-event/debian/compat [new file with mode: 0644]
ruby-logstash-event/debian/control [new file with mode: 0644]
ruby-logstash-event/debian/copyright [new file with mode: 0644]
ruby-logstash-event/debian/ruby-logstash-event.docs [new file with mode: 0644]
ruby-logstash-event/debian/ruby-tests.rb [new file with mode: 0644]
ruby-logstash-event/debian/rules [new file with mode: 0755]
ruby-logstash-event/debian/source/format [new file with mode: 0644]
ruby-logstash-event/debian/watch [new file with mode: 0644]
ruby-logstash-event/lib/logstash-event.rb [new file with mode: 0644]
ruby-logstash-event/lib/logstash/event.rb [new file with mode: 0644]
ruby-logstash-event/lib/logstash/namespace.rb [new file with mode: 0644]
ruby-logstash-event/lib/logstash/util.rb [new file with mode: 0644]
ruby-logstash-event/lib/logstash/util/fieldreference.rb [new file with mode: 0644]
ruby-logstash-event/metadata.yml [new file with mode: 0644]
ruby-logstash-event/spec/event.rb [new file with mode: 0644]

diff --git a/ruby-logstash-event/LICENSE b/ruby-logstash-event/LICENSE
new file mode 100644 (file)
index 0000000..b3e3070
--- /dev/null
@@ -0,0 +1,14 @@
+Copyright 2009-2013 Jordan Sissel, Pete Fritchman, and contributors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
diff --git a/ruby-logstash-event/debian/changelog b/ruby-logstash-event/debian/changelog
new file mode 100644 (file)
index 0000000..2483582
--- /dev/null
@@ -0,0 +1,5 @@
+ruby-logstash-event (1.2.02-1) UNRELEASED; urgency=medium
+
+  * Initial release (Closes: #nnnn)
+
+ -- MAINTAINER <valtri@myriad14.zcu.cz>  Wed, 12 Mar 2014 10:30:49 +0100
diff --git a/ruby-logstash-event/debian/compat b/ruby-logstash-event/debian/compat
new file mode 100644 (file)
index 0000000..7f8f011
--- /dev/null
@@ -0,0 +1 @@
+7
diff --git a/ruby-logstash-event/debian/control b/ruby-logstash-event/debian/control
new file mode 100644 (file)
index 0000000..2c99de4
--- /dev/null
@@ -0,0 +1,19 @@
+Source: ruby-logstash-event
+Section: ruby
+Priority: optional
+Maintainer: Debian Ruby Extras Maintainers <pkg-ruby-extras-maintainers@lists.alioth.debian.org>
+Uploaders:  <>
+Build-Depends: debhelper (>= 7.0.50~), gem2deb (>= 0.6.1~)
+Standards-Version: 3.9.4
+#Vcs-Git: git://anonscm.debian.org/pkg-ruby-extras/ruby-logstash-event.git
+#Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-ruby-extras/ruby-logstash-event.git;a=summary
+Homepage: https://github.com/logstash/logstash
+XS-Ruby-Versions: all
+
+Package: ruby-logstash-event
+Architecture: all
+XB-Ruby-Versions: ${ruby:Versions}
+Depends: ${shlibs:Depends}, ${misc:Depends}, ruby | ruby-interpreter
+# rspec (>= 0, development), guard (>= 0, development), guard-rspec (>= 0, development), insist (= 1.0.0, development)
+Description: Library that contains the classes required to create LogStash events
+ Library that contains the classes required to create LogStash events
diff --git a/ruby-logstash-event/debian/copyright b/ruby-logstash-event/debian/copyright
new file mode 100644 (file)
index 0000000..d514a3d
--- /dev/null
@@ -0,0 +1,35 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: logstash-event
+Source: FIXME <http://example.com/>
+
+Files: *
+Copyright: <years> <put author's name and email here>
+           <years> <likewise for another author>
+License: GPL-2+ (FIXME)
+
+Files: debian/*
+Copyright: 2014  <>
+License: GPL-2+ (FIXME)
+Comment: the Debian packaging is licensed under the same terms as the original package.
+
+License: GPL-2+ (FIXME)
+ This program is free software; you can redistribute it
+ and/or modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later
+ version.
+ .
+ This program is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.  See the GNU General Public License for more
+ details.
+ .
+ You should have received a copy of the GNU General Public
+ License along with this package; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA  02110-1301 USA
+ .
+ On Debian systems, the full text of the GNU General Public
+ License version 2 can be found in the file
+ `/usr/share/common-licenses/GPL-2'.
diff --git a/ruby-logstash-event/debian/ruby-logstash-event.docs b/ruby-logstash-event/debian/ruby-logstash-event.docs
new file mode 100644 (file)
index 0000000..d0ab95f
--- /dev/null
@@ -0,0 +1 @@
+# FIXME: READMEs found
diff --git a/ruby-logstash-event/debian/ruby-tests.rb b/ruby-logstash-event/debian/ruby-tests.rb
new file mode 100644 (file)
index 0000000..eac5ce6
--- /dev/null
@@ -0,0 +1,13 @@
+# FIXME
+# there's a spec/ or a test/ directory in the upstream source, but
+# no test suite was defined in the Gem specification. It would be
+# a good idea to define it here so the package gets tested at build time.
+# Examples:
+# $: << 'lib' << '.'
+# Dir['{spec,test}/**/*.rb'].each { |f| require f }
+#
+# require 'test/ts_foo.rb'
+#
+# require 'rbconfig'
+# ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
+# exec("#{ruby} -I. test/runtests.rb")
diff --git a/ruby-logstash-event/debian/rules b/ruby-logstash-event/debian/rules
new file mode 100755 (executable)
index 0000000..82ddc0c
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/make -f
+#export DH_VERBOSE=1
+#
+# Uncomment to ignore all test failures (but the tests will run anyway)
+#export DH_RUBY_IGNORE_TESTS=all
+#
+# Uncomment to ignore some test failures (but the tests will run anyway).
+# Valid values:
+#export DH_RUBY_IGNORE_TESTS=ruby1.9.1 ruby2.0 require-rubygems
+#
+# If you need to specify the .gemspec (eg there is more than one)
+#export DH_RUBY_GEMSPEC=gem.gemspec
+
+%:
+       dh $@ --buildsystem=ruby --with ruby
diff --git a/ruby-logstash-event/debian/source/format b/ruby-logstash-event/debian/source/format
new file mode 100644 (file)
index 0000000..163aaf8
--- /dev/null
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/ruby-logstash-event/debian/watch b/ruby-logstash-event/debian/watch
new file mode 100644 (file)
index 0000000..539dfcd
--- /dev/null
@@ -0,0 +1,2 @@
+version=3
+http://pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch/logstash-event .*/logstash-event-(.*).tar.gz
diff --git a/ruby-logstash-event/lib/logstash-event.rb b/ruby-logstash-event/lib/logstash-event.rb
new file mode 100644 (file)
index 0000000..6444026
--- /dev/null
@@ -0,0 +1 @@
+require "logstash/event"
diff --git a/ruby-logstash-event/lib/logstash/event.rb b/ruby-logstash-event/lib/logstash/event.rb
new file mode 100644 (file)
index 0000000..d3d2742
--- /dev/null
@@ -0,0 +1,272 @@
+require "json"
+require "time"
+require "date"
+require "logstash/namespace"
+require "logstash/util/fieldreference"
+
+# Use a custom serialization for jsonifying Time objects.
+# TODO(sissel): Put this in a separate file.
+class Time
+  def to_json(*args)
+    return iso8601(3).to_json(*args)
+  end
+
+  def inspect
+    return to_json
+  end
+end
+
+# the logstash event object.
+#
+# An event is simply a tuple of (timestamp, data).
+# The 'timestamp' is an ISO8601 timestamp. Data is anything - any message,
+# context, references, etc that are relevant to this event.
+#
+# Internally, this is represented as a hash with only two guaranteed fields.
+#
+# * "@timestamp" - an ISO8601 timestamp representing the time the event
+#   occurred at.
+# * "@version" - the version of the schema. Currently "1"
+#
+# They are prefixed with an "@" symbol to avoid clashing with your
+# own custom fields. 
+#
+# When serialized, this is represented in JSON. For example:
+#
+#     {
+#       "@timestamp": "2013-02-09T20:39:26.234Z",
+#       "@version": "1",
+#       message: "hello world"
+#     }
+class LogStash::Event
+  class DeprecatedMethod < StandardError; end
+
+  public
+  def initialize(data={})
+    @cancelled = false
+
+    @data = data
+    if data.include?("@timestamp")
+      t = data["@timestamp"]
+      if t.is_a?(String)
+        data["@timestamp"] = Time.parse(t).gmtime
+      end
+    else
+      data["@timestamp"] = ::Time.now.utc 
+    end
+    data["@version"] = "1" if !@data.include?("@version")
+  end # def initialize
+
+  # Add class methods on inclusion.
+  public
+  def self.included(klass)
+    klass.extend(ClassMethods)
+  end # def included
+
+  module ClassMethods
+    public
+    def from_json(json)
+      return self.new(JSON.parse(json))
+    end # def from_json
+  end
+
+  public
+  def cancel
+    @cancelled = true
+  end # def cancel
+
+  public
+  def uncancel
+    @cancelled = false
+  end # def uncancel
+
+  public
+  def cancelled?
+    return @cancelled
+  end # def cancelled?
+
+  # Create a deep-ish copy of this event.
+  public
+  def clone
+    copy = {}
+    @data.each do |k,v|
+      # TODO(sissel): Recurse if this is a hash/array?
+      copy[k] = v.clone
+    end
+    return self.class.new(copy)
+  end # def clone
+
+  if RUBY_ENGINE == "jruby"
+    public
+    def to_s
+      return self.sprintf("%{+yyyy-MM-dd'T'HH:mm:ss.SSSZ} %{host} %{message}")
+    end # def to_s
+  else
+    public
+    def to_s
+      return self.sprintf("#{self["@timestamp"].iso8601} %{host} %{message}")
+    end # def to_s
+  end
+
+  public
+  def timestamp; return @data["@timestamp"]; end # def timestamp
+  def timestamp=(val); return @data["@timestamp"] = val; end # def timestamp=
+
+  def unix_timestamp
+    raise DeprecatedMethod
+  end # def unix_timestamp
+
+  def ruby_timestamp
+    raise DeprecatedMethod
+  end # def unix_timestamp
+  
+  # field-related access
+  public
+  def [](str)
+    if str[0,1] == "+"
+    else
+      return LogStash::Util::FieldReference.exec(str, @data)
+    end
+  end # def []
+  
+  public
+  def []=(str, value)
+    r = LogStash::Util::FieldReference.exec(str, @data) do |obj, key|
+      obj[key] = value
+    end
+
+    # The assignment can fail if the given field reference (str) does not exist
+    # In this case, we'll want to set the value manually.
+    if r.nil?
+      # TODO(sissel): Implement this in LogStash::Util::FieldReference
+      if str[0,1] != "["
+        return @data[str] = value
+      end
+
+      # No existing element was found, so let's set one.
+      *parents, key = str.scan(/(?<=\[)[^\]]+(?=\])/)
+      obj = @data
+      parents.each do |p|
+        if obj.include?(p)
+          obj = obj[p]
+        else
+          obj[p] = {}
+          obj = obj[p]
+        end
+      end
+      obj[key] = value
+    end
+    return value
+  end # def []=
+
+  public
+  def fields
+    raise DeprecatedMethod
+  end
+  
+  public
+  def to_json(*args)
+    return @data.to_json(*args) 
+  end # def to_json
+
+  def to_hash
+    return @data
+  end # def to_hash
+
+  public
+  def overwrite(event)
+    @data = event.to_hash
+  end
+
+  public
+  def include?(key)
+    return !self[key].nil?
+  end # def include?
+
+  # Append an event to this one.
+  public
+  def append(event)
+    # non-destructively merge that event with ourselves.
+    LogStash::Util.hash_merge(@data, event.to_hash)
+  end # append
+
+  # Remove a field or field reference. Returns the value of that field when
+  # deleted
+  public
+  def remove(str)
+    return LogStash::Util::FieldReference.exec(str, @data) do |obj, key|
+      next obj.delete(key)
+    end
+  end # def remove
+
+  # sprintf. This could use a better method name.
+  # The idea is to take an event and convert it to a string based on 
+  # any format values, delimited by %{foo} where 'foo' is a field or
+  # metadata member.
+  #
+  # For example, if the event has type == "foo" and source == "bar"
+  # then this string:
+  #   "type is %{type} and source is %{host}"
+  # will return
+  #   "type is foo and source is bar"
+  #
+  # If a %{name} value is an array, then we will join by ','
+  # If a %{name} value does not exist, then no substitution occurs.
+  #
+  # TODO(sissel): It is not clear what the value of a field that 
+  # is an array (or hash?) should be. Join by comma? Something else?
+  public
+  def sprintf(format)
+    format = format.to_s
+    if format.index("%").nil?
+      return format
+    end
+
+    return format.gsub(/%\{[^}]+\}/) do |tok|
+      # Take the inside of the %{ ... }
+      key = tok[2 ... -1]
+
+      if key == "+%s"
+        # Got %{+%s}, support for unix epoch time
+        next @data["@timestamp"].to_i
+      elsif key[0,1] == "+"
+        t = @data["@timestamp"]
+        formatter = org.joda.time.format.DateTimeFormat.forPattern(key[1 .. -1])\
+          .withZone(org.joda.time.DateTimeZone::UTC)
+        #next org.joda.time.Instant.new(t.tv_sec * 1000 + t.tv_usec / 1000).toDateTime.toString(formatter)
+        # Invoke a specific Instant constructor to avoid this warning in JRuby
+        #  > ambiguous Java methods found, using org.joda.time.Instant(long)
+        org.joda.time.Instant.java_class.constructor(Java::long).new_instance(
+          t.tv_sec * 1000 + t.tv_usec / 1000
+        ).to_java.toDateTime.toString(formatter)
+      else
+        value = self[key]
+        case value
+          when nil
+            tok # leave the %{foo} if this field does not exist in this event.
+          when Array
+            value.join(",") # Join by ',' if value is an array
+          when Hash
+            value.to_json # Convert hashes to json
+          else
+            value # otherwise return the value
+        end # case value
+      end # 'key' checking
+    end # format.gsub...
+  end # def sprintf
+
+  # Shims to remove after event v1 is the default.
+  def tags=(value); self["tags"] = value; end
+  def tags; return self["tags"]; end
+  def message=(value); self["message"] = value; end
+  def source=(value); self["source"] = value; end
+  def type=(value); self["type"] = value; end
+  def type; return self["type"]; end
+  def fields; return self.to_hash; end
+
+  def tag(value)
+    # Generalize this method for more usability
+    self["tags"] ||= []
+    self["tags"] << value unless self["tags"].include?(value)
+  end
+end # class LogStash::Event
diff --git a/ruby-logstash-event/lib/logstash/namespace.rb b/ruby-logstash-event/lib/logstash/namespace.rb
new file mode 100644 (file)
index 0000000..e2f8d04
--- /dev/null
@@ -0,0 +1,15 @@
+#$: << File.join(File.dirname(__FILE__), "..", "..", "vendor", "bundle")
+
+module LogStash
+  module Inputs; end
+  module Outputs; end
+  module Filters; end
+  module Search; end
+  module Config; end
+  module File; end
+  module Web; end
+  module Util; end
+  module PluginMixins; end
+
+  SHUTDOWN = :shutdown
+end # module LogStash
diff --git a/ruby-logstash-event/lib/logstash/util.rb b/ruby-logstash-event/lib/logstash/util.rb
new file mode 100644 (file)
index 0000000..1012a4c
--- /dev/null
@@ -0,0 +1,105 @@
+require "logstash/namespace"
+
+module LogStash::Util
+  UNAME = case RbConfig::CONFIG["host_os"]
+    when /^linux/; "linux"
+    else; RbConfig::CONFIG["host_os"]
+  end
+
+  PR_SET_NAME = 15
+  def self.set_thread_name(name)
+    if RUBY_ENGINE == "jruby"
+      # Keep java and ruby thread names in sync.
+      Java::java.lang.Thread.currentThread.setName(name)
+    end
+    Thread.current[:name] = name
+    
+    if UNAME == "linux"
+      require "logstash/util/prctl"
+      # prctl PR_SET_NAME allows up to 16 bytes for a process name
+      # since MRI 1.9, JRuby, and Rubinius use system threads for this.
+      LibC.prctl(PR_SET_NAME, name[0..16], 0, 0, 0)
+    end
+  end # def set_thread_name
+
+  # Merge hash 'src' into 'dst' nondestructively
+  #
+  # Duplicate keys will become array values
+  #
+  # [ src["foo"], dst["foo"] ]
+  def self.hash_merge(dst, src)
+    src.each do |name, svalue|
+      if dst.include?(name)
+        dvalue = dst[name]
+        if dvalue.is_a?(Hash) && svalue.is_a?(Hash)
+          dvalue = hash_merge(dvalue, svalue)
+        elsif svalue.is_a?(Array) 
+          if dvalue.is_a?(Array)
+            # merge arrays without duplicates.
+            dvalue |= svalue
+          else
+            dvalue = [dvalue] | svalue
+          end
+        else
+          if dvalue.is_a?(Array)
+            dvalue << svalue unless dvalue.include?(svalue)
+          else
+            dvalue = [dvalue, svalue] unless dvalue == svalue
+          end
+        end
+
+        dst[name] = dvalue
+      else
+        # dst doesn't have this key, just set it.
+        dst[name] = svalue
+      end
+    end
+
+    return dst
+  end # def self.hash_merge
+  # Merge hash 'src' into 'dst' nondestructively
+  #
+  # Duplicate keys will become array values
+  # Arrays merged will simply be appended.
+  #
+  # [ src["foo"], dst["foo"] ]
+  def self.hash_merge_with_dups(dst, src)
+    src.each do |name, svalue|
+      if dst.include?(name)
+        dvalue = dst[name]
+        if dvalue.is_a?(Hash) && svalue.is_a?(Hash)
+          dvalue = hash_merge(dvalue, svalue)
+        elsif svalue.is_a?(Array) 
+          if dvalue.is_a?(Array)
+            # merge arrays without duplicates.
+            dvalue += svalue
+          else
+            dvalue = [dvalue] + svalue
+          end
+        else
+          if dvalue.is_a?(Array)
+            dvalue << svalue unless dvalue.include?(svalue)
+          else
+            dvalue = [dvalue, svalue] unless dvalue == svalue
+          end
+        end
+
+        dst[name] = dvalue
+      else
+        # dst doesn't have this key, just set it.
+        dst[name] = svalue
+      end
+    end
+
+    return dst
+  end # def self.hash_merge
+
+  def self.hash_merge_many(*hashes)
+    dst = {}
+    hashes.each do |hash|
+      hash_merge_with_dups(dst, hash)
+    end
+    return dst
+  end # def hash_merge_many
+end # module LogStash::Util
diff --git a/ruby-logstash-event/lib/logstash/util/fieldreference.rb b/ruby-logstash-event/lib/logstash/util/fieldreference.rb
new file mode 100644 (file)
index 0000000..b826a4b
--- /dev/null
@@ -0,0 +1,49 @@
+require "logstash/namespace"
+require "logstash/util"
+
+module LogStash::Util::FieldReference
+  def compile(str)
+    if str[0,1] != '['
+      return <<-"CODE"
+        lambda do |e, &block|
+          return block.call(e, #{str.inspect}) unless block.nil?
+          return e[#{str.inspect}]
+        end
+      CODE
+    end
+
+    code = "lambda do |e, &block|\n"
+    selectors = str.scan(/(?<=\[).+?(?=\])/)
+    selectors.each_with_index do |tok, i|
+      last = (i == selectors.count() - 1)
+      code << "   # [#{tok}]#{ last ? " (last selector)" : "" }\n"
+     
+      if last
+        code << <<-"CODE"
+          return block.call(e, #{tok.inspect}) unless block.nil?
+        CODE
+      end
+
+      code << <<-"CODE"
+        if e.is_a?(Array)
+          e = e[#{tok.to_i}]
+        else
+          e = e[#{tok.inspect}]
+        end
+        return e if e.nil?
+      CODE
+      
+    end
+    code << "return e\nend"
+    #puts code
+    return code
+  end # def compile
+
+  def exec(str, obj, &block)
+    @__fieldeval_cache ||= {}
+    @__fieldeval_cache[str] ||= eval(compile(str))
+    return @__fieldeval_cache[str].call(obj, &block)
+  end
+
+  extend self
+end # module LogStash::Util::FieldReference
diff --git a/ruby-logstash-event/metadata.yml b/ruby-logstash-event/metadata.yml
new file mode 100644 (file)
index 0000000..6ebe83b
--- /dev/null
@@ -0,0 +1,117 @@
+--- !ruby/object:Gem::Specification
+name: logstash-event
+version: !ruby/object:Gem::Version
+  version: 1.2.02
+  prerelease: 
+platform: ruby
+authors:
+- Jordan Sissel
+autorequire: 
+bindir: bin
+cert_chain: []
+date: 2013-09-11 00:00:00.000000000 Z
+dependencies:
+- !ruby/object:Gem::Dependency
+  name: rspec
+  requirement: !ruby/object:Gem::Requirement
+    none: false
+    requirements:
+    - - ! '>='
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    none: false
+    requirements:
+    - - ! '>='
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: guard
+  requirement: !ruby/object:Gem::Requirement
+    none: false
+    requirements:
+    - - ! '>='
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    none: false
+    requirements:
+    - - ! '>='
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: guard-rspec
+  requirement: !ruby/object:Gem::Requirement
+    none: false
+    requirements:
+    - - ! '>='
+      - !ruby/object:Gem::Version
+        version: '0'
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    none: false
+    requirements:
+    - - ! '>='
+      - !ruby/object:Gem::Version
+        version: '0'
+- !ruby/object:Gem::Dependency
+  name: insist
+  requirement: !ruby/object:Gem::Requirement
+    none: false
+    requirements:
+    - - '='
+      - !ruby/object:Gem::Version
+        version: 1.0.0
+  type: :development
+  prerelease: false
+  version_requirements: !ruby/object:Gem::Requirement
+    none: false
+    requirements:
+    - - '='
+      - !ruby/object:Gem::Version
+        version: 1.0.0
+description: Library that contains the classes required to create LogStash events
+email:
+- jls@semicomplete.com
+executables: []
+extensions: []
+extra_rdoc_files: []
+files:
+- lib/logstash-event.rb
+- lib/logstash/event.rb
+- lib/logstash/namespace.rb
+- lib/logstash/util/fieldreference.rb
+- lib/logstash/util.rb
+- spec/event.rb
+- LICENSE
+homepage: https://github.com/logstash/logstash
+licenses:
+- Apache License (2.0)
+post_install_message: 
+rdoc_options: []
+require_paths:
+- lib
+required_ruby_version: !ruby/object:Gem::Requirement
+  none: false
+  requirements:
+  - - ! '>='
+    - !ruby/object:Gem::Version
+      version: '0'
+required_rubygems_version: !ruby/object:Gem::Requirement
+  none: false
+  requirements:
+  - - ! '>='
+    - !ruby/object:Gem::Version
+      version: '0'
+requirements: []
+rubyforge_project: 
+rubygems_version: 1.8.25
+signing_key: 
+specification_version: 3
+summary: Library that contains the classes required to create LogStash events
+test_files: []
diff --git a/ruby-logstash-event/spec/event.rb b/ruby-logstash-event/spec/event.rb
new file mode 100644 (file)
index 0000000..4fd775a
--- /dev/null
@@ -0,0 +1,139 @@
+require "logstash/event"
+require "insist"
+
+describe LogStash::Event do
+  subject do
+    LogStash::Event.new(
+      "@timestamp" => Time.iso8601("2013-01-01T00:00:00.000Z"),
+      "type" => "sprintf",
+      "message" => "hello world",
+      "tags" => [ "tag1" ],
+      "source" => "/home/foo",
+      "a" => "b", 
+      "c" => {
+        "d" => "f",
+        "e" => {"f" => "g"}
+      }, 
+      "f" => { "g" => { "h" => "i" } },
+      "j" => { 
+          "k1" => "v", 
+          "k2" => [ "w", "x" ],
+          "k3" => {"4" => "m"},
+          5 => 6,
+          "5" => 7
+      } 
+    )
+  end
+
+  context "#sprintf" do
+    it "should report a unix timestamp for %{+%s}" do
+      insist { subject.sprintf("%{+%s}") } == "1356998400"
+    end
+    
+    it "should report a time with %{+format} syntax", :if => RUBY_ENGINE == "jruby" do
+      insist { subject.sprintf("%{+YYYY}") } == "2013"
+      insist { subject.sprintf("%{+MM}") } == "01"
+      insist { subject.sprintf("%{+HH}") } == "00"
+    end
+  
+    it "should report fields with %{field} syntax" do
+      insist { subject.sprintf("%{type}") } == "sprintf"
+      insist { subject.sprintf("%{message}") } == subject["message"]
+    end
+    
+    it "should print deep fields" do
+      insist { subject.sprintf("%{[j][k1]}") } == "v"
+      insist { subject.sprintf("%{[j][k2][0]}") } == "w"
+    end
+
+    it "should be able to take a non-string for the format" do
+      insist { subject.sprintf(2) } == "2"
+    end
+  end
+  
+  context "#[]" do
+    it "should fetch data" do
+      insist { subject["type"] } == "sprintf"
+    end
+    it "should fetch fields" do
+      insist { subject["a"] } == "b"
+      insist { subject['c']['d'] } == "f"
+    end
+    it "should fetch deep fields" do
+      insist { subject["[j][k1]"] } == "v"
+      insist { subject["[c][d]"] } == "f"
+      insist { subject['[f][g][h]'] } == "i"
+      insist { subject['[j][k3][4]'] } == "m"
+      insist { subject['[j][5]'] } == 7
+
+    end
+
+    it "should be fast?", :if => ENV["SPEEDTEST"] do
+      2.times do
+        start = Time.now
+        100000.times { subject["[j][k1]"] }
+        puts "Duration: #{Time.now - start}"
+      end
+    end
+  end
+
+  context "#append" do
+    it "should append strings to an array" do
+      subject.append(LogStash::Event.new("message" => "another thing"))
+      insist { subject["message"] } == [ "hello world", "another thing" ]
+    end
+  
+    it "should concatenate tags" do
+      subject.append(LogStash::Event.new("tags" => [ "tag2" ]))
+      insist { subject["tags"] } == [ "tag1", "tag2" ]
+    end
+  
+    context "when event field is nil" do
+      it "should add single value as string" do
+        subject.append(LogStash::Event.new({"field1" => "append1"}))
+        insist { subject[ "field1" ] } == "append1"
+      end
+      it "should add multi values as array" do
+        subject.append(LogStash::Event.new({"field1" => [ "append1","append2" ]}))
+        insist { subject[ "field1" ] } == [ "append1","append2" ]
+      end
+    end
+  
+    context "when event field is a string" do
+      before { subject[ "field1" ] = "original1" }
+  
+      it "should append string to values, if different from current" do
+        subject.append(LogStash::Event.new({"field1" => "append1"}))
+        insist { subject[ "field1" ] } == [ "original1", "append1" ]
+      end
+      it "should not change value, if appended value is equal current" do
+        subject.append(LogStash::Event.new({"field1" => "original1"}))
+        insist { subject[ "field1" ] } == "original1"
+      end
+      it "should concatenate values in an array" do
+        subject.append(LogStash::Event.new({"field1" => [ "append1" ]}))
+        insist { subject[ "field1" ] } == [ "original1", "append1" ]
+      end
+      it "should join array, removing duplicates" do
+        subject.append(LogStash::Event.new({"field1" => [ "append1","original1" ]}))
+        insist { subject[ "field1" ] } == [ "original1", "append1" ]
+      end
+    end
+    context "when event field is an array" do
+      before { subject[ "field1" ] = [ "original1", "original2" ] }
+  
+      it "should append string values to array, if not present in array" do
+        subject.append(LogStash::Event.new({"field1" => "append1"}))
+        insist { subject[ "field1" ] } == [ "original1", "original2", "append1" ]
+      end
+      it "should not append string values, if the array already contains it" do
+        subject.append(LogStash::Event.new({"field1" => "original1"}))
+        insist { subject[ "field1" ] } == [ "original1", "original2" ]
+      end
+      it "should join array, removing duplicates" do
+        subject.append(LogStash::Event.new({"field1" => [ "append1","original1" ]}))
+        insist { subject[ "field1" ] } == [ "original1", "original2", "append1" ]
+      end
+    end
+  end
+end