fyipe 3.0.11516 → 3.0.11910.pre.qa

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c497c9ac737e8c3dc70b4f5793eb388ab5e5a6ec6e431212d7cff2031f201228
4
- data.tar.gz: 8ff5fbe0e4d8fe54aec562fe17b96267c2cd88f004b780b8f62bd74109a19be4
3
+ metadata.gz: 2331d90271eaac762d3a0d6987224401ef1a8a90d34af6435d21bc8d9cc7ad7e
4
+ data.tar.gz: c431a30d6b080f0c5fa5a3c4cff65506488fd4e155b9d9a51302d41de3e68849
5
5
  SHA512:
6
- metadata.gz: 04b823df12a09d4f5e95ef3233cc444b31c7572f438601a86d3772aa3e3bc677d826a56ddc1c5aed30189011496307db19b1ca0a734fb25a63369e0d3a180ed4
7
- data.tar.gz: 8a9d36d40e4ca6aa4b9a948fd4c71ee7c8bc57811a83d7943002c2fa7ba83725fdd088483d2b597506b48ac97c884b67f7b8382f868c4e2774d1c13543dae125
6
+ metadata.gz: 7bf055e46779a5af6f0a431d49b3514abf58b4165c38283b6030afa5a833879c12387cb3e824afe0d82448c26139e16ebd2e8e871b5a58b377d14040b2b19cf7
7
+ data.tar.gz: 4081bc1ac42955010ac7f03259a17376adf5ed7e4f69ed7ae69db9f579cdd5cdec4ad6a25f638855702dc70e0a8496adc598578dac113f27db57d777babd833b
data/.gitignore CHANGED
@@ -11,4 +11,5 @@ pkg/*
11
11
  .DS_Store
12
12
  .env
13
13
  spec/dummy/tmp/*
14
- spec/dummy/log/*.log
14
+ spec/dummy/log/*.log
15
+ demo.rb
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 = 'fyipe'
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,9 @@
1
+ require 'ruby-enum'
2
+
3
+ class LogType
4
+ include Ruby::Enum
5
+
6
+ define :INFO, "info"
7
+ define :WARNING, "warning"
8
+ define :ERROR, "error"
9
+ 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
@@ -1,3 +1,4 @@
1
1
  module Fyipe
2
- VERSION = '3.0.11516'
2
+ NAME = 'fyipe'
3
+ VERSION = '3.0.11910-qa'
3
4
  end
@@ -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.11516
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-09 00:00:00.000000000 Z
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: '0'
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: '0'
186
+ version: 1.3.1
166
187
  requirements: []
167
188
  rubyforge_project:
168
189
  rubygems_version: 2.7.6