fyipe 3.0.11516 → 3.0.11910.pre.qa
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 +4 -4
- data/.gitignore +2 -1
- data/fyipe.gemspec +3 -2
- data/lib/fyipe/fyipeListener.rb +42 -0
- data/lib/fyipe/fyipeTransport.rb +24 -0
- data/lib/fyipe/logtype.rb +9 -0
- data/lib/fyipe/timelineManager.rb +41 -0
- data/lib/fyipe/util.rb +158 -0
- data/lib/fyipe/version.rb +2 -1
- data/lib/fyipeTracker.rb +262 -0
- data/spec/fyipe_tracker_spec.rb +453 -0
- metadata +29 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2331d90271eaac762d3a0d6987224401ef1a8a90d34af6435d21bc8d9cc7ad7e
|
|
4
|
+
data.tar.gz: c431a30d6b080f0c5fa5a3c4cff65506488fd4e155b9d9a51302d41de3e68849
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7bf055e46779a5af6f0a431d49b3514abf58b4165c38283b6030afa5a833879c12387cb3e824afe0d82448c26139e16ebd2e8e871b5a58b377d14040b2b19cf7
|
|
7
|
+
data.tar.gz: 4081bc1ac42955010ac7f03259a17376adf5ed7e4f69ed7ae69db9f579cdd5cdec4ad6a25f638855702dc70e0a8496adc598578dac113f27db57d777babd833b
|
data/.gitignore
CHANGED
data/fyipe.gemspec
CHANGED
|
@@ -2,7 +2,7 @@ require File.expand_path('lib/fyipe/version', __dir__)
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |spec|
|
|
4
4
|
|
|
5
|
-
spec.name =
|
|
5
|
+
spec.name = Fyipe::NAME
|
|
6
6
|
spec.version = Fyipe::VERSION
|
|
7
7
|
spec.authors = ['HackerBay, Inc.']
|
|
8
8
|
spec.email = ['hello@hackerbay.io']
|
|
@@ -19,7 +19,8 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
spec.files = all_files - test_files
|
|
20
20
|
spec.extra_rdoc_files = ['README.md']
|
|
21
21
|
spec.add_dependency 'httparty', '~> 0.17'
|
|
22
|
-
spec.add_dependency 'gem-release'
|
|
22
|
+
spec.add_dependency 'gem-release', '~> 2.2'
|
|
23
|
+
spec.add_dependency 'ruby-enum', '~> 0.9'
|
|
23
24
|
spec.add_development_dependency 'dotenv', '~> 2.5'
|
|
24
25
|
spec.add_development_dependency 'rspec', '~> 3.6'
|
|
25
26
|
spec.add_development_dependency 'rubocop', '~> 0.60'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require_relative 'timelineManager'
|
|
2
|
+
require_relative 'util'
|
|
3
|
+
|
|
4
|
+
class FyipeListener
|
|
5
|
+
def initialize(eventId, options)
|
|
6
|
+
# start the timeline manager
|
|
7
|
+
@timelineObj = FyipeTimelineManager.new(options)
|
|
8
|
+
@currentEventId = eventId
|
|
9
|
+
@utilObj = Util.new(options)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def logErrorEvent(content, category = 'exception')
|
|
13
|
+
timelineObj = {}
|
|
14
|
+
timelineObj["category"]= category
|
|
15
|
+
timelineObj["data"]= content
|
|
16
|
+
timelineObj["type"]= @utilObj.getErrorType('ERROR')
|
|
17
|
+
timelineObj["eventId"]= @currentEventId
|
|
18
|
+
|
|
19
|
+
# add timeline to the stack
|
|
20
|
+
@timelineObj.addToTimeline(timelineObj)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def logCustomTimelineEvent(timelineObj)
|
|
24
|
+
timelineObj["eventId"] = @currentEventId
|
|
25
|
+
|
|
26
|
+
# add timeline to the stack
|
|
27
|
+
@timelineObj.addToTimeline(timelineObj)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def getTimeline()
|
|
31
|
+
# this always get the current state of the timeline array
|
|
32
|
+
return @timelineObj.getTimeline()
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def clearTimeline(eventId)
|
|
36
|
+
# set a new eventId
|
|
37
|
+
@currentEventId = eventId
|
|
38
|
+
# this will reset the state of the timeline array
|
|
39
|
+
return @timelineObj.clearTimeline()
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'httparty'
|
|
2
|
+
|
|
3
|
+
class FyipeTransport
|
|
4
|
+
include HTTParty
|
|
5
|
+
|
|
6
|
+
def initialize( apiUrl)
|
|
7
|
+
# set up the api transporter
|
|
8
|
+
@apiUrl = apiUrl
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def sendErrorEventToServer(event)
|
|
12
|
+
response = makeApiRequest(event)
|
|
13
|
+
return response
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
def makeApiRequest(body)
|
|
18
|
+
# make api request and return response
|
|
19
|
+
|
|
20
|
+
response = self.class.post(@apiUrl, :headers => {'Content-Type'=>'application/json'}, :body => body.to_json).parsed_response
|
|
21
|
+
|
|
22
|
+
return response
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
class FyipeTimelineManager
|
|
2
|
+
def initialize(options)
|
|
3
|
+
@options = options
|
|
4
|
+
@timeLineStack = []
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def addToTimeline(item)
|
|
9
|
+
addItemToTimeline(item)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# return the timeline
|
|
13
|
+
def getTimeline()
|
|
14
|
+
return @timeLineStack
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# clear the timeline
|
|
18
|
+
def clearTimeline()
|
|
19
|
+
@timeLineStack = []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
def addItemToTimeline(item)
|
|
25
|
+
# get the size of the stack
|
|
26
|
+
if (@options[:maxTimeline] != nil && (@timeLineStack.length() == @options[:maxTimeline].to_i))
|
|
27
|
+
return # It discards new timeline update once maximum is reached
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# add time to it
|
|
31
|
+
# current date and time
|
|
32
|
+
time = Time.now
|
|
33
|
+
now = time.inspect
|
|
34
|
+
|
|
35
|
+
item["timestamp"] = now
|
|
36
|
+
|
|
37
|
+
# add a new item to the stack
|
|
38
|
+
@timeLineStack.append(item)
|
|
39
|
+
return true
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/fyipe/util.rb
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
require_relative 'logtype'
|
|
3
|
+
|
|
4
|
+
class Util
|
|
5
|
+
|
|
6
|
+
def initialize(options)
|
|
7
|
+
@options = options
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def v4()
|
|
11
|
+
return SecureRandom.uuid
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def getErrorType(val)
|
|
15
|
+
enumValue = ""
|
|
16
|
+
LogType.each do |key, enum|
|
|
17
|
+
if (key.to_s.eql? "#{val}")
|
|
18
|
+
enumValue = enum.value
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
return enumValue
|
|
23
|
+
end
|
|
24
|
+
def getExceptionStackTrace(exception)
|
|
25
|
+
frames = [];
|
|
26
|
+
lineNumber = 'N/A'
|
|
27
|
+
|
|
28
|
+
obj = {}
|
|
29
|
+
obj["type"] = exception.class
|
|
30
|
+
obj["message"] = exception.message
|
|
31
|
+
obj["lineNumber"] = lineNumber
|
|
32
|
+
|
|
33
|
+
backtraces = exception.backtrace
|
|
34
|
+
backtraces != nil ?
|
|
35
|
+
backtraces.each do |backtrace|
|
|
36
|
+
breakdown = backtrace.split(":")
|
|
37
|
+
fileName = breakdown[0]
|
|
38
|
+
lineNumber = breakdown[1]
|
|
39
|
+
methodName = breakdown[2]
|
|
40
|
+
frame = {}
|
|
41
|
+
frame["fileName"] = fileName
|
|
42
|
+
frame["methodName"] = methodName
|
|
43
|
+
frame["lineNumber"] = lineNumber
|
|
44
|
+
frames.append(frame)
|
|
45
|
+
end
|
|
46
|
+
: nil
|
|
47
|
+
|
|
48
|
+
stacktrace = {}
|
|
49
|
+
stacktrace["frames"] = frames
|
|
50
|
+
|
|
51
|
+
obj["stacktrace"] = stacktrace
|
|
52
|
+
obj["lineNumber"] = frames[0] ? frames[0]["lineNumber"] : lineNumber
|
|
53
|
+
|
|
54
|
+
# run only if user agreed to use this feature
|
|
55
|
+
if @options[:captureCodeSnippet] == true
|
|
56
|
+
obj = getErrorCodeSnippet(obj)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
return obj
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def getErrorCodeSnippet(errorObj)
|
|
63
|
+
frames = []
|
|
64
|
+
if errorObj["stacktrace"] != nil
|
|
65
|
+
frames = errorObj["stacktrace"]["frames"]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# get content related to each frame
|
|
69
|
+
contentFrame = [];
|
|
70
|
+
|
|
71
|
+
frames.each do |frame|
|
|
72
|
+
updateFrame = getFrameContent(frame)
|
|
73
|
+
# update content of each frame
|
|
74
|
+
updateFrameContent(frame)
|
|
75
|
+
contentFrame.append(updateFrame)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
errorObj["stacktrace"]["frames"] = frames
|
|
79
|
+
return errorObj
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def getFrameContent(frame)
|
|
83
|
+
|
|
84
|
+
fileName = frame['fileName']
|
|
85
|
+
|
|
86
|
+
# # try to read the file content and save to frame
|
|
87
|
+
begin
|
|
88
|
+
file = File.open(fileName)
|
|
89
|
+
frame["sourceFile"] = file.readlines.map(&:chomp)
|
|
90
|
+
|
|
91
|
+
rescue => exception
|
|
92
|
+
# something terrible went wrong
|
|
93
|
+
puts "Warning; Could read file: #{exception.message}"
|
|
94
|
+
ensure
|
|
95
|
+
file.close
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
return frame
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def updateFrameContent(frame)
|
|
102
|
+
lines = []
|
|
103
|
+
if frame["sourceFile"] != nil
|
|
104
|
+
lines = frame["sourceFile"]
|
|
105
|
+
end
|
|
106
|
+
localFrame = addCodeSnippetToFrame(lines, frame)
|
|
107
|
+
frame = localFrame
|
|
108
|
+
return frame
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def addCodeSnippetToFrame(lines, frame, linesOfContext = 5)
|
|
112
|
+
|
|
113
|
+
if lines.length() < 1
|
|
114
|
+
return
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
lineNumber = 0
|
|
118
|
+
if frame['lineNumber'] != nil
|
|
119
|
+
lineNumber = frame['lineNumber'].to_i
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
maxLines = lines.length()
|
|
123
|
+
sourceLine = max(min(maxLines, lineNumber - 1), 0)
|
|
124
|
+
# attach the line before the error
|
|
125
|
+
frame['linesBeforeError'] = getPathOfLines(lines, max(0, sourceLine - linesOfContext), linesOfContext)
|
|
126
|
+
# attach the line after the error
|
|
127
|
+
frame['linesAfterError'] = getPathOfLines(
|
|
128
|
+
lines,
|
|
129
|
+
min(sourceLine + 1, maxLines),
|
|
130
|
+
1 + linesOfContext
|
|
131
|
+
)
|
|
132
|
+
# attach the error line
|
|
133
|
+
frame['errorLine'] = lines[min(maxLines - 1, sourceLine)]
|
|
134
|
+
|
|
135
|
+
# remove the source file
|
|
136
|
+
frame.delete('sourceFile')
|
|
137
|
+
|
|
138
|
+
return frame
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private
|
|
142
|
+
def getPathOfLines(lines, start, count)
|
|
143
|
+
terminal = start + count
|
|
144
|
+
return lines[start..terminal]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
def max (a,b)
|
|
149
|
+
a>b ? a : b
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
private
|
|
153
|
+
def min (a,b)
|
|
154
|
+
a<b ? a : b
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
end
|
data/lib/fyipe/version.rb
CHANGED
data/lib/fyipeTracker.rb
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
require_relative 'fyipe/util'
|
|
2
|
+
require_relative 'fyipe/fyipeListener'
|
|
3
|
+
require_relative 'fyipe/fyipeTransport'
|
|
4
|
+
require File.expand_path('./fyipe/version', __dir__)
|
|
5
|
+
|
|
6
|
+
class FyipeTracker
|
|
7
|
+
# FyipeLogger constructor.
|
|
8
|
+
# @param string apiUrl
|
|
9
|
+
# @param string errorTrackerId
|
|
10
|
+
# @param string errorTrackerKey
|
|
11
|
+
|
|
12
|
+
def initialize(apiUrl, errorTrackerId, errorTrackerKey, options = [])
|
|
13
|
+
# instance variable intialzation
|
|
14
|
+
@configKeys = ['baseUrl']
|
|
15
|
+
@MAX_ITEMS_ALLOWED_IN_STACK = 100
|
|
16
|
+
@errorTrackerId = errorTrackerId
|
|
17
|
+
setApiUrl(apiUrl)
|
|
18
|
+
@errorTrackerKey = errorTrackerKey
|
|
19
|
+
@tags = []
|
|
20
|
+
@fingerprint = []
|
|
21
|
+
@options = {
|
|
22
|
+
'maxTimeline': 5,
|
|
23
|
+
'captureCodeSnippet': true
|
|
24
|
+
}
|
|
25
|
+
setUpOptions(options)
|
|
26
|
+
@util = Util.new(@options)
|
|
27
|
+
setEventId()
|
|
28
|
+
@listenerObj = FyipeListener.new(getEventId(), @options)
|
|
29
|
+
@apiTransport = FyipeTransport.new(@apiUrl)
|
|
30
|
+
# setUpExceptionHandlerListener()
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def setApiUrl(apiUrl)
|
|
34
|
+
@apiUrl = apiUrl + '/error-tracker/' + @errorTrackerId + '/track';
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def setUpOptions(options)
|
|
38
|
+
# set up options
|
|
39
|
+
if(options.class.to_s != "Hash")
|
|
40
|
+
return # ignore passed options if it is not an object
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
options.each do |key, value|
|
|
44
|
+
# proceed with current key if it is not in the config keys
|
|
45
|
+
if (!(@configKeys.include? key))
|
|
46
|
+
# if key is allowed in options
|
|
47
|
+
if (@options[key] != nil)
|
|
48
|
+
# set max timeline properly after hecking conditions
|
|
49
|
+
if key.to_s == 'maxTimeline'
|
|
50
|
+
allowedValue = value
|
|
51
|
+
if value > @MAX_ITEMS_ALLOWED_IN_STACK or value < 1
|
|
52
|
+
allowedValue = @MAX_ITEMS_ALLOWED_IN_STACK
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
@options[key] = allowedValue
|
|
56
|
+
elsif key.to_s == 'captureCodeSnippet'
|
|
57
|
+
defaultVal = true
|
|
58
|
+
# set boolean value if boolean or set default `true` if anything other than boolean is passed
|
|
59
|
+
if [true, false].include? value # since there is no Boolean class in Ruby
|
|
60
|
+
defaultVal = value
|
|
61
|
+
end
|
|
62
|
+
@options[key] = defaultVal
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def setEventId()
|
|
71
|
+
@eventId = @util.v4()
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def getEventId()
|
|
75
|
+
return @eventId
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def addToTimeline(category, content, type)
|
|
79
|
+
timelineObj = {}
|
|
80
|
+
timelineObj["category"] = category
|
|
81
|
+
timelineObj["data"] = content
|
|
82
|
+
timelineObj["type"] = type
|
|
83
|
+
|
|
84
|
+
@listenerObj.logCustomTimelineEvent(timelineObj)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def getTimeline()
|
|
88
|
+
return @listenerObj.getTimeline()
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def setTag(key, value)
|
|
92
|
+
if (!((key.class.to_s.eql? "String") || (value.class.to_s.eql? "String")))
|
|
93
|
+
raise "Invalid Tag"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
exist = false
|
|
97
|
+
@tags.each do |tag|
|
|
98
|
+
if(tag['key'].to_s.eql? key)
|
|
99
|
+
# set the found flag
|
|
100
|
+
exist = true
|
|
101
|
+
# replace value if it exist
|
|
102
|
+
tag['value'] = value
|
|
103
|
+
break
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
if(!exist)
|
|
107
|
+
# push key and value if it doesnt
|
|
108
|
+
tag = {}
|
|
109
|
+
tag['key'] = key
|
|
110
|
+
tag['value'] = value
|
|
111
|
+
@tags.append(tag)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def setTags(tags)
|
|
116
|
+
|
|
117
|
+
if (!(tags.class.to_s.eql? "Array"))
|
|
118
|
+
raise "Invalid Tags"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
tags.each do |tag|
|
|
122
|
+
if(tag[:key] != nil && tag[:value] != nil)
|
|
123
|
+
setTag(tag[:key], tag[:value])
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def getTags()
|
|
129
|
+
return @tags
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def setFingerPrint(key)
|
|
133
|
+
# get data type of the passed key
|
|
134
|
+
keyClassType = key.class.to_s
|
|
135
|
+
|
|
136
|
+
# routine check
|
|
137
|
+
if (keyClassType != "String" && keyClassType != "Array")
|
|
138
|
+
raise "Invalid Fingerprint"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
fingerprint = key
|
|
142
|
+
if (keyClassType == "String")
|
|
143
|
+
fingerprint = [key]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
@fingerprint = fingerprint
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def getFingerprint(errorMessage)
|
|
150
|
+
|
|
151
|
+
# if no fingerprint exist currently
|
|
152
|
+
if (@fingerprint.length() < 1)
|
|
153
|
+
# set up finger print based on error since none exist
|
|
154
|
+
setFingerPrint(errorMessage)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
return @fingerprint
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def captureMessage( message)
|
|
161
|
+
# set the a handled tag
|
|
162
|
+
setTag('handled', 'true')
|
|
163
|
+
messageObj = {}
|
|
164
|
+
messageObj["message"] = message
|
|
165
|
+
|
|
166
|
+
prepareErrorObject('message', messageObj);
|
|
167
|
+
|
|
168
|
+
# send to the server
|
|
169
|
+
return sendErrorEventToServer()
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def setUpExceptionHandlerListener()
|
|
173
|
+
# start listener
|
|
174
|
+
at_exit do
|
|
175
|
+
manageErrorObject($!) if $!
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
end
|
|
179
|
+
def manageErrorObject(exception)
|
|
180
|
+
|
|
181
|
+
# construct the error object
|
|
182
|
+
errorObj = @utilObj.getExceptionStackTrace(exception);
|
|
183
|
+
|
|
184
|
+
# set the a handled tag
|
|
185
|
+
setTag('handled', 'false');
|
|
186
|
+
# prepare to send to server
|
|
187
|
+
prepareErrorObject('error', errorObj);
|
|
188
|
+
|
|
189
|
+
# send to the server
|
|
190
|
+
return sendErrorEventToServer();
|
|
191
|
+
end
|
|
192
|
+
def prepareErrorObject(eventType, errorStackTrace)
|
|
193
|
+
# set a last timeline as the error message
|
|
194
|
+
@listenerObj.logErrorEvent(errorStackTrace["message"], eventType)
|
|
195
|
+
|
|
196
|
+
# get current timeline
|
|
197
|
+
timeline = getTimeline()
|
|
198
|
+
|
|
199
|
+
tags = getTags()
|
|
200
|
+
fingerprint = getFingerprint(errorStackTrace["message"]) # default fingerprint will be the message from the error stacktrace
|
|
201
|
+
# get event ID
|
|
202
|
+
# Temporary display the state of the error stack, timeline and device details when an error occur
|
|
203
|
+
# prepare the event so it can be sent to the server
|
|
204
|
+
@event = {}
|
|
205
|
+
@event["type"] = eventType
|
|
206
|
+
@event["timeline"]= timeline
|
|
207
|
+
@event["exception"]= errorStackTrace
|
|
208
|
+
@event["eventId"]= getEventId()
|
|
209
|
+
@event["tags"]= tags
|
|
210
|
+
@event["fingerprint"]= fingerprint
|
|
211
|
+
@event["errorTrackerKey"]= @errorTrackerKey
|
|
212
|
+
@event["sdk"]= getSDKDetails()
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def getCurrentEvent()
|
|
216
|
+
return @event
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def captureException(exception)
|
|
220
|
+
|
|
221
|
+
# construct the error object
|
|
222
|
+
exceptionObj = @util.getExceptionStackTrace(exception)
|
|
223
|
+
|
|
224
|
+
# set the a handled tag
|
|
225
|
+
setTag('handled', 'true')
|
|
226
|
+
|
|
227
|
+
prepareErrorObject('exception', exceptionObj)
|
|
228
|
+
|
|
229
|
+
# send to the server
|
|
230
|
+
return sendErrorEventToServer()
|
|
231
|
+
end
|
|
232
|
+
def sendErrorEventToServer()
|
|
233
|
+
response = nil
|
|
234
|
+
# send to API properly
|
|
235
|
+
response = @apiTransport.sendErrorEventToServer(@event)
|
|
236
|
+
# generate a new event Id
|
|
237
|
+
setEventId()
|
|
238
|
+
# clear the timeline after a successful call to the server
|
|
239
|
+
clear(getEventId())
|
|
240
|
+
return response
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def clear(newEventId)
|
|
244
|
+
# clear tags
|
|
245
|
+
@tags = []
|
|
246
|
+
# clear fingerprint
|
|
247
|
+
@fingerprint = []
|
|
248
|
+
# clear timeline
|
|
249
|
+
@listenerObj.clearTimeline(newEventId)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def getSDKDetails()
|
|
253
|
+
# default sdk details
|
|
254
|
+
sdkDetail = {}
|
|
255
|
+
sdkDetail["name"] = Fyipe::NAME
|
|
256
|
+
sdkDetail["version"] = Fyipe::VERSION
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
return sdkDetail
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
end
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
# spec/fyipe_tracker_spec.rb
|
|
2
|
+
require_relative '../lib/fyipeTracker'
|
|
3
|
+
require_relative 'helper'
|
|
4
|
+
|
|
5
|
+
RSpec.configure do |config|
|
|
6
|
+
config.before(:suite){
|
|
7
|
+
# using $ registers the variable as a global variable
|
|
8
|
+
# ref: https://stackoverflow.com/a/19167379/6800815
|
|
9
|
+
$apiUrl = 'http://localhost:3002/api'
|
|
10
|
+
$helper = Helper.new()
|
|
11
|
+
sampleUser = $helper.getSampleUser()
|
|
12
|
+
$customTimeline = {}
|
|
13
|
+
$customTimeline["category"] = "cart"
|
|
14
|
+
$customTimeline["type"] = "info"
|
|
15
|
+
$customTimeline["content"] = { "message": "test-content"}
|
|
16
|
+
|
|
17
|
+
begin
|
|
18
|
+
# create user
|
|
19
|
+
createdUser = $helper.makeApiRequest($apiUrl+"/user/signup", sampleUser)
|
|
20
|
+
|
|
21
|
+
# get token and project
|
|
22
|
+
$token = createdUser['tokens']['jwtAccessToken']
|
|
23
|
+
$project = createdUser['project']
|
|
24
|
+
|
|
25
|
+
# create a component
|
|
26
|
+
component = { 'name' => $helper.getTitle() }
|
|
27
|
+
$createdComponent = $helper.makeApiRequest($apiUrl+"/component/"+$project["_id"], component, $token)
|
|
28
|
+
|
|
29
|
+
# create an errorTracker and set it as the global error tracker.
|
|
30
|
+
errorTrack = { 'name' => $helper.getTitle() }
|
|
31
|
+
$errorTracker = $helper.makeApiRequest($apiUrl+"/error-tracker/"+$project["_id"]+"/"+$createdComponent["_id"]+"/create", errorTrack, $token)
|
|
32
|
+
rescue => exception
|
|
33
|
+
puts "Couldnt create an error tracker to run a test, Error occured: #{exception.message}"
|
|
34
|
+
ensure
|
|
35
|
+
puts "All clear, Tests will commence now"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
RSpec.describe FyipeTracker do
|
|
42
|
+
it 'test_should_take_in_custom_timeline_event' do
|
|
43
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
44
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
45
|
+
timeline = tracker.getTimeline()
|
|
46
|
+
expect(timeline).to be_an_instance_of(Array)
|
|
47
|
+
expect(timeline.length()).to eql 1
|
|
48
|
+
expect($customTimeline["category"]).to eql timeline[0]["category"]
|
|
49
|
+
end
|
|
50
|
+
it 'test_should_ensure_timeline_event_contains_eventId_and_timestamp' do
|
|
51
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
52
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
53
|
+
|
|
54
|
+
timeline = tracker.getTimeline()
|
|
55
|
+
|
|
56
|
+
expect(timeline[0]["eventId"]).to be_an_instance_of(String)
|
|
57
|
+
expect(timeline[0]["timestamp"]).to be_an_instance_of(String)
|
|
58
|
+
end
|
|
59
|
+
it 'test_should_ensure_different_timeline_event_have_the_same_eventId' do
|
|
60
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
61
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
62
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], "error")
|
|
63
|
+
|
|
64
|
+
timeline = tracker.getTimeline()
|
|
65
|
+
expect(timeline.length()).to eql 2 # two timeline events
|
|
66
|
+
expect(timeline[0]["eventId"]).to eql timeline[1]["eventId"] # their eventId is the same, till there is an error sent to the server
|
|
67
|
+
end
|
|
68
|
+
it 'test_should_ensure_max_timline_cant_be_set_as_a_negative_number' do
|
|
69
|
+
options = {
|
|
70
|
+
"maxTimeline": -5
|
|
71
|
+
}
|
|
72
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"], options)
|
|
73
|
+
|
|
74
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
75
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], "error")
|
|
76
|
+
|
|
77
|
+
timeline = tracker.getTimeline()
|
|
78
|
+
expect(timeline.length()).to eql 2 # two timeline events
|
|
79
|
+
end
|
|
80
|
+
it 'test_should_ensure_new_timeline_event_after_max_timeline_are_discarded' do
|
|
81
|
+
options = {
|
|
82
|
+
"maxTimeline": 2
|
|
83
|
+
}
|
|
84
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"], options)
|
|
85
|
+
|
|
86
|
+
customTimeline2 = {}
|
|
87
|
+
|
|
88
|
+
customTimeline2["category"] = "logout"
|
|
89
|
+
customTimeline2["type"] = "success"
|
|
90
|
+
customTimeline2["content"] = {"message": "tester"}
|
|
91
|
+
|
|
92
|
+
# add 3 timeline events
|
|
93
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
94
|
+
tracker.addToTimeline(customTimeline2["category"], customTimeline2["content"], customTimeline2["type"])
|
|
95
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], "debug")
|
|
96
|
+
|
|
97
|
+
timeline = tracker.getTimeline()
|
|
98
|
+
|
|
99
|
+
expect(options[:maxTimeline]).to eql timeline.length() # two timeline events
|
|
100
|
+
expect(timeline[0]["type"]).to eql $customTimeline["type"]
|
|
101
|
+
expect(timeline[1]["category"]).to eql customTimeline2["category"]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'test_should_add_tags' do
|
|
105
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
106
|
+
|
|
107
|
+
tag = {
|
|
108
|
+
"key": "location",
|
|
109
|
+
"value": "Warsaw"
|
|
110
|
+
}
|
|
111
|
+
tracker.setTag(tag[:key], tag[:value])
|
|
112
|
+
|
|
113
|
+
availableTags = tracker.getTags()
|
|
114
|
+
expect(availableTags).to be_an_instance_of(Array)
|
|
115
|
+
expect(availableTags.length()).to eql 1
|
|
116
|
+
expect(tag[:key]).to eql availableTags[0]["key"]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'test_should_add_multiple_tags' do
|
|
120
|
+
|
|
121
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
122
|
+
|
|
123
|
+
tags = []
|
|
124
|
+
tag = {
|
|
125
|
+
"key": "location",
|
|
126
|
+
"value": "Warsaw"
|
|
127
|
+
}
|
|
128
|
+
tags.append(tag)
|
|
129
|
+
|
|
130
|
+
tagB = {
|
|
131
|
+
"key": "city",
|
|
132
|
+
"value": "Leeds"
|
|
133
|
+
}
|
|
134
|
+
tags.append(tagB)
|
|
135
|
+
|
|
136
|
+
tagC = {
|
|
137
|
+
"key": "device",
|
|
138
|
+
"value": "iPhone"
|
|
139
|
+
}
|
|
140
|
+
tags.append(tagC)
|
|
141
|
+
|
|
142
|
+
tracker.setTags(tags)
|
|
143
|
+
|
|
144
|
+
availableTags = tracker.getTags()
|
|
145
|
+
expect(availableTags).to be_an_instance_of(Array)
|
|
146
|
+
expect(availableTags.length()).to eql tags.length()
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'test_should_overwrite_existing_keys_to_avoid_duplicate_tags' do
|
|
150
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
151
|
+
|
|
152
|
+
tags = []
|
|
153
|
+
tag = {
|
|
154
|
+
"key": "location",
|
|
155
|
+
"value": "Warsaw"
|
|
156
|
+
}
|
|
157
|
+
tags.append(tag)
|
|
158
|
+
|
|
159
|
+
tagB = {
|
|
160
|
+
"key": "city",
|
|
161
|
+
"value": "Leeds"
|
|
162
|
+
}
|
|
163
|
+
tags.append(tagB)
|
|
164
|
+
|
|
165
|
+
tagC = {
|
|
166
|
+
"key": "location",
|
|
167
|
+
"value": "Paris"
|
|
168
|
+
}
|
|
169
|
+
tags.append(tagC)
|
|
170
|
+
|
|
171
|
+
tagD = {
|
|
172
|
+
"key": "device",
|
|
173
|
+
"value": "iPhone"
|
|
174
|
+
}
|
|
175
|
+
tags.append(tagD)
|
|
176
|
+
|
|
177
|
+
tagE = {
|
|
178
|
+
"key": "location",
|
|
179
|
+
"value": "London"
|
|
180
|
+
}
|
|
181
|
+
tags.append(tagE)
|
|
182
|
+
|
|
183
|
+
tracker.setTags(tags)
|
|
184
|
+
|
|
185
|
+
availableTags = tracker.getTags()
|
|
186
|
+
expect(availableTags).to be_an_instance_of(Array)
|
|
187
|
+
expect(availableTags.length()).to eql 3 # only 3 unique tags
|
|
188
|
+
expect(tagC[:key]).to eql availableTags[0]["key"]
|
|
189
|
+
expect(tagC[:value]).not_to eql availableTags[0]["value"]# old value for that tag location
|
|
190
|
+
expect(tagE[:key]).to eql availableTags[0]["key"]
|
|
191
|
+
expect(tagE[:value]).to eql availableTags[0]["value"]# latest value for that tag location
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it 'test_should_create_fingerprint_as_message_for_error_capture_without_any_fingerprint' do
|
|
195
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
196
|
+
|
|
197
|
+
errorMessage = "Uncaught Exception"
|
|
198
|
+
tracker.captureMessage(errorMessage)
|
|
199
|
+
event = tracker.getCurrentEvent()
|
|
200
|
+
expect(event["fingerprint"][0]).to eql errorMessage
|
|
201
|
+
end
|
|
202
|
+
it 'test_should_use_defined_fingerprint_array_for_error_capture_with_fingerprint' do
|
|
203
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
fingerprints = ['custom', 'errors']
|
|
207
|
+
tracker.setFingerPrint(fingerprints)
|
|
208
|
+
errorMessage = 'Uncaught Exception'
|
|
209
|
+
tracker.captureMessage(errorMessage)
|
|
210
|
+
event = tracker.getCurrentEvent()
|
|
211
|
+
expect(event["fingerprint"][0]).to eql fingerprints[0]
|
|
212
|
+
expect(event["fingerprint"][1]).to eql fingerprints[1]
|
|
213
|
+
end
|
|
214
|
+
it 'test_should_use_defined_fingerprint_string_for_error_capture_with_fingerprint' do
|
|
215
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
216
|
+
|
|
217
|
+
fingerprint = 'custom-fingerprint'
|
|
218
|
+
tracker.setFingerPrint(fingerprint)
|
|
219
|
+
errorMessage = 'Uncaught Exception'
|
|
220
|
+
tracker.captureMessage(errorMessage)
|
|
221
|
+
event = tracker.getCurrentEvent()
|
|
222
|
+
expect(event["fingerprint"][0]).to eql fingerprint
|
|
223
|
+
end
|
|
224
|
+
it 'test_should_create_an_event_ready_for_the_server_using_capture_message' do
|
|
225
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
226
|
+
|
|
227
|
+
errorMessage = 'This is a test'
|
|
228
|
+
tracker.captureMessage(errorMessage)
|
|
229
|
+
event = tracker.getCurrentEvent()
|
|
230
|
+
expect(event["type"]).to eql "message"
|
|
231
|
+
expect(event["exception"]["message"]).to eql errorMessage
|
|
232
|
+
end
|
|
233
|
+
it 'test_should_create_an_event_ready_for_the_server_while_having_the_timeline_with_same_event_id' do
|
|
234
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
235
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
236
|
+
|
|
237
|
+
errorMessage = 'This is a test'
|
|
238
|
+
tracker.captureMessage(errorMessage)
|
|
239
|
+
event = tracker.getCurrentEvent()
|
|
240
|
+
|
|
241
|
+
expect(event["timeline"].length()).to eql 2
|
|
242
|
+
expect(event["eventId"]).to eql event["timeline"][0]["eventId"]
|
|
243
|
+
expect(event["exception"]["message"]).to eql errorMessage
|
|
244
|
+
end
|
|
245
|
+
it 'test_should_create_an_event_ready_for_the_server_using_capture_exception' do
|
|
246
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
247
|
+
|
|
248
|
+
errorMessage = 'Error Found'
|
|
249
|
+
tracker.captureException(Exception.new(errorMessage))
|
|
250
|
+
event = tracker.getCurrentEvent()
|
|
251
|
+
|
|
252
|
+
expect(event["type"]).to eql "exception"
|
|
253
|
+
expect(event["exception"]["message"]).to eql errorMessage
|
|
254
|
+
end
|
|
255
|
+
it 'test_should_create_an_event_with_array_of_stacktrace' do
|
|
256
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
257
|
+
|
|
258
|
+
errorType = ""
|
|
259
|
+
begin
|
|
260
|
+
divByZero = 1/0
|
|
261
|
+
rescue => ex
|
|
262
|
+
errorType = ex.class
|
|
263
|
+
tracker.captureException(ex)
|
|
264
|
+
end
|
|
265
|
+
event = tracker.getCurrentEvent()
|
|
266
|
+
|
|
267
|
+
expect(event["type"]).to eql "exception"
|
|
268
|
+
expect(event["exception"]["type"]).to eql errorType
|
|
269
|
+
expect(event["exception"]["stacktrace"]).to be_an_instance_of(Hash)
|
|
270
|
+
expect(event["exception"]["stacktrace"]["frames"]).to be_an_instance_of(Array)
|
|
271
|
+
end
|
|
272
|
+
it 'test_should_create_an_event_with_the_object_of_the_stacktrace_in_place' do
|
|
273
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
274
|
+
|
|
275
|
+
errorType = ''
|
|
276
|
+
begin
|
|
277
|
+
divByZero= 1/0
|
|
278
|
+
rescue => ex
|
|
279
|
+
errorType = ex.class
|
|
280
|
+
tracker.captureException(ex)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
event = tracker.getCurrentEvent()
|
|
284
|
+
frame = event["exception"]["stacktrace"]["frames"][0]
|
|
285
|
+
|
|
286
|
+
expect(frame).to have_key('methodName')
|
|
287
|
+
expect(frame).to have_key('lineNumber')
|
|
288
|
+
expect(frame).to have_key('fileName')
|
|
289
|
+
|
|
290
|
+
end
|
|
291
|
+
it 'test_should_create_an_event_and_new_event_should_have_different_id' do
|
|
292
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
293
|
+
|
|
294
|
+
errorMessage = 'random error occured'
|
|
295
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
296
|
+
|
|
297
|
+
event = tracker.captureMessage(errorMessage)
|
|
298
|
+
|
|
299
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
300
|
+
|
|
301
|
+
newEvent = nil
|
|
302
|
+
errorMessageException = ''
|
|
303
|
+
begin
|
|
304
|
+
divByZero= 1/0
|
|
305
|
+
rescue => ex
|
|
306
|
+
errorMessageException = ex.message
|
|
307
|
+
newEvent = tracker.captureException(ex)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# ensure that the first event have a type message, same error message
|
|
311
|
+
expect(event["type"]).to eql "message"
|
|
312
|
+
expect(event["content"]["message"]).to eql errorMessage
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
# ensure that the second event have a type exception, same error message
|
|
316
|
+
expect(newEvent["type"]).to eql "exception"
|
|
317
|
+
expect(newEvent["content"]["message"]).to eql errorMessageException
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
# confim their eventId is different
|
|
321
|
+
expect(event["_id"]).not_to eql newEvent["_id"]
|
|
322
|
+
end
|
|
323
|
+
it 'test_should_create_an_event_that_has_timeline_and_new_event_having_timeline_and_tags' do
|
|
324
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
325
|
+
|
|
326
|
+
errorMessage = 'random error caused midway'
|
|
327
|
+
errorMessageObj = '';
|
|
328
|
+
|
|
329
|
+
# add timeline to first tracker
|
|
330
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
331
|
+
event =tracker.captureMessage(errorMessage)
|
|
332
|
+
|
|
333
|
+
# add timeline and tag to second tracker
|
|
334
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
335
|
+
tag = {
|
|
336
|
+
"key": "location",
|
|
337
|
+
"value": "Warsaw"
|
|
338
|
+
}
|
|
339
|
+
tracker.setTag(tag[:key], tag[:value])
|
|
340
|
+
newEvent = nil
|
|
341
|
+
begin
|
|
342
|
+
divByZero= 1/0
|
|
343
|
+
rescue => ex
|
|
344
|
+
errorMessageObj = ex.message
|
|
345
|
+
newEvent = tracker.captureException(ex)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# puts event["timeline"]
|
|
349
|
+
# ensure that the first event have a type message, same error message and two timeline (one custom, one generic)
|
|
350
|
+
expect(event["type"]).to eql "message"
|
|
351
|
+
expect(event["content"]["message"]).to eql errorMessage
|
|
352
|
+
expect(event["timeline"].length()).to eql 2
|
|
353
|
+
expect(event["tags"].length()).to eql 1 # the default event tag added
|
|
354
|
+
|
|
355
|
+
# ensure that the second event have a type exception, same error message and 2 tags
|
|
356
|
+
expect(newEvent["type"]).to eql "exception"
|
|
357
|
+
expect(newEvent["content"]["message"]).to eql errorMessageObj
|
|
358
|
+
expect(newEvent["timeline"].length()).to eql 2
|
|
359
|
+
expect(newEvent["tags"].length()).to eql 2 # the default and custom tag
|
|
360
|
+
end
|
|
361
|
+
it 'test_should_contain_version_number_and_sdk_name_in_captured_message' do
|
|
362
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"])
|
|
363
|
+
|
|
364
|
+
errorMessage = 'Error Found'
|
|
365
|
+
tracker.captureMessage(errorMessage)
|
|
366
|
+
event = tracker.getCurrentEvent()
|
|
367
|
+
|
|
368
|
+
expect(event["sdk"]["name"]).to be_an_instance_of(String)
|
|
369
|
+
|
|
370
|
+
expect(event['sdk']['version']).to match(/(([0-9])+\.([0-9])+\.([0-9])+)/)# confirm that the version follows the pattern XX.XX.XX where X is a non negative integer
|
|
371
|
+
end
|
|
372
|
+
it 'test_should_add_code_capture_to_stack_trace_when_flag_is_passed_in_options' do
|
|
373
|
+
options = {
|
|
374
|
+
"captureCodeSnippet": true
|
|
375
|
+
}
|
|
376
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"], options)
|
|
377
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
378
|
+
|
|
379
|
+
event = nil
|
|
380
|
+
errorMsg = ''
|
|
381
|
+
begin
|
|
382
|
+
divByZero = 1/0
|
|
383
|
+
rescue => ex
|
|
384
|
+
errorMsg = ex.message
|
|
385
|
+
event = tracker.captureException(ex)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
expect(event["type"]).to eql "exception"
|
|
389
|
+
expect(event["content"]["message"]).to eql errorMsg
|
|
390
|
+
expect(event["content"]["stacktrace"]).to be_an_instance_of(Hash)
|
|
391
|
+
expect(event["content"]["stacktrace"]["frames"]).to be_an_instance_of(Array)
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
incidentFrame = event["content"]["stacktrace"]["frames"][0]
|
|
395
|
+
expect(incidentFrame).to have_key('linesBeforeError')
|
|
396
|
+
expect(incidentFrame).to have_key('linesAfterError')
|
|
397
|
+
expect(incidentFrame).to have_key('errorLine')
|
|
398
|
+
end
|
|
399
|
+
it 'test_should_not_add_code_capture_to_stack_trace_when_flag_is_passed_in_options' do
|
|
400
|
+
options = {
|
|
401
|
+
"captureCodeSnippet": false
|
|
402
|
+
}
|
|
403
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"], options)
|
|
404
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
405
|
+
|
|
406
|
+
event = nil
|
|
407
|
+
errorType = ''
|
|
408
|
+
begin
|
|
409
|
+
divByZero = 1/0
|
|
410
|
+
rescue => ex
|
|
411
|
+
errorType = ex.class.to_s
|
|
412
|
+
event = tracker.captureException(ex)
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
expect(event["type"]).to eql "exception"
|
|
416
|
+
expect(event["content"]["type"]).to eql errorType
|
|
417
|
+
expect(event["content"]["stacktrace"]).to be_an_instance_of(Hash)
|
|
418
|
+
expect(event["content"]["stacktrace"]["frames"]).to be_an_instance_of(Array)
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
incidentFrame = event["content"]["stacktrace"]["frames"][0]
|
|
422
|
+
expect(incidentFrame).to_not have_key('linesBeforeError')
|
|
423
|
+
expect(incidentFrame).to_not have_key('linesAfterError')
|
|
424
|
+
expect(incidentFrame).to_not have_key('errorLine')
|
|
425
|
+
end
|
|
426
|
+
it 'test_should_add_code_capture_to_stack_trace_by_default_when_unwanted_flag_is_passed_in_options' do
|
|
427
|
+
options = {
|
|
428
|
+
"captureCodeSnippet": "heyy" # sdk expects a true or false but it defaults to true if wrong value is sent
|
|
429
|
+
}
|
|
430
|
+
tracker = FyipeTracker.new($apiUrl, $errorTracker["_id"], $errorTracker["key"], options)
|
|
431
|
+
tracker.addToTimeline($customTimeline["category"], $customTimeline["content"], $customTimeline["type"])
|
|
432
|
+
|
|
433
|
+
event = nil
|
|
434
|
+
errorMsg = ''
|
|
435
|
+
begin
|
|
436
|
+
divByZero = 1/0
|
|
437
|
+
rescue => ex
|
|
438
|
+
errorMsg = ex.message
|
|
439
|
+
event = tracker.captureException(ex)
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
expect(event["type"]).to eql "exception"
|
|
443
|
+
expect(event["content"]["message"]).to eql errorMsg
|
|
444
|
+
expect(event["content"]["stacktrace"]).to be_an_instance_of(Hash)
|
|
445
|
+
expect(event["content"]["stacktrace"]["frames"]).to be_an_instance_of(Array)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
incidentFrame = event["content"]["stacktrace"]["frames"][0]
|
|
449
|
+
expect(incidentFrame).to have_key('linesBeforeError')
|
|
450
|
+
expect(incidentFrame).to have_key('linesAfterError')
|
|
451
|
+
expect(incidentFrame).to have_key('errorLine')
|
|
452
|
+
end
|
|
453
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fyipe
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.11910.pre.qa
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- HackerBay, Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-06-
|
|
11
|
+
date: 2021-06-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: httparty
|
|
@@ -28,16 +28,30 @@ dependencies:
|
|
|
28
28
|
name: gem-release
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '2.2'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
32
39
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
40
|
+
version: '2.2'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: ruby-enum
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.9'
|
|
34
48
|
type: :runtime
|
|
35
49
|
prerelease: false
|
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
51
|
requirements:
|
|
38
|
-
- - "
|
|
52
|
+
- - "~>"
|
|
39
53
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
54
|
+
version: '0.9'
|
|
41
55
|
- !ruby/object:Gem::Dependency
|
|
42
56
|
name: dotenv
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -140,9 +154,16 @@ files:
|
|
|
140
154
|
- README.md
|
|
141
155
|
- RakeFile
|
|
142
156
|
- fyipe.gemspec
|
|
157
|
+
- lib/fyipe/fyipeListener.rb
|
|
158
|
+
- lib/fyipe/fyipeTransport.rb
|
|
159
|
+
- lib/fyipe/logtype.rb
|
|
160
|
+
- lib/fyipe/timelineManager.rb
|
|
161
|
+
- lib/fyipe/util.rb
|
|
143
162
|
- lib/fyipe/version.rb
|
|
144
163
|
- lib/fyipeLogger.rb
|
|
164
|
+
- lib/fyipeTracker.rb
|
|
145
165
|
- spec/fyipe_logger_spec.rb
|
|
166
|
+
- spec/fyipe_tracker_spec.rb
|
|
146
167
|
- spec/helper.rb
|
|
147
168
|
- spec/spec_helper.rb
|
|
148
169
|
homepage: https://github.com/Fyipe/ruby-sdk
|
|
@@ -160,9 +181,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
160
181
|
version: 2.5.0
|
|
161
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
183
|
requirements:
|
|
163
|
-
- - "
|
|
184
|
+
- - ">"
|
|
164
185
|
- !ruby/object:Gem::Version
|
|
165
|
-
version:
|
|
186
|
+
version: 1.3.1
|
|
166
187
|
requirements: []
|
|
167
188
|
rubyforge_project:
|
|
168
189
|
rubygems_version: 2.7.6
|