sentry_fs 0.6

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6a7385144932acf7cdd009fbb6713e7527cb67d2
4
+ data.tar.gz: 347b2e26ade28383bc1ae89c9ac46dce2d178eed
5
+ SHA512:
6
+ metadata.gz: 07050064749397a234c45643b51f0b9f99139fa4d67d21380cce86bf317a7e6b78eceddf899cf3fbf55ab633fc9416d96a6f90f569ff50f0d814e5e2a5396411
7
+ data.tar.gz: 5f7d27f2ed638e61440972f73179cf82ee4b15401482f83671ef276361797f4f9ccd2e89d00e215494d7fb0c5d0cf734de03913faa8e2201d05b34a7049aa2c0
data/bin/sentry_fs ADDED
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "optparse"
4
+ require "logger"
5
+ require "raven"
6
+ require "file/tail"
7
+ require "sentry_fs"
8
+
9
+ logger = Logger.new(STDOUT)
10
+ options = {}
11
+
12
+ OptionParser.new do |opts|
13
+ opts.banner = "Usage: sentry_fs [options]"
14
+
15
+ opts.on("--fslog PATH", "PATH to FreeSWITCH log") {|path|
16
+ options[:fs_log] = path
17
+ }
18
+
19
+ opts.on("--dsn DSN", "Sentry DSN") {|dsn|
20
+ options[:dsn] = dsn
21
+ }
22
+
23
+ opts.on("--log PATH", "PATH to sentry_fs log") {|path|
24
+ logger = Logger.new(path)
25
+ }
26
+
27
+ opts.on("--daemon", "Run in background") {|daemon|
28
+ options[:daemon] = daemon
29
+ }
30
+
31
+ opts.on("--pidfile PATH", "PATH to pidfile") {|path|
32
+ options[:pidfile] = path
33
+ }
34
+ end.parse!
35
+
36
+ if !options[:fs_log]
37
+ $stderr.puts "--fslog required"
38
+ exit 1
39
+ end
40
+
41
+ if !options[:dsn]
42
+ $stderr.puts "--dsn required"
43
+ exit 2
44
+ end
45
+
46
+ if !File.exists?(options[:fs_log])
47
+ $stderr.puts "#{options[:fs_log]} does not exist"
48
+ exit 3
49
+ end
50
+
51
+ if options[:daemon]
52
+ Process.daemon(nochdir=true)
53
+ end
54
+
55
+ if options[:pidfile]
56
+ File.open(options[:pidfile], "w") {|f| f.write(Process.pid)}
57
+ end
58
+
59
+ Raven.configure do |config|
60
+ config.dsn = options[:dsn]
61
+ config.logger = logger
62
+ config.current_environment = "production"
63
+ end
64
+
65
+ File.open(options[:fs_log]) do |log|
66
+ log.extend(File::Tail)
67
+ log.interval = 10
68
+ log.backward 0
69
+ log.tail {|line|
70
+ begin
71
+ event = SentryFS.parse(line)
72
+ SentryFS.capture(event) if event
73
+ rescue => e
74
+ logger.error line
75
+ logger.error e.message
76
+ logger.error e.backtrace
77
+ end
78
+ }
79
+ end
data/lib/sentry_fs.rb ADDED
@@ -0,0 +1,64 @@
1
+ require "json"
2
+
3
+ module SentryFS
4
+ class Event
5
+ attr_reader :uuid
6
+ attr_reader :message
7
+ attr_reader :extra
8
+ attr_reader :full_message
9
+ attr_reader :level
10
+
11
+ def initialize(uuid:, message:, extra: {}, full_message: nil, level: "err")
12
+ @uuid = uuid
13
+ @message = message
14
+ @extra = extra
15
+ @full_message = full_message
16
+ @level = level
17
+ end
18
+ end
19
+
20
+ EXPRESSIONS = {
21
+ global: /\A\S+ \S+ \[(?<level>WARNING|ALERT|CRIT|ERR)\] (?<line>\S+) (?<message>.*)\z/,
22
+ session: /\A(?<uuid>\S+) \S+ \S+ \[(?<level>WARNING|ALERT|CRIT|ERR)\] (?<line>\S+) (?<message>.*)\z/,
23
+ odbc: /\A(?<message>.*CODE.*ERROR.*)\z/
24
+ }
25
+
26
+ def self.parse(log_line)
27
+ log_line.chomp!
28
+ EXPRESSIONS.each {|name, regexp|
29
+ match = log_line.match(regexp)
30
+ if match
31
+ uuid = match.names.include?("uuid") ? match[:uuid] : nil
32
+ line = match.names.include?("line") ? match[:line] : nil
33
+ level = match.names.include?("level") ? match[:level].downcase : "err"
34
+ begin
35
+ json = JSON.parse(match[:message])
36
+ message = json["message"]
37
+ extra = json["extra"]
38
+ rescue JSON::ParserError
39
+ message = [line, match[:message]].compact.join(" ")
40
+ extra = {}
41
+ end
42
+ event = Event.new(
43
+ uuid: uuid,
44
+ message: message,
45
+ full_message: log_line,
46
+ extra: extra,
47
+ level: level
48
+ )
49
+ return event
50
+ end
51
+ }
52
+ nil
53
+ end
54
+
55
+ def self.capture(event)
56
+ Raven.capture_message(event.message, {
57
+ level: event.level,
58
+ extra: {
59
+ uuid: event.uuid,
60
+ full_message: event.full_message
61
+ }.merge(event.extra)
62
+ })
63
+ end
64
+ end
data/sentry_fs.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "sentry_fs"
3
+ s.version = "0.6"
4
+ s.date = "2015-10-21"
5
+ s.summary = "Parse FreeSWITCH logs and report errors to Sentry"
6
+ s.email = "hv@firmafon.dk"
7
+ s.homepage = "http://github.com/firmafon/sentry_fs"
8
+ s.description = "Parse FreeSWITCH logs and report errors to Sentry"
9
+ s.authors = ["Harry Vangberg"]
10
+ s.executables = ["sentry_fs"]
11
+ s.files = [
12
+ "sentry_fs.gemspec",
13
+ "lib/sentry_fs.rb",
14
+ "bin/sentry_fs"
15
+ ]
16
+ s.test_files = [
17
+ "test/test_helper.rb",
18
+ "test/unit/test_sentry_fs.rb"
19
+ ]
20
+ s.add_dependency "file-tail", "~> 1.0"
21
+ s.add_dependency "sentry-raven", "~> 0.14.0"
22
+ s.add_dependency "json"
23
+ end
@@ -0,0 +1,2 @@
1
+ require "minitest/autorun"
2
+ require "sentry_fs"
@@ -0,0 +1,83 @@
1
+ require "test_helper"
2
+
3
+ class TestSentryFS < MiniTest::Unit::TestCase
4
+ LOG_LEVELS = %w(WARNING ALERT CRIT ERR)
5
+
6
+ LOG_LEVELS.each do |level|
7
+ define_method(:"test_parse_global_#{level}") do
8
+ log = "2013-03-19 10:41:53.556663 [#{level}] mod_db.c:117 Error Opening DB\n"
9
+ event = SentryFS.parse(log)
10
+
11
+ assert_nil event.uuid
12
+ assert_equal "mod_db.c:117 Error Opening DB", event.message
13
+ assert_equal log, event.full_message
14
+ assert_equal level.downcase, event.level
15
+ end
16
+ end
17
+
18
+ LOG_LEVELS.each do |level|
19
+ define_method(:"test_parse_session_#{level}") do
20
+ log = "447d3058-90be-11e2-906b-d954932e9cdf 2013-03-19 10:56:04.307690 [#{level}] mod_sofia.c:4224 Invalid Gateway\n"
21
+ event = SentryFS.parse(log)
22
+
23
+ assert_equal "447d3058-90be-11e2-906b-d954932e9cdf", event.uuid
24
+ assert_equal "mod_sofia.c:4224 Invalid Gateway", event.message
25
+ assert_equal log, event.full_message
26
+ assert_equal level.downcase, event.level
27
+ end
28
+ end
29
+
30
+ def test_parse_global_json_error
31
+ log = '2013-03-19 10:41:53.556663 [ERR] utils.js:123 {"message":"error 123", "extra": {"some_var":"some_data"}}' + "\n"
32
+ event = SentryFS.parse(log)
33
+
34
+ assert_nil event.uuid
35
+ assert_equal "error 123", event.message
36
+ assert_equal log, event.full_message
37
+ assert_equal({"some_var" => "some_data"}, event.extra)
38
+ assert_equal "err", event.level
39
+ end
40
+
41
+ def test_parse_session_json_error
42
+ log = '447d3058-90be-11e2-906b-d954932e9cdf 2013-03-19 10:56:04.307690 [ERR] utils.js:123 {"message":"error 123", "extra":{"some_var":"some_data"}}' + "\n"
43
+ event = SentryFS.parse(log)
44
+
45
+ assert_equal "447d3058-90be-11e2-906b-d954932e9cdf", event.uuid
46
+ assert_equal "error 123", event.message
47
+ assert_equal log, event.full_message
48
+ assert_equal({"some_var" => "some_data"}, event.extra)
49
+ assert_equal "err", event.level
50
+ end
51
+
52
+ def test_parse_odbc_error_without_timestamp
53
+ log = "[STATE: 42S22 CODE 1054 ERROR: [unixODBC][MySQL][ODBC 3.51 Driver][mysqld-5.1.39-ndb-7.0.9-1ubuntu7]Unknown column 'undefined' in 'where clause'\n"
54
+
55
+ event = SentryFS.parse(log)
56
+
57
+ assert_nil event.uuid
58
+ assert_equal log, event.message
59
+ assert_equal log, event.full_message
60
+ assert_equal "err", event.level
61
+ end
62
+
63
+ def test_parse_odbc_error_with_timestamp
64
+ log = "2013-04-24 07:28:09.347700 [ERR] switch_core_sqldb.c:476 SQL ERR [STATE: HY000 CODE 1205 ERROR: [unixODBC][MySQL][ODBC 3.51 Driver][mysqld-5.1.39-ndb-7.0.9-1ubuntu7]Lock wait timeout exceeded; try restarting transaction\n"
65
+
66
+ event = SentryFS.parse(log)
67
+
68
+ message = "switch_core_sqldb.c:476 SQL ERR [STATE: HY000 CODE 1205 ERROR: [unixODBC][MySQL][ODBC 3.51 Driver][mysqld-5.1.39-ndb-7.0.9-1ubuntu7]Lock wait timeout exceeded; try restarting transaction"
69
+
70
+ assert_nil event.uuid
71
+ assert_equal message, event.message
72
+ assert_equal log, event.full_message
73
+ assert_equal "err", event.level
74
+ end
75
+
76
+ def test_parse_something_else
77
+ log = "0ea0aa02-acd2-11e2-87e3-2f16ea487161 EXECUTE sofia/external/22334455@192.168.90.1 javascript(voicemail.js 4571992020)\n"
78
+
79
+ event = SentryFS.parse(log)
80
+
81
+ assert_nil event
82
+ end
83
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sentry_fs
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.6'
5
+ platform: ruby
6
+ authors:
7
+ - Harry Vangberg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: file-tail
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sentry-raven
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.14.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.14.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Parse FreeSWITCH logs and report errors to Sentry
56
+ email: hv@firmafon.dk
57
+ executables:
58
+ - sentry_fs
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - bin/sentry_fs
63
+ - lib/sentry_fs.rb
64
+ - sentry_fs.gemspec
65
+ - test/test_helper.rb
66
+ - test/unit/test_sentry_fs.rb
67
+ homepage: http://github.com/firmafon/sentry_fs
68
+ licenses: []
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.4.5
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Parse FreeSWITCH logs and report errors to Sentry
90
+ test_files:
91
+ - test/test_helper.rb
92
+ - test/unit/test_sentry_fs.rb
93
+ has_rdoc: