Skip to content

Commit 661cc23

Browse files
authored
Adding extra context information to on_error reporting. Fixes #96 (#103)
1 parent f8adc32 commit 661cc23

File tree

8 files changed

+25
-20
lines changed

8 files changed

+25
-20
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,14 @@ Cable.configure do |settings|
8686
settings.backend_class = Cable::RedisBackend
8787
settings.backend_ping_interval = 15.seconds
8888
settings.restart_error_allowance = 20
89-
settings.on_error = ->(error : Exception, message : String) do
89+
settings.on_error = ->(error : Exception, message : String, connection : Cable::Connection?) do
9090
# or whichever error reportings you're using
9191
Bugsnag.report(error) do |event|
9292
event.app.app_type = "lucky"
9393
event.meta_data = {
9494
"error_class" => JSON::Any.new(error.class.name),
9595
"message" => JSON::Any.new(message),
96+
"token" => JSON::Any.new(connection.try(&.token).to_s),
9697
}
9798
end
9899
end
@@ -283,7 +284,7 @@ You can setup a hook to report errors to any 3rd party service you choose.
283284
```crystal
284285
# config/cable.cr
285286
Cable.configure do |settings|
286-
settings.on_error = ->(exception : Exception, message : String) do
287+
settings.on_error = ->(exception : Exception, message : String, connection : Cable::Connection?) do
287288
# new 3rd part service handler
288289
ExceptionService.notify(exception, message: message)
289290
# default logic
@@ -295,13 +296,13 @@ end
295296

296297
```crystal
297298
Habitat.create do
298-
setting on_error : Proc(Exception, String, Nil) = ->(exception : Exception, message : String) do
299+
setting on_error : Proc(Exception, String, Cable::Connection?, Nil) = ->(exception : Exception, message : String, connection : Cable::Connection?) do
299300
Cable::Logger.error(exception: exception) { message }
300301
end
301302
end
302303
```
303304

304-
> NOTE: The message field will contain details regarding which class/method raised the error
305+
> NOTE: The message field will contain details regarding which class/method raised the error. The connection parameter provides access to the `Cable::Connection` instance (when available), including the `token`, `connection_identifier`, and any fields defined via `identified_by` or `owned_by`.
305306
306307
## Client-Side
307308

spec/cable/handler_spec.cr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,10 @@ describe Cable::Handler do
132132
end
133133

134134
FakeExceptionService.size.should eq(1)
135-
FakeExceptionService.exceptions.first.keys.first.should eq("Cable::Handler#socket.on_message")
136-
FakeExceptionService.exceptions.first.values.first.class.should eq(JSON::SerializableError)
135+
exception = FakeExceptionService.exceptions.first
136+
exception.message.should contain("Cable::Handler#socket.on_message")
137+
exception.exception.class.should eq(JSON::SerializableError)
138+
exception.connection.as(Cable::Connection).token.should eq("1")
137139
end
138140

139141
it "rejected" do

spec/spec_helper.cr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Cable.configure do |settings|
1616
settings.backend_class = Cable::RedisBackend
1717
settings.backend_ping_interval = 2.seconds
1818
settings.restart_error_allowance = 2
19-
settings.on_error = ->(exception : Exception, message : String) do
20-
FakeExceptionService.notify(exception, message: message)
19+
settings.on_error = ->(exception : Exception, message : String, connection : Cable::Connection?) do
20+
FakeExceptionService.notify(exception, message: message, connection: connection)
2121
end
2222
end
2323

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
class FakeExceptionService
2-
@@exceptions : Array(Hash(String, Exception)) = [] of Hash(String, Exception)
2+
record Report, exception : Exception, message : String, connection : Cable::Connection?
3+
@@exceptions : Array(Report) = [] of Report
34

45
def self.clear
5-
@@exceptions = [] of Hash(String, Exception)
6+
@@exceptions = [] of Report
67
end
78

89
def self.size
@@ -13,7 +14,7 @@ class FakeExceptionService
1314
@@exceptions
1415
end
1516

16-
def self.notify(exception, message)
17-
@@exceptions << {message => exception}
17+
def self.notify(exception, message, connection = nil)
18+
@@exceptions << Report.new(exception: exception, message: message, connection: connection)
1819
end
1920
end

src/cable.cr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ module Cable
3737
setting backend_class : Cable::BackendCore.class = Cable::BackendRegistry, example: "Cable::RedisBackend"
3838
setting backend_ping_interval : Time::Span = 15.seconds
3939
setting restart_error_allowance : Int32 = 20
40-
setting on_error : Proc(Exception, String, Nil) = ->(exception : Exception, message : String) do
40+
# ameba:disable Lint/UnusedArgument
41+
setting on_error : Proc(Exception, String, Cable::Connection?, Nil) = ->(exception : Exception, message : String, connection : Cable::Connection?) do
4142
Cable::Logger.error(exception: exception) { message }
4243
end
4344
end

src/cable/connection.cr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ module Cable
7777
channels_to_close.each do |identifier, channel|
7878
channel.close
7979
rescue e : IO::Error
80-
Cable.settings.on_error.call(e, "IO::Error: #{e.message} -> #{self.class.name}#close")
80+
Cable.settings.on_error.call(e, "IO::Error: #{e.message} -> #{self.class.name}#close", self)
8181
end
8282
unsubscribe_from_internal_channel
8383
end
@@ -185,7 +185,7 @@ module Cable
185185
Cable::Logger.info { "#{channel.class}#receive(#{payload.data})" }
186186
channel.receive(payload.data)
187187
rescue e : TypeCastError
188-
Cable.settings.on_error.call(e, "Exception: #{e.message} -> #{self.class.name}#message(payload) { #{payload.inspect} }")
188+
Cable.settings.on_error.call(e, "Exception: #{e.message} -> #{self.class.name}#message(payload) { #{payload.inspect} }", self)
189189
end
190190
end
191191
end

src/cable/handler.cr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ module Cable
5151
ws_pinger.stop
5252
socket.close(HTTP::WebSocket::CloseCode::InvalidFramePayloadData, "Invalid message")
5353
Cable.server.remove_connection(connection_id)
54-
Cable.settings.on_error.call(e, "Cable::Handler#socket.on_message")
54+
Cable.settings.on_error.call(e, "Cable::Handler#socket.on_message -> #{message}", connection)
5555
rescue e : Cable::Connection::UnauthorizedConnectionException
5656
# handle unauthorized connections
5757
# no need to log them
@@ -69,7 +69,7 @@ module Cable
6969
# handle restart
7070
Cable.server.count_error!
7171
Cable.restart if Cable.server.restart?
72-
Cable.settings.on_error.call(e, "Cable::Handler#socket.on_message")
72+
Cable.settings.on_error.call(e, "Cable::Handler#socket.on_message -> #{message}", connection)
7373
end
7474
end
7575

@@ -84,7 +84,7 @@ module Cable
8484
if conn_id = connection_id
8585
Cable.server.remove_connection(conn_id)
8686
end
87-
Cable.settings.on_error.call(e, "Cable::Handler#call -> HTTP::WebSocketHandler")
87+
Cable.settings.on_error.call(e, "Cable::Handler#call -> HTTP::WebSocketHandler", connection)
8888
raise e
8989
end
9090

src/cable/server.cr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ module Cable
5353
subscribe
5454
process_subscribed_messages
5555
rescue e
56-
Cable.settings.on_error.call(e, "Cable::Server.initialize")
56+
Cable.settings.on_error.call(e, "Cable::Server.initialize", nil)
5757
raise e
5858
end
5959
end
@@ -151,7 +151,7 @@ module Cable
151151
end
152152
end
153153
rescue e : IO::Error
154-
Cable.settings.on_error.call(e, "IO::Error Exception: #{e.message}: #{parsed_message} -> Cable::Server#send_to_channels(channel, message)")
154+
Cable.settings.on_error.call(e, "IO::Error Exception: #{e.message}: #{parsed_message} -> Cable::Server#send_to_channels(channel, message)", nil)
155155
end
156156
end
157157

0 commit comments

Comments
 (0)