Skip to content

Commit 5f53b95

Browse files
FelonEkonomvarsill
andauthored
Ensure error logs are always printed (#822)
* Add macro ensuring errors are logged * mix format * Refactor logs * Fix small bug * Update lib/membrane/core/macros.ex Co-authored-by: Łukasz Kita <lukasz.kita0@gmail.com> * Implement CR suggestions * Remove leftover * Release v1.1.0 --------- Co-authored-by: Łukasz Kita <lukasz.kita0@gmail.com>
1 parent c7afa10 commit 5f53b95

16 files changed

+328
-206
lines changed

CHANGELOG.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
# Changelog
22

3-
## 1.1.0-rc1
3+
## 1.1.0
44
* Add new callbacks `handle_child_setup_completed/3` and `handle_child_playing/3` in Bins and Pipelines. [#801](https://github.com/membraneframework/membrane_core/pull/801)
5-
6-
## 1.1.0-rc0
75
* Deprecate `handle_spec_started/3` callback in Bins and Pipelines. [#708](https://github.com/membraneframework/membrane_core/pull/708)
86
* Handle buffers from input pads having `flow_control: :auto` only if demand on all output pads having `flow_control: :auto` is positive. [#693](https://github.com/membraneframework/membrane_core/pull/693)
97
* Set `:ratio` dependency version to `"~> 3.0 or ~> 4.0"`. [#780](https://github.com/membraneframework/membrane_core/pull/780)

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ Apart from plugins, Membrane has stream formats, which live in `membrane_X_forma
9292
The API for creating pipelines (and custom elements too) is provided by [membrane_core](https://github.com/membraneframework/membrane_core). To install it, add the following line to your `deps` in `mix.exs` and run `mix deps.get`
9393

9494
```elixir
95-
{:membrane_core, "~> 1.0"}
95+
{:membrane_core, "~> 1.1"}
9696
```
9797

9898
**Standalone libraries**

lib/membrane/clock.ex

+28-13
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ defmodule Membrane.Clock do
3232
alias Membrane.Core.Message
3333
alias Membrane.Time
3434

35+
require Membrane.Core.Utils, as: Utils
36+
3537
@typedoc @moduledoc
3638
@type t :: pid
3739

@@ -115,6 +117,12 @@ defmodule Membrane.Clock do
115117

116118
@impl GenServer
117119
def init(options) do
120+
Utils.log_on_error do
121+
do_init(options)
122+
end
123+
end
124+
125+
defp do_init(options) do
118126
proxy_opts = get_proxy_options(options[:proxy], options[:proxy_for])
119127

120128
state =
@@ -131,7 +139,13 @@ defmodule Membrane.Clock do
131139
end
132140

133141
@impl GenServer
134-
def handle_cast({:proxy_for, proxy_for}, %{proxy: true} = state) do
142+
def handle_cast(request, state) do
143+
Utils.log_on_error do
144+
do_handle_cast(request, state)
145+
end
146+
end
147+
148+
defp do_handle_cast({:proxy_for, proxy_for}, %{proxy: true} = state) do
135149
if state.proxy_for, do: unsubscribe(state.proxy_for)
136150

137151
state = %{state | proxy_for: proxy_for}
@@ -147,8 +161,7 @@ defmodule Membrane.Clock do
147161
{:noreply, state}
148162
end
149163

150-
@impl GenServer
151-
def handle_cast({:clock_subscribe, pid}, state) do
164+
defp do_handle_cast({:clock_subscribe, pid}, state) do
152165
state
153166
|> update_in([:subscribers, pid], fn
154167
nil ->
@@ -162,8 +175,7 @@ defmodule Membrane.Clock do
162175
~> {:noreply, &1}
163176
end
164177

165-
@impl GenServer
166-
def handle_cast({:clock_unsubscribe, pid}, state) do
178+
defp do_handle_cast({:clock_unsubscribe, pid}, state) do
167179
if Map.has_key?(state.subscribers, pid) do
168180
{subs, state} =
169181
state |> Bunch.Access.get_updated_in([:subscribers, pid, :subscriptions], &(&1 - 1))
@@ -175,24 +187,27 @@ defmodule Membrane.Clock do
175187
~> {:noreply, &1}
176188
end
177189

178-
@impl GenServer
179-
def handle_info({:membrane_clock_update, till_next}, %{proxy: false} = state) do
190+
@impl true
191+
def handle_info(msg, state) do
192+
Utils.log_on_error do
193+
do_handle_info(msg, state)
194+
end
195+
end
196+
197+
defp do_handle_info({:membrane_clock_update, till_next}, %{proxy: false} = state) do
180198
{:noreply, handle_clock_update(till_next, state)}
181199
end
182200

183-
@impl GenServer
184-
def handle_info({:membrane_clock_ratio, pid, ratio}, %{proxy: true, proxy_for: pid} = state) do
201+
defp do_handle_info({:membrane_clock_ratio, pid, ratio}, %{proxy: true, proxy_for: pid} = state) do
185202
{:noreply, broadcast_and_update_ratio(ratio, state)}
186203
end
187204

188-
@impl GenServer
189205
# When ratio from previously proxied clock comes in after unsubscribing
190-
def handle_info({:membrane_clock_ratio, _pid, _ratio}, %{proxy: true} = state) do
206+
defp do_handle_info({:membrane_clock_ratio, _pid, _ratio}, %{proxy: true} = state) do
191207
{:noreply, state}
192208
end
193209

194-
@impl GenServer
195-
def handle_info({:DOWN, _ref, :process, pid, _reason}, state) do
210+
defp do_handle_info({:DOWN, _ref, :process, pid, _reason}, state) do
196211
{:noreply, handle_unsubscribe(pid, state)}
197212
end
198213

lib/membrane/core/bin.ex

+27-13
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ defmodule Membrane.Core.Bin do
1919

2020
alias Membrane.ResourceGuard
2121

22+
require Membrane.Core.Utils, as: Utils
2223
require Membrane.Core.Message
2324
require Membrane.Core.Telemetry
2425
require Membrane.Logger
@@ -79,6 +80,12 @@ defmodule Membrane.Core.Bin do
7980

8081
@impl GenServer
8182
def init(options) do
83+
Utils.log_on_error do
84+
do_init(options)
85+
end
86+
end
87+
88+
defp do_init(options) do
8289
Process.link(options.parent_supervisor)
8390
%{name: name, module: module} = options
8491

@@ -144,13 +151,17 @@ defmodule Membrane.Core.Bin do
144151

145152
@impl GenServer
146153
def handle_continue(:setup, state) do
147-
state = Parent.LifecycleController.handle_setup(state)
148-
{:noreply, state}
154+
Utils.log_on_error do
155+
state = Parent.LifecycleController.handle_setup(state)
156+
{:noreply, state}
157+
end
149158
end
150159

151160
@impl GenServer
152161
def handle_info(message, state) do
153-
do_handle_info(message, state)
162+
Utils.log_on_error do
163+
do_handle_info(message, state)
164+
end
154165
end
155166

156167
@compile {:inline, do_handle_info: 2}
@@ -162,7 +173,6 @@ defmodule Membrane.Core.Bin do
162173

163174
defp do_handle_info(Message.new(:parent_notification, notification), state) do
164175
state = Child.LifecycleController.handle_parent_notification(notification, state)
165-
166176
{:noreply, state}
167177
end
168178

@@ -251,22 +261,26 @@ defmodule Membrane.Core.Bin do
251261
end
252262

253263
@impl GenServer
254-
def handle_call(
255-
Message.new(:handle_link, [direction, this, other, params]),
256-
_from,
257-
state
258-
) do
264+
def handle_call(request, from, state) do
265+
Utils.log_on_error do
266+
do_handle_call(request, from, state)
267+
end
268+
end
269+
270+
defp do_handle_call(
271+
Message.new(:handle_link, [direction, this, other, params]),
272+
_from,
273+
state
274+
) do
259275
{reply, state} = PadController.handle_link(direction, this, other, params, state)
260276
{:reply, reply, state}
261277
end
262278

263-
@impl GenServer
264-
def handle_call(Message.new(:get_clock), _from, state) do
279+
defp do_handle_call(Message.new(:get_clock), _from, state) do
265280
{:reply, state.synchronization.clock, state}
266281
end
267282

268-
@impl GenServer
269-
def handle_call(Message.new(:get_child_pid, child_name), _from, state) do
283+
defp do_handle_call(Message.new(:get_child_pid, child_name), _from, state) do
270284
reply =
271285
with %State{children: %{^child_name => %{pid: child_pid}}} <- state do
272286
{:ok, child_pid}

lib/membrane/core/callback_handler.ex

+2-22
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,6 @@ defmodule Membrane.Core.CallbackHandler do
185185
Error handling actions returned by callback #{inspect(state.module)}.#{callback}
186186
""")
187187

188-
log_debug_orginal_error(actions, e, __STACKTRACE__)
189-
190188
reraise e, __STACKTRACE__
191189
end
192190

@@ -197,32 +195,14 @@ defmodule Membrane.Core.CallbackHandler do
197195
rescue
198196
e ->
199197
Membrane.Logger.error("""
200-
Error handling action #{inspect(action)} returned by callback #{inspect(state.module)}.#{callback}
198+
Error handling action returned by callback #{inspect(state.module)}.#{callback}.
199+
Action: #{inspect(action, pretty: true)}
201200
""")
202201

203-
log_debug_orginal_error(action, e, __STACKTRACE__)
204-
205202
reraise e, __STACKTRACE__
206203
end
207204
end)
208205

209206
handler_module.handle_end_of_actions(state)
210207
end
211-
212-
# We log it, because sometimes, for some reason, crashing process doesn't cause
213-
# printing error logs on stderr, so this debug log allows us to get some info
214-
# about what happened in case of process crash
215-
defp log_debug_orginal_error(action_or_actions, error, stacktrace) do
216-
action_or_actions =
217-
if(is_list(action_or_actions), do: "actions ", else: "action ") <>
218-
inspect(action_or_actions, limit: :infinity)
219-
220-
Membrane.Logger.debug("""
221-
Error while handling #{action_or_actions}
222-
223-
Orginal error:
224-
#{inspect(error, pretty: true, limit: :infinity)}
225-
#{Exception.format_stacktrace(stacktrace)}
226-
""")
227-
end
228208
end

lib/membrane/core/element.ex

+33-20
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ defmodule Membrane.Core.Element do
3535

3636
alias Membrane.Core.{SubprocessSupervisor, TimerController}
3737

38+
require Membrane.Core.Utils, as: Utils
3839
require Membrane.Core.Message, as: Message
3940
require Membrane.Core.Stalker, as: Stalker
4041
require Membrane.Core.Telemetry, as: Telemetry
@@ -94,6 +95,12 @@ defmodule Membrane.Core.Element do
9495

9596
@impl GenServer
9697
def init(options) do
98+
Utils.log_on_error do
99+
do_init(options)
100+
end
101+
end
102+
103+
defp do_init(options) do
97104
Process.link(options.parent_supervisor)
98105

99106
observability_config = %{
@@ -155,50 +162,56 @@ defmodule Membrane.Core.Element do
155162

156163
@impl GenServer
157164
def handle_continue(:setup, state) do
158-
state = LifecycleController.handle_setup(state)
159-
{:noreply, state}
165+
Utils.log_on_error do
166+
state = LifecycleController.handle_setup(state)
167+
{:noreply, state}
168+
end
160169
end
161170

162171
@impl GenServer
163-
def handle_call(Message.new(:get_clock), _from, state) do
172+
def handle_call(request, from, state) do
173+
Utils.log_on_error do
174+
do_handle_call(request, from, state)
175+
end
176+
end
177+
178+
defp do_handle_call(Message.new(:get_clock), _from, state) do
164179
{:reply, state.synchronization.clock, state}
165180
end
166181

167-
@impl GenServer
168-
def handle_call(
169-
Message.new(:handle_link, [direction, this, other, params]),
170-
_from,
171-
state
172-
) do
182+
defp do_handle_call(
183+
Message.new(:handle_link, [direction, this, other, params]),
184+
_from,
185+
state
186+
) do
173187
{reply, state} = PadController.handle_link(direction, this, other, params, state)
174188
{:reply, reply, state}
175189
end
176190

177-
@impl GenServer
178-
def handle_call(Message.new(:set_stream_sync, sync), _from, state) do
191+
defp do_handle_call(Message.new(:set_stream_sync, sync), _from, state) do
179192
state = put_in(state.synchronization.stream_sync, sync)
180193
{:reply, :ok, state}
181194
end
182195

183-
@impl GenServer
184-
def handle_call(Message.new(:get_child_pid, _child_name), _from, state) do
196+
defp do_handle_call(Message.new(:get_child_pid, _child_name), _from, state) do
185197
{:reply, {:error, :element_cannot_have_children}, state}
186198
end
187199

188-
@impl GenServer
189-
def handle_call(message, {pid, _tag}, _state) do
200+
defp do_handle_call(message, {pid, _tag}, _state) do
190201
raise Membrane.ElementError,
191202
"Received invalid message #{inspect(message)} from #{inspect(pid)}"
192203
end
193204

194205
@impl GenServer
195206
def handle_info(message, state) do
196-
Telemetry.report_metric(
197-
:queue_len,
198-
:erlang.process_info(self(), :message_queue_len) |> elem(1)
199-
)
207+
Utils.log_on_error do
208+
Telemetry.report_metric(
209+
:queue_len,
210+
:erlang.process_info(self(), :message_queue_len) |> elem(1)
211+
)
200212

201-
do_handle_info(message, state)
213+
do_handle_info(message, state)
214+
end
202215
end
203216

204217
@compile {:inline, do_handle_info: 2}

lib/membrane/core/element/atomic_demand/distributed_atomic/worker.ex

+18-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ defmodule Membrane.Core.Element.AtomicDemand.DistributedAtomic.Worker do
66

77
use GenServer
88

9+
require Membrane.Core.Utils, as: Utils
10+
911
@type t :: pid()
1012

1113
@spec start_link(any()) :: {:ok, t}
@@ -18,25 +20,33 @@ defmodule Membrane.Core.Element.AtomicDemand.DistributedAtomic.Worker do
1820

1921
@impl true
2022
def handle_call({:add_get, atomic_ref, value}, _from, _state) do
21-
result = :atomics.add_get(atomic_ref, 1, value)
22-
{:reply, result, nil}
23+
Utils.log_on_error do
24+
result = :atomics.add_get(atomic_ref, 1, value)
25+
{:reply, result, nil}
26+
end
2327
end
2428

2529
@impl true
2630
def handle_call({:sub_get, atomic_ref, value}, _from, _state) do
27-
result = :atomics.sub_get(atomic_ref, 1, value)
28-
{:reply, result, nil}
31+
Utils.log_on_error do
32+
result = :atomics.sub_get(atomic_ref, 1, value)
33+
{:reply, result, nil}
34+
end
2935
end
3036

3137
@impl true
3238
def handle_call({:get, atomic_ref}, _from, _state) do
33-
result = :atomics.get(atomic_ref, 1)
34-
{:reply, result, nil}
39+
Utils.log_on_error do
40+
result = :atomics.get(atomic_ref, 1)
41+
{:reply, result, nil}
42+
end
3543
end
3644

3745
@impl true
3846
def handle_cast({:put, atomic_ref, value}, _state) do
39-
:atomics.put(atomic_ref, 1, value)
40-
{:noreply, nil}
47+
Utils.log_on_error do
48+
:atomics.put(atomic_ref, 1, value)
49+
{:noreply, nil}
50+
end
4151
end
4252
end

0 commit comments

Comments
 (0)