Add `lifetime` option
diff --git a/src/passage.erl b/src/passage.erl
index f7dde8b..f44a8d2 100644
--- a/src/passage.erl
+++ b/src/passage.erl
@@ -133,9 +133,11 @@
 -type finish_span_options() :: [finish_span_option()].
 %% Options for {@link finish_span/2}.
 
--type finish_span_option() :: {time, erlang:timestamp()}.
+-type finish_span_option() :: {time, erlang:timestamp()}
+                            | {lifetime, pid()}.
 %% <ul>
 %%   <li><b>time</b>: Finish timestamp of the span. The default value is `erlang:timestamp()'.</li>
+%%   <li><b>lifetime</b>: If this option is specified, the report of the finished span will be delayed until the lifetime process exits.</li>
 %% </ul>
 
 -type log_options() :: [log_option()].
@@ -204,7 +206,15 @@
 -spec finish_span(maybe_span(), finish_span_options()) -> ok.
 finish_span(undefined, _)  -> ok;
 finish_span(Span, Options) ->
-    passage_span:finish(Span, Options).
+    case lists:keyfind(lifetime, 1, Options) of
+        false    -> passage_span:finish(Span, Options);
+        {_, Pid} ->
+            spawn(fun () ->
+                          Monitor = monitor(process, Pid),
+                          finish_span_when_process_exits(Monitor, Span, Options)
+                  end),
+            ok
+    end.
 
 %% @doc Sets the operation name of `Span' to `Name'.
 -spec set_operation_name(maybe_span(), operation_name()) -> maybe_span().
@@ -281,3 +291,29 @@
                 {ok, Context} -> passage_span:make_extracted_span(Tracer, Context)
             end
     end.
+
+%%------------------------------------------------------------------------------
+%% Interal Functions
+%%------------------------------------------------------------------------------
+-spec finish_span_when_process_exits(
+        reference(), passage_span:span(), finish_span_options()) -> ok.
+finish_span_when_process_exits(Monitor, Span0, Options) ->
+    receive
+        {'DOWN', Monitor, _, _, Reason} ->
+            IsError =
+                case Reason of
+                    normal        -> false;
+                    shutdown      -> false;
+                    {shutdown, _} -> false;
+                    _             -> true
+                end,
+            Span1 = log(Span0, #{?LOG_FIELD_EVENT => exit, 'exit.reason' => Reason}),
+            Span2 =
+                case IsError of
+                    false -> Span1;
+                    true  -> set_tags(Span1, #{?TAG_ERROR => true})
+                end,
+            passage_span:finish(Span2, Options);
+        _ ->
+            finish_span_when_process_exits(Monitor, Span0, Options)
+    end.
diff --git a/test/passage_tests.erl b/test/passage_tests.erl
index 044d1fd..327b801 100644
--- a/test/passage_tests.erl
+++ b/test/passage_tests.erl
@@ -107,6 +107,22 @@
                ?assertEqual(#{error => true},
                             passage_span:get_tags(FinishedSpan))
        end},
+      {"lifetime",
+       fun () ->
+               ok = start_test_tracer(),
+               Span = passage:start_span(root, [{tracer, test_tracer}]),
+               Pid = spawn(timer, sleep, [infinity]),
+               passage:finish_span(Span, [{lifetime, Pid}]),
+
+               ?assertEqual([], finished_spans()),
+
+               exit(Pid, kill),
+               monitor(process, Pid),
+               receive {'DOWN', _, _, Pid, _} -> ok end,
+               timer:sleep(1),
+
+               ?assertMatch([_], finished_spans())
+       end},
       {"'sampling.priority' = 0",
        fun () ->
                ok = start_test_tracer(),