crash_analysis 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/crash_analysis +1 -1
- data/lib/crash_analysis.rb +76 -94
- data/lib/crash_analysis/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8cacc9eba88eac17c2e429f8895fecda7632bb2e
|
4
|
+
data.tar.gz: 05bfacc7cc22340badf9b536c1bfdfba2a4b0c33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b7b2c700cef929c5aa098de5441a514482270b4e6784f36de0729bc199d631c680fc8f2500ebfc0b5e4aaa83f25d3f24269fe3c49c5dbfe4b4e1471ba08ab34
|
7
|
+
data.tar.gz: ff3d803826d727c031b399a340b5462140f4944d8b6e5a3e519e1cec0cdcf8d14b630fa3b38944be801700c574d1164abed220d3da2f49d1ae10257df1ba7863
|
data/bin/crash_analysis
CHANGED
data/lib/crash_analysis.rb
CHANGED
@@ -1,127 +1,109 @@
|
|
1
1
|
require "crash_analysis/version"
|
2
2
|
|
3
|
-
# Utils
|
4
|
-
class Array
|
5
|
-
def prog_each(&block)
|
6
|
-
bar_length = (`tput cols` || 80).to_i - 30
|
7
|
-
time_now = Time.now
|
8
|
-
total = self.count
|
9
|
-
last_flush = 0
|
10
|
-
flush_time = 1
|
11
|
-
self.each_with_index{|element, x|
|
12
|
-
cur = (x + 1) * 100 / total
|
13
|
-
time_left = (((Time.now - time_now) * (100 - cur)).to_f / cur).ceil
|
14
|
-
if (Time.now - last_flush).to_i >= flush_time or time_left < 1
|
15
|
-
time_left_graceful = Time.at(time_left).utc.strftime("%H:%M:%S")
|
16
|
-
if time_left > 86400
|
17
|
-
time_left_graceful = res.split(":")
|
18
|
-
time_left_graceful[0] = (time_left_graceful[0].to_i + days * 24).to_s
|
19
|
-
time_left_graceful = time_left_graceful.join(":")
|
20
|
-
end
|
21
|
-
print "\r"
|
22
|
-
cur_len = (bar_length * (x + 1)) / total
|
23
|
-
print "[" << (["#"] * cur_len).join << (["-"] * (bar_length - cur_len)).join << "] #{cur}% [#{time_left_graceful} left]"
|
24
|
-
last_flush = Time.now
|
25
|
-
end
|
26
|
-
block.call element if block
|
27
|
-
}
|
28
|
-
puts "\n"
|
29
|
-
"Done."
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
3
|
# Main
|
34
4
|
module CrashAnalysis
|
35
|
-
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
5
|
+
|
6
|
+
def initialize()
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.run()
|
10
|
+
puts "input logs_dir_path: "
|
11
|
+
logs_dir_path = gets.chomp
|
12
|
+
if logs_dir_path.empty? || logs_dir_path.nil? || !File.directory?(logs_dir_path)
|
13
|
+
puts "invalid logs_dir_path"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
puts "input log_file_suffix(log, crash, txt etc.): "
|
17
|
+
log_file_suffix = gets.chomp
|
18
|
+
if log_file_suffix.empty? || log_file_suffix.nil?
|
19
|
+
puts "invalid log_file_suffix"
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
puts "init settings..."
|
24
|
+
output = []
|
25
|
+
r, io = IO.pipe
|
26
|
+
fork do
|
27
|
+
system("find /Applications/Xcode.app -name symbolicatecrash -type f", out: io, err: :out)
|
28
|
+
end
|
29
|
+
io.close
|
30
|
+
r.each_line{|l| puts l; output << l.chomp}
|
31
|
+
symbolicatecrash_path = output[0]
|
32
|
+
|
33
|
+
puts "running..."
|
34
|
+
analysis = Analysis.new()
|
35
|
+
analysis.run(logs_dir_path, log_file_suffix, symbolicatecrash_path)
|
36
|
+
|
40
37
|
end
|
41
38
|
|
42
39
|
class Analysis
|
43
40
|
|
44
41
|
def initialize()
|
45
|
-
@
|
42
|
+
@dSYM_file_name = ""
|
46
43
|
end
|
47
44
|
|
48
|
-
def run(
|
49
|
-
|
50
|
-
|
51
|
-
return
|
52
|
-
end
|
53
|
-
if filePath.nil? || filePath.empty?
|
54
|
-
puts "error: need directory path"
|
55
|
-
else
|
56
|
-
if File.directory?(filePath)
|
57
|
-
crashFileNames = traverse(filePath, rawFileSuffix)
|
58
|
-
if crashFileNames.nil? || crashFileNames.empty?
|
59
|
-
return
|
60
|
-
else
|
61
|
-
AnalysisLog(crashFileNames, rawFileSuffix, filePath)
|
62
|
-
end
|
63
|
-
else
|
64
|
-
puts "error: not a directory"
|
65
|
-
end
|
66
|
-
end
|
45
|
+
def run(logs_dir_path, log_file_suffix, symbolicatecrash_path)
|
46
|
+
crash_files = traverse(logs_dir_path, log_file_suffix)
|
47
|
+
analysis_action(crash_files, log_file_suffix, logs_dir_path, symbolicatecrash_path)
|
67
48
|
end
|
68
49
|
|
69
|
-
def traverse(
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
Dir.foreach(
|
75
|
-
|
76
|
-
if
|
77
|
-
|
78
|
-
|
50
|
+
def traverse(logs_dir_path, log_file_suffix)
|
51
|
+
crash_files = Array.new
|
52
|
+
count_app = 0
|
53
|
+
count_dSYM = 0
|
54
|
+
|
55
|
+
Dir.foreach(logs_dir_path) do |file|
|
56
|
+
file_suffix_array = file.strip.split(".")
|
57
|
+
if file_suffix_array.last == log_file_suffix
|
58
|
+
file_suffix_array.pop
|
59
|
+
crash_files << (file)
|
79
60
|
end
|
80
|
-
if
|
81
|
-
|
61
|
+
if file_suffix_array.last == "app"
|
62
|
+
count_app += 1
|
82
63
|
end
|
83
|
-
if
|
84
|
-
|
64
|
+
if file_suffix_array.last == "dSYM"
|
65
|
+
@dSYM_file_name = file
|
66
|
+
count_dSYM += 1
|
85
67
|
end
|
86
68
|
end
|
87
|
-
else
|
88
|
-
puts "Files:" + filePath
|
89
|
-
end
|
90
69
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
70
|
+
if count_app != 1 || count_dSYM !=1 || crash_files.count < 1
|
71
|
+
puts "error:\n"
|
72
|
+
puts "make sure the directory contains those files: 1 .app file & 1 .dSYM file & related crash files"
|
73
|
+
return
|
74
|
+
end
|
75
|
+
return crash_files
|
95
76
|
end
|
96
77
|
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
def AnalysisLog(crashFileNames, rawFileSuffix, filePath)
|
101
|
-
cmd = "/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash"
|
78
|
+
def analysis_action(crash_files, log_file_suffix, logs_dir_path, symbolicatecrash_path)
|
102
79
|
evn = "export DEVELOPER_DIR='/Applications/XCode.app/Contents/Developer'"
|
103
|
-
|
104
|
-
|
105
|
-
if !File.directory?(
|
106
|
-
Dir.mkdir(
|
80
|
+
output_log_dir = logs_dir_path + "/crash_logs"
|
81
|
+
percent_count = 0
|
82
|
+
if !File.directory?(output_log_dir)
|
83
|
+
Dir.mkdir(output_log_dir)
|
107
84
|
end
|
108
85
|
|
109
|
-
for
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
86
|
+
for file in crash_files
|
87
|
+
running_thread = Thread.new do
|
88
|
+
short_file_name = file.split("/").last
|
89
|
+
|
90
|
+
output_file = output_log_dir + "/" + short_file_name
|
91
|
+
current_log_file = logs_dir_path + "/" + file
|
92
|
+
system("#{evn} \n #{symbolicatecrash_path} #{current_log_file} #{@dSYM_file_name} > #{output_file}")
|
93
|
+
|
94
|
+
percent_count = percent_count + 1
|
95
|
+
precent = ((percent_count.to_f / crash_files.count.to_f) * 10000).round / 10000.0
|
116
96
|
str = (precent * 100).to_s
|
117
|
-
|
97
|
+
puts "#{str[0,4]}% || analyzing file: #{file}"
|
118
98
|
Thread.main.wakeup
|
119
99
|
end
|
120
100
|
# Maximum run for 10 seconds
|
121
101
|
sleep 10
|
122
|
-
Thread.kill(
|
102
|
+
Thread.kill(running_thread)
|
123
103
|
end
|
124
104
|
puts "\n Done."
|
125
105
|
end
|
106
|
+
|
126
107
|
end
|
108
|
+
|
127
109
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crash_analysis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- HongliYu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|