sentry_breakpad 0.1.0
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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/sentry_breakpad/breakpad_parser.rb +318 -0
- data/lib/sentry_breakpad/version.rb +3 -0
- data/lib/sentry_breakpad.rb +22 -0
- data/sentry_breakpad.gemspec +24 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c7921ceaf17f0f3529ab2337bb347cd0c0b6923d
|
4
|
+
data.tar.gz: 729a4142ef71e60beea9a90fa8994def7931d3a2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4808f54bef2fc2d1d4d6640ea339553f627e2a8ea7c97584c943a2d42a2e5eb875f5e633da22d795c590407a47fadbbfaba5410906a2cfe693fc79461e6815d4
|
7
|
+
data.tar.gz: dd264b5313a9a23f56793e04f939fac896216eef7d2f41806ac4f67f8385255991db7904916f0f96ddc9a7b5a825fb5ce7656842d50f8912632394c8a1d4eafe
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Jean Rouge
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# SentryBreakpad
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sentry_breakpad`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'sentry_breakpad'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install sentry_breakpad
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/sentry_breakpad.
|
36
|
+
|
37
|
+
|
38
|
+
## License
|
39
|
+
|
40
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
41
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "sentry_breakpad"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
require 'raven'
|
2
|
+
|
3
|
+
module SentryBreakpad
|
4
|
+
# parses a breakpad report
|
5
|
+
class BreakpadParser
|
6
|
+
def self.from_file(file_path)
|
7
|
+
new(File.open(file_path).read)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(breakpad_report_content)
|
11
|
+
@breakpad_report_content = breakpad_report_content
|
12
|
+
@parsed = false
|
13
|
+
|
14
|
+
@message = nil
|
15
|
+
@tags = {}
|
16
|
+
@crashed_thread_stacktrace = []
|
17
|
+
@culprit = nil
|
18
|
+
@modules = {}
|
19
|
+
@extra = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def raven_event(extra_info = {}, include_whole_report = true)
|
23
|
+
hash = deep_merge(raven_event_hash(include_whole_report), extra_info)
|
24
|
+
|
25
|
+
Raven::Event.new(hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
def raven_event_hash(include_whole_report = true)
|
29
|
+
parse
|
30
|
+
|
31
|
+
extra = if include_whole_report
|
32
|
+
@extra.merge({'raw_breakpad_report' => @breakpad_report_content})
|
33
|
+
else
|
34
|
+
@extra
|
35
|
+
end
|
36
|
+
|
37
|
+
{
|
38
|
+
'message' => @message,
|
39
|
+
'tags' => @tags,
|
40
|
+
'culprit' => @culprit,
|
41
|
+
'modules' => @modules,
|
42
|
+
'extra' => extra,
|
43
|
+
'level' => 'fatal',
|
44
|
+
'logger' => 'breakpad',
|
45
|
+
'platform' => 'c',
|
46
|
+
'interfaces' => {
|
47
|
+
'stacktrace' => @crashed_thread_stacktrace
|
48
|
+
}
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def parse
|
55
|
+
return if @parsed
|
56
|
+
|
57
|
+
parse_lines(@breakpad_report_content.split("\n").reverse!)
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_lines(lines)
|
61
|
+
until lines.empty?
|
62
|
+
case lines.last
|
63
|
+
when /^Operating system:/
|
64
|
+
parse_operating_system(lines)
|
65
|
+
when /^CPU: /
|
66
|
+
parse_cpu(lines)
|
67
|
+
when /^Crash reason:/
|
68
|
+
parse_crash_reason(lines.pop)
|
69
|
+
when /^Crash address:/
|
70
|
+
parse_crash_address(lines.pop)
|
71
|
+
when /^Thread ([0-9]+) \(crashed\)/
|
72
|
+
parse_crashed_thread_stacktrace(lines, $1.to_i)
|
73
|
+
when /^Loaded modules:/
|
74
|
+
parse_loaded_modules(lines)
|
75
|
+
else
|
76
|
+
lines.pop
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Parses something of the form
|
82
|
+
# Operating system: Windows NT
|
83
|
+
# 6.1.7601 Service Pack 1
|
84
|
+
def parse_operating_system(lines)
|
85
|
+
parse_indented_section(lines, 'Operating system:', 'os')
|
86
|
+
end
|
87
|
+
|
88
|
+
# Parses something of the form
|
89
|
+
# CPU: x86
|
90
|
+
# GenuineIntel family 6 model 70 stepping 1
|
91
|
+
# 4 CPUs
|
92
|
+
def parse_cpu(lines)
|
93
|
+
parse_indented_section(lines, 'CPU:', 'cpu')
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_indented_section(lines, prefix, tag_name)
|
97
|
+
short = remove_prefix(lines.pop, prefix)
|
98
|
+
long = short
|
99
|
+
|
100
|
+
while lines.last && lines.last.start_with?(' ')
|
101
|
+
long += ' - ' + lines.pop.strip
|
102
|
+
end
|
103
|
+
|
104
|
+
@tags[tag_name] = short
|
105
|
+
@tags["#{tag_name}_full"] = long
|
106
|
+
end
|
107
|
+
|
108
|
+
# Parses a single line like
|
109
|
+
# Crash reason: EXCEPTION_ACCESS_VIOLATION_READ
|
110
|
+
def parse_crash_reason(line)
|
111
|
+
reason = remove_prefix(line, 'Crash reason:')
|
112
|
+
|
113
|
+
if @message.nil?
|
114
|
+
@message = reason
|
115
|
+
else
|
116
|
+
# we parse the crashed thread first
|
117
|
+
@message = "#{reason} at #{@message}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Parses a single line like
|
122
|
+
# Crash address: 0xfffffffffee1dead
|
123
|
+
def parse_crash_address(line)
|
124
|
+
address = remove_prefix(line, 'Crash address:')
|
125
|
+
|
126
|
+
@extra['crash_address'] = address
|
127
|
+
end
|
128
|
+
|
129
|
+
def remove_prefix(line, prefix)
|
130
|
+
line.slice!(prefix)
|
131
|
+
line.strip
|
132
|
+
end
|
133
|
+
|
134
|
+
BACKTRACE_LINE_REGEX = /^\s*([0-9]+)\s+(.*)\s+(?:\[(([^ ]+)\s+:\s+([0-9]+))\s+\+\s+0x[0-9a-f]+\]|\+\s+0x[0-9a-f]+)\s*$/
|
135
|
+
|
136
|
+
# Parses something of the form
|
137
|
+
# Thread 0 (crashed)
|
138
|
+
# 0 ETClient.exe!QString::~QString() [qstring.h : 992 + 0xa]
|
139
|
+
# eip = 0x00d74e3a esp = 0x0018d1b4 ebp = 0x0018d1b8 ebx = 0x01ad947c
|
140
|
+
# esi = 0x05850000 edi = 0x058277f8 eax = 0xfee1dead ecx = 0xfee1dead
|
141
|
+
# edx = 0x00000004 efl = 0x00210282
|
142
|
+
# Found by: given as instruction pointer in context
|
143
|
+
# 1 ETClient.exe!QString::`scalar deleting destructor'(unsigned int) + 0xf
|
144
|
+
# eip = 0x00d9161f esp = 0x0018d1c0 ebp = 0x0018d1c4
|
145
|
+
# Found by: call frame info
|
146
|
+
# 2 ETClient.exe!buggyFunc() [machinelistitem.cpp : 181 + 0x1d]
|
147
|
+
# eip = 0x00daaea3 esp = 0x0018d1cc ebp = 0x0018d1dc
|
148
|
+
# Found by: call frame info
|
149
|
+
# 3 ETClient.exe!MachineListItem::on_EditButtonClicked() [machinelistitem.cpp : 197 + 0x5]
|
150
|
+
# eip = 0x00da5dd4 esp = 0x0018d1e4 ebp = 0x0018d250
|
151
|
+
# Found by: call frame info
|
152
|
+
# 4 ETClient.exe!MachineListItem::qt_static_metacall(QObject *,QMetaObject::Call,int,void * *) [moc_machinelistitem.cpp : 115 + 0x8]
|
153
|
+
# eip = 0x00de14a1 esp = 0x0018d258 ebp = 0x0018d27c
|
154
|
+
# Found by: call frame info
|
155
|
+
# 5 ETClient.exe!QMetaObject::activate(QObject *,int,int,void * *) + 0x4cf
|
156
|
+
# eip = 0x0135329f esp = 0x0018d284 ebp = 0x00000000
|
157
|
+
# Found by: call frame info
|
158
|
+
# 6 ETClient.exe!QMetaObject::activate(QObject *,QMetaObject const *,int,void * *) + 0x1e
|
159
|
+
# eip = 0x0135345e esp = 0x0018d304 ebp = 0x0018d32c
|
160
|
+
# Found by: call frame info
|
161
|
+
# 7 ETClient.exe!ToggleButtonWid::sig_buttonClicked() [moc_togglebuttonwid.cpp : 123 + 0x12]
|
162
|
+
# eip = 0x00de2759 esp = 0x0018d318 ebp = 0x0018d32c
|
163
|
+
# Found by: call frame info
|
164
|
+
# 8 ETClient.exe!ToggleButtonWid::mousePressEvent(QMouseEvent *) [togglebuttonwid.cpp : 122 + 0x8]
|
165
|
+
# eip = 0x00dcac14 esp = 0x0018d334 ebp = 0x0018d338
|
166
|
+
# Found by: call frame info
|
167
|
+
# 9 ETClient.exe!QWidget::event(QEvent *) + 0x89
|
168
|
+
# eip = 0x00df4fa9 esp = 0x0018d340 ebp = 0x05821ae0
|
169
|
+
# Found by: call frame info
|
170
|
+
# 10 ETClient.exe!QFrame::event(QEvent *) + 0x20
|
171
|
+
# eip = 0x00e17280 esp = 0x0018d40c ebp = 0x0018d7f8
|
172
|
+
# Found by: call frame info
|
173
|
+
# 11 ETClient.exe!QLabel::event(QEvent *) + 0xdf
|
174
|
+
# eip = 0x00e0714f esp = 0x0018d420 ebp = 0x0018d7f8
|
175
|
+
# Found by: call frame info
|
176
|
+
# 12 ETClient.exe!QApplicationPrivate::notify_helper(QObject *,QEvent *) + 0x98
|
177
|
+
# eip = 0x00e1de08 esp = 0x0018d434 ebp = 0x0033c6f8
|
178
|
+
# Found by: call frame info
|
179
|
+
# 13 ETClient.exe!QApplication::notify(QObject *,QEvent *) + 0x659
|
180
|
+
# eip = 0x00e1c5e9 esp = 0x0018d448 ebp = 0x0018d7f8
|
181
|
+
# Found by: call frame info
|
182
|
+
# 14 ETClient.exe!WinMain + 0x21358
|
183
|
+
# eip = 0x015bb068 esp = 0x0018d690 ebp = 0x0018d7f8
|
184
|
+
# Found by: call frame info
|
185
|
+
def parse_crashed_thread_stacktrace(lines, thread_id)
|
186
|
+
# remove the 1st line
|
187
|
+
lines.pop
|
188
|
+
|
189
|
+
stacktrace = []
|
190
|
+
process_matching_lines(lines, BACKTRACE_LINE_REGEX) do |match|
|
191
|
+
frame_nb = match[1]
|
192
|
+
function = match[2]
|
193
|
+
filename = match[4] || 'unknown'
|
194
|
+
lineno = match[5]
|
195
|
+
|
196
|
+
frame = {
|
197
|
+
'filename': filename,
|
198
|
+
'function': function,
|
199
|
+
'module': 'sentry.interfaces.Stacktrace'
|
200
|
+
}
|
201
|
+
frame['lineno'] = lineno.to_i if lineno
|
202
|
+
|
203
|
+
stacktrace << frame
|
204
|
+
|
205
|
+
if frame_nb.to_i == 0
|
206
|
+
@culprit = function
|
207
|
+
|
208
|
+
message_tail = function
|
209
|
+
message_tail += " (#{match[3]})" if match[3]
|
210
|
+
|
211
|
+
if @message.nil?
|
212
|
+
@message = message_tail
|
213
|
+
else
|
214
|
+
# already parsed the crash reason
|
215
|
+
@message += " at #{message_tail}"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# sentry wants their stacktrace with the oldest frame first
|
221
|
+
@crashed_thread_stacktrace = stacktrace.reverse
|
222
|
+
|
223
|
+
@extra['crashed_thread_id'] = thread_id
|
224
|
+
end
|
225
|
+
|
226
|
+
MODULE_LINE_REGEX = /0x[0-9a-f]+\s+-\s+0x[0-9a-f]+\s+([^ ]+)\s+([^ ]+)/
|
227
|
+
|
228
|
+
# Parses something of the form
|
229
|
+
# Loaded modules:
|
230
|
+
# 0x00d70000 - 0x01b39fff ETClient.exe ??? (main)
|
231
|
+
# 0x67070000 - 0x671a8fff libeay32.dll 1.0.2.4
|
232
|
+
# 0x71020000 - 0x71090fff msvcp120.dll 12.0.21005.1
|
233
|
+
# 0x71370000 - 0x713bbfff ssleay32.dll 1.0.2.4
|
234
|
+
# 0x72470000 - 0x724effff uxtheme.dll 6.1.7600.16385
|
235
|
+
# 0x726e0000 - 0x726f2fff dwmapi.dll 6.1.7601.18917
|
236
|
+
# 0x73160000 - 0x7316dfff RpcRtRemote.dll 6.1.7601.17514
|
237
|
+
# 0x731e0000 - 0x7321afff rsaenh.dll 6.1.7600.16385
|
238
|
+
# 0x73250000 - 0x7329efff webio.dll 6.1.7601.17725
|
239
|
+
# 0x732a0000 - 0x732f7fff winhttp.dll 6.1.7601.17514
|
240
|
+
# 0x73380000 - 0x73396fff cryptsp.dll 6.1.7601.18741
|
241
|
+
# 0x733b0000 - 0x7349afff dbghelp.dll 6.1.7601.17514
|
242
|
+
# 0x736e0000 - 0x736ecfff dhcpcsvc6.DLL 6.1.7601.17970
|
243
|
+
# 0x736f0000 - 0x73701fff dhcpcsvc.dll 6.1.7600.16385
|
244
|
+
# 0x73710000 - 0x73716fff winnsi.dll 6.1.7600.16385
|
245
|
+
# 0x73720000 - 0x7373bfff IPHLPAPI.DLL 6.1.7601.17514
|
246
|
+
# 0x73740000 - 0x73744fff WSHTCPIP.DLL 6.1.7600.16385
|
247
|
+
# 0x73750000 - 0x7378bfff mswsock.dll 6.1.7601.18254
|
248
|
+
# 0x73790000 - 0x737c1fff winmm.dll 6.1.7601.17514
|
249
|
+
# 0x737d0000 - 0x737f4fff powrprof.dll 6.1.7600.16385
|
250
|
+
# 0x73800000 - 0x73805fff wlanutil.dll 6.1.7600.16385
|
251
|
+
# 0x73810000 - 0x73824fff d3d9.dll 4.3.22.0
|
252
|
+
# 0x73850000 - 0x7393dfff msvcr120.dll 12.0.21005.1
|
253
|
+
# 0x73cc0000 - 0x73cd5fff wlanapi.dll 6.1.7600.16385
|
254
|
+
# 0x74d40000 - 0x74d47fff credssp.dll 6.1.7601.19110
|
255
|
+
# 0x74d70000 - 0x74d7bfff CRYPTBASE.dll 6.1.7601.19110
|
256
|
+
# 0x74d80000 - 0x74ddffff sspicli.dll 6.1.7601.19110
|
257
|
+
# 0x74e80000 - 0x75acafff shell32.dll 6.1.7601.18952
|
258
|
+
# 0x75b30000 - 0x75b39fff lpk.dll 6.1.7601.18985
|
259
|
+
# 0x75b40000 - 0x75bebfff msvcrt.dll 7.0.7601.17744
|
260
|
+
# 0x75bf0000 - 0x75c01fff devobj.dll 6.1.7601.17621
|
261
|
+
# 0x75c10000 - 0x75c1bfff msasn1.dll 6.1.7601.17514
|
262
|
+
# 0x75c80000 - 0x75cd6fff shlwapi.dll 6.1.7601.17514
|
263
|
+
# 0x75d20000 - 0x75e2ffff kernel32.dll 6.1.7601.19110 (WARNING: No symbols, wkernel32.pdb, 5B44EEB548A94000AB2677B80472D6442)
|
264
|
+
# 0x75e30000 - 0x75ed0fff advapi32.dll 6.1.7601.19091
|
265
|
+
# 0x75ee0000 - 0x75f6efff oleaut32.dll 6.1.7601.18679
|
266
|
+
# 0x75f70000 - 0x7605ffff rpcrt4.dll 6.1.7601.19110
|
267
|
+
# 0x76090000 - 0x761b0fff crypt32.dll 6.1.7601.18839
|
268
|
+
# 0x761e0000 - 0x7627cfff usp10.dll 1.626.7601.19054
|
269
|
+
# 0x76280000 - 0x7630ffff gdi32.dll 6.1.7601.19091
|
270
|
+
# 0x76310000 - 0x763dbfff msctf.dll 6.1.7601.18731
|
271
|
+
# 0x763e0000 - 0x763e5fff nsi.dll 6.1.7600.16385
|
272
|
+
# 0x76420000 - 0x7657bfff ole32.dll 6.1.7601.18915 (WARNING: No symbols, ole32.pdb, DE14A7E1B047414B826E606585170A892)
|
273
|
+
# 0x76580000 - 0x7671cfff setupapi.dll 6.1.7601.17514
|
274
|
+
# 0x76a80000 - 0x76ab4fff ws2_32.dll 6.1.7601.17514
|
275
|
+
# 0x76ac0000 - 0x76acafff profapi.dll 6.1.7600.16385
|
276
|
+
# 0x76ad0000 - 0x76ae8fff sechost.dll 6.1.7601.18869
|
277
|
+
# 0x76af0000 - 0x76beffff user32.dll 6.1.7601.19061 (WARNING: No symbols, wuser32.pdb, 9B8CF996B7584AC1ADA9DB5CADE512922)
|
278
|
+
# 0x76c80000 - 0x76cc6fff KERNELBASE.dll 6.1.7601.19110 (WARNING: No symbols, wkernelbase.pdb, A0567C574144432389F2D6539B69AA161)
|
279
|
+
# 0x76f90000 - 0x76feffff imm32.dll 6.1.7601.17514
|
280
|
+
# 0x76ff0000 - 0x77016fff cfgmgr32.dll 6.1.7601.17621
|
281
|
+
# 0x77420000 - 0x7759ffff ntdll.dll 6.1.7601.19110 (WARNING: No symbols, wntdll.pdb, 992AA396746C4D548F7F497DD63B4EEC2)
|
282
|
+
def parse_loaded_modules(lines)
|
283
|
+
# remove the 1st line
|
284
|
+
lines.pop
|
285
|
+
|
286
|
+
process_matching_lines(lines, MODULE_LINE_REGEX) do |match|
|
287
|
+
name = match[1]
|
288
|
+
version = match[2]
|
289
|
+
|
290
|
+
@modules[name] = version
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def process_matching_lines(lines, regex, &blk)
|
295
|
+
loop do
|
296
|
+
line = lines.pop
|
297
|
+
line.strip! if line
|
298
|
+
|
299
|
+
break if !line || line.empty?
|
300
|
+
|
301
|
+
match = regex.match(line)
|
302
|
+
yield(match) if match
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
# merges hash2 into hash1, recursively
|
307
|
+
# wish ActiveSupport was around...
|
308
|
+
def deep_merge(hash1, hash2)
|
309
|
+
hash2.each do |key, value|
|
310
|
+
if hash1.key?(value) && hash1[key].is_a?(Hash) && value.is_a?(Hash)
|
311
|
+
hash1[key] = hash1[key].merge(value)
|
312
|
+
else
|
313
|
+
hash1[key] = value
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'sentry_breakpad/version'
|
2
|
+
require 'sentry_breakpad/breakpad_parser'
|
3
|
+
|
4
|
+
require 'raven'
|
5
|
+
|
6
|
+
module SentryBreakpad
|
7
|
+
class << self
|
8
|
+
def send_from_file(file_path, extra_info = {}, include_whole_report = true)
|
9
|
+
send_event(BreakpadParser.from_file(file_path), extra_info, include_whole_report)
|
10
|
+
end
|
11
|
+
|
12
|
+
def send_from_string(string, extra_info = {}, include_whole_report = true)
|
13
|
+
send_event(BreakpadParser.new(string), extra_info, include_whole_report)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def send_event(parser, extra_info, include_whole_report)
|
19
|
+
Raven.client.send_event(parser.raven_event(extra_info, include_whole_report))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sentry_breakpad/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sentry_breakpad"
|
8
|
+
spec.version = SentryBreakpad::VERSION
|
9
|
+
spec.authors = ["Jean Rouge"]
|
10
|
+
spec.email = ["jer329@cornell.edu"]
|
11
|
+
|
12
|
+
spec.summary = %q{Converts Google breakpad's reports into Sentry/Raven events}
|
13
|
+
spec.homepage = "https://github.com/wk8/sentry_breakpad"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "sentry-raven", "~> 0.15.4"
|
22
|
+
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sentry_breakpad
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jean Rouge
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sentry-raven
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.15.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.15.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- jer329@cornell.edu
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- ".rspec"
|
50
|
+
- ".travis.yml"
|
51
|
+
- Gemfile
|
52
|
+
- LICENSE.txt
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- bin/console
|
56
|
+
- bin/setup
|
57
|
+
- lib/sentry_breakpad.rb
|
58
|
+
- lib/sentry_breakpad/breakpad_parser.rb
|
59
|
+
- lib/sentry_breakpad/version.rb
|
60
|
+
- sentry_breakpad.gemspec
|
61
|
+
homepage: https://github.com/wk8/sentry_breakpad
|
62
|
+
licenses:
|
63
|
+
- MIT
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.4.5
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: Converts Google breakpad's reports into Sentry/Raven events
|
85
|
+
test_files: []
|
86
|
+
has_rdoc:
|