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 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