elasticelmah 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/elasticelmah.rb +131 -0
  2. data/tests/elasticelmah_tests.rb +129 -0
  3. metadata +113 -0
@@ -0,0 +1,131 @@
1
+ require 'elasticsearch'
2
+ require 'log4r'
3
+ require 'time'
4
+ module ElasticElmah
5
+
6
+ class Outputter < Log4r::Outputter
7
+ attr_reader :log
8
+ def initialize(_name, hash={})
9
+ super(_name, hash)
10
+ @index = "logs"
11
+
12
+ @index = hash[:index] if hash.has_key?(:index)
13
+ @closed = false
14
+ @initialized = false
15
+ @client = Elasticsearch::Client.new #log: true
16
+ end
17
+
18
+ def time_now
19
+ Time.now.utc
20
+ end
21
+ def time_stamp
22
+ time_now.strftime('%Y-%m-%dT%H:%M:%S.%7N%:z') #"0001-01-01T00:00:00.0 00 000 0+01:00"
23
+ end
24
+
25
+ def closed?
26
+ @closed
27
+ end
28
+
29
+ def close
30
+ @closed = true
31
+ @level = OFF
32
+ OutputterFactory.create_methods(self)
33
+ Logger.log_internal {"Outputter '#{@name}' closed and set to OFF"}
34
+ end
35
+
36
+ def serialize(l)
37
+ # attr_reader :level, :tracer, :data, :name, :fullname
38
+ # [level] The integer level of the log event. Use LNAMES[level]
39
+ # to get the actual level name.
40
+ # [tracer] The execution stack returned by <tt>caller</tt> at the
41
+ # log event. It is nil if the invoked Logger's trace is false.
42
+ # [data] The object that was passed into the logging method.
43
+ # [name] The name of the logger that was invoked.
44
+ # [fullname] The fully qualified name of the logger that was invoked.
45
+ return {
46
+ loggerName:l.name,
47
+ level: Log4r::LNAMES[l.level],
48
+ message: l.data != nil && l.data.respond_to?(:message) ? l.data.message : l.data,
49
+ threadName:"",
50
+ timeStamp:time_stamp,
51
+ locationInfo:{
52
+ className:"?",
53
+ fileName:"?",
54
+ lineNumber:"?",
55
+ methodName:"?"
56
+ },
57
+ userName:"",
58
+ properties:{},
59
+ exceptionString: l.tracer!=nil ? l.tracer.join("\n") : "",
60
+ domain:"",
61
+ identity:""
62
+ }
63
+ end
64
+
65
+ #######
66
+ private
67
+ #######
68
+ def create_index
69
+ @client.indices.create(index: @index, body: {
70
+ settings: {
71
+ index: { number_of_shards: 1, number_of_replicas: 0 }
72
+ },
73
+ mappings:{
74
+ "LoggingEvent" => logging_event_mappings
75
+ }
76
+ })
77
+ #@client.indices.put_mapping(index: @index, type: 'LoggingEvent', body: logging_event_mappings)
78
+ end
79
+ def logging_event_mappings
80
+ {
81
+ _source: {
82
+ enabled: true,
83
+ compress: false
84
+ },
85
+ _ttl: {
86
+ enabled: true,
87
+ default: "24d"
88
+ },
89
+ _timestamp: {
90
+ enabled: true,
91
+ path: "timeStamp",
92
+ store: true
93
+ },
94
+ properties: {
95
+ timeStamp: {
96
+ type: "date"
97
+ },
98
+ message:{type: "string"},
99
+ exceptionString:{type: "string"},
100
+ domain:{type: "string"},
101
+ identity:{type: "string"},
102
+ userName: {type: "string"},
103
+ locationInfo:{
104
+ type: "object",
105
+ properties: {
106
+ className:{type: "string"},
107
+ fileName:{type: "string"},
108
+ lineNumber:{type: "string"},
109
+ methodName:{type: "string"}
110
+ }
111
+ },
112
+ threadName:{type: "string"},
113
+ loggerName:{type: "string"},
114
+ level:{type:"string"},
115
+ properties:{ type: "object", store: "yes" }
116
+ }
117
+ }
118
+ end
119
+
120
+ # perform the write
121
+ def canonical_log(logevent)
122
+ if !@initialized
123
+ @initialized= true
124
+ if !@client.indices.exists(index: @index)
125
+ create_index
126
+ end
127
+ end
128
+ @client.index index: @index, type: 'LoggingEvent', body: serialize(logevent)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,129 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'elasticelmah'
4
+ require 'test/unit'
5
+ require 'securerandom'
6
+ class OutputterWithFakedElastic < ElasticElmah::Outputter
7
+ attr_reader :written
8
+ def initialize(_name, hash={})
9
+ super(_name, hash)
10
+ @written = []
11
+ end
12
+
13
+ private
14
+ def canonical_log(logevent)
15
+ @written.push(logevent)
16
+ end
17
+ end
18
+
19
+ class OutputterWithFakedElasticAndTimestamp < OutputterWithFakedElastic
20
+ def initialize(_name, hash={})
21
+ super(_name, hash)
22
+ @written = []
23
+ end
24
+ def time_now
25
+ Time.new(2008,6,21, 12,30,0, "+01:00")
26
+ end
27
+ end
28
+
29
+ class TestElasticElmahOutputterForReal < Test::Unit::TestCase
30
+ def setup
31
+ Log4r::Logger.root.level = Log4r::INFO
32
+ @logger = Log4r::Logger.new 'testout_for_real'
33
+ @index = SecureRandom.uuid
34
+ @outp = ElasticElmah::Outputter.new 'outp_for_real',{index: @index}
35
+ @logger.add('outp_for_real')
36
+ @client = Elasticsearch::Client.new# log: true
37
+ end
38
+ def teardown
39
+ @client.indices.delete(index: @index)
40
+ end
41
+
42
+ def test_generated_from_logging_event_data
43
+ @logger.error('some_error')
44
+ @client.indices.flush(index: @index )
45
+ result = @client.search index: @index
46
+ assert_equal 1, result["hits"]["hits"].length
47
+ hits = result["hits"]["hits"]
48
+ assert_equal 'some_error', hits[0]["_source"]["message"]
49
+ end
50
+ end
51
+
52
+
53
+ class TestElasticElmahOutputter < Test::Unit::TestCase
54
+ def setup
55
+ Log4r::Logger.root.level = Log4r::INFO
56
+ @logger = Log4r::Logger.new 'testoutp'
57
+
58
+ @outp = OutputterWithFakedElasticAndTimestamp.new 'outp1'
59
+ @logger.add('outp1')
60
+ end
61
+
62
+ def test_generated_from_logging_event_data
63
+ @logger.error('some_error')
64
+ assert_equal([{:loggerName=>"testoutp",
65
+ :level=>"ERROR",
66
+ :message=>"some_error",
67
+ :threadName=>"",
68
+ :timeStamp=>"2008-06-21T12:30:00.0000000+01:00",
69
+ :locationInfo=>
70
+ {:className=>"?", :fileName=>"?", :lineNumber=>"?", :methodName=>"?"},
71
+ :userName=>"",
72
+ :properties=>{},
73
+ :exceptionString=>"",
74
+ :domain=>"",
75
+ :identity=>""}],
76
+ @outp.written.map do |written| @outp.serialize(written) end)
77
+ end
78
+ end
79
+
80
+ class FakeLogger
81
+ attr_reader :name, :fullname
82
+ def initialize(name,fullname)
83
+ @name = name
84
+ @fullname = fullname
85
+ end
86
+ end
87
+
88
+ class TestElasticElmahSerializer < Test::Unit::TestCase
89
+ def setup
90
+ @outp = OutputterWithFakedElasticAndTimestamp.new 'outp2'
91
+ end
92
+
93
+
94
+ def test_will_serialize_exception_string
95
+ logger = FakeLogger.new('logger_1', 'fullname_of_logger_1')
96
+ tracer = caller
97
+ data = Exception.new("Message")
98
+ l = Log4r::LogEvent.new(Log4r::INFO, logger, tracer, data)
99
+ s = @outp.serialize(l)
100
+ assert_equal("Message",s[:message])
101
+ assert_equal(caller.join("\n"),s[:exceptionString])
102
+ end
103
+
104
+ def test_will_serialize_exception_without_exception_string
105
+ expected = {
106
+ loggerName:"logger_1",
107
+ level:"INFO",
108
+ message:"Message",
109
+ threadName:"",
110
+ timeStamp:"2008-06-21T12:30:00.0000000+01:00",
111
+ locationInfo:{
112
+ className:"?",
113
+ fileName:"?",
114
+ lineNumber:"?",
115
+ methodName:"?"
116
+ },
117
+ userName:"",
118
+ properties:{},
119
+ exceptionString:"",
120
+ domain:"",
121
+ identity:""
122
+ }
123
+ logger = FakeLogger.new('logger_1', 'fullname_of_logger_1')
124
+ tracer = nil
125
+ data = Exception.new("Message")
126
+ l = Log4r::LogEvent.new(Log4r::INFO, logger, tracer, data)
127
+ assert_equal(expected, @outp.serialize(l))
128
+ end
129
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elasticelmah
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Oskar Gewalli
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-02-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: elasticsearch
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: log4r
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: ! 'An appender for log4r that appends to elastic search
79
+
80
+ '
81
+ email: ''
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - lib/elasticelmah.rb
87
+ - tests/elasticelmah_tests.rb
88
+ homepage:
89
+ licenses: []
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 1.8.24
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: ElasticSearch log4r appender
112
+ test_files:
113
+ - tests/elasticelmah_tests.rb