Skip to content

Commit 90fc583

Browse files
committed
minor symfony#13699 Describe how to get a stack trace with Symfony (greg0ire)
This PR was submitted for the master branch but it was merged into the 4.4 branch instead. Discussion ---------- Describe how to get a stack trace with Symfony As a maintainer, I often struggle to get stack traces in bug reports. I miss a good resource to describe how to do it with Symfony. This aims at showing developers how to do that, but also to help them understand more about stack traces. This PR does not fix a bug, nor does it document a new feature, so I'm not sure which branch I should target here. Commits ------- d0a97ae Describe how to get a stack trace with Symfony
2 parents ebbd092 + d0a97ae commit 90fc583

File tree

5 files changed

+195
-1
lines changed

5 files changed

+195
-1
lines changed
737 KB
Loading

contributing/code/bugs.rst

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ If your problem definitely looks like a bug, report it using the official bug
3333
* Give as much detail as possible about your environment (OS, PHP version,
3434
Symfony version, enabled extensions, ...);
3535

36-
* If you want to provide a stack trace you got on an HTML page, be sure to
36+
* If there was an exception and you would like to report it, it is
37+
valuable to provide the :doc:`stack trace
38+
</contributing/code/stack_trace>` for that exception.
39+
If you want to provide a stack trace you got on an HTML page, be sure to
3740
provide the plain text version, which should appear at the bottom of the
3841
page. *Do not* provide it as a screenshot, since search engines will not be
3942
able to index the text inside them. Same goes for errors encountered in a

contributing/code/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Contributing Code
55
:maxdepth: 2
66

77
bugs
8+
stack_trace
89
reproducer
910
pull_requests
1011
maintenance

contributing/code/stack_trace.rst

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
Getting a Stack Trace
2+
=====================
3+
4+
When :doc:`reporting a bug </contributing/code/bugs>` for an
5+
exception or a wrong behavior in code, it is crucial that you provide
6+
one or several stack traces. To understand why, you first have to
7+
understand what a stack trace is, and how it can be useful to you as a
8+
developer, and also to library maintainers.
9+
10+
Anatomy of a Stack Trace
11+
------------------------
12+
13+
A stack trace is called that way because it allows one to see a trail of
14+
function calls leading to a point in code since the beginning of the
15+
program. That point is not necessarily an exception. For instance, you
16+
can use the native PHP function ``debug_print_backtrace()`` to get such
17+
a trace. For each line in the trace, you get a file and a function or
18+
method call, and the line number for that call. This is often of great
19+
help for understanding the flow of your program and how it can end up in
20+
unexpected places, such as lines of code where exceptions are thrown.
21+
22+
Stack Traces and Exceptions
23+
---------------------------
24+
25+
In PHP, every exception comes with its own stack trace, which is
26+
displayed by default if the exception is not caught. When using Symfony,
27+
such exceptions go through a custom exception handler, which enhances
28+
them in various ways before displaying them according to the current
29+
Server API (CLI or not).
30+
This means a better way to get a stack trace when you do need the
31+
program to continue is to throw an exception, as follows:
32+
``throw new \Exception();``
33+
34+
Nested Exceptions
35+
-----------------
36+
37+
When applications get bigger, complexity is often tackled with layers of
38+
architecture that need to be kept separate. For instance, if you have a
39+
web application that makes a call to a remote API, it might be good to
40+
wrap exceptions thrown when making that call with exceptions that have
41+
special meaning in your domain, and to build appropriate HTTP exceptions
42+
from those. Exceptions can be nested by using the ``$previous``
43+
argument that appears in the signature of the ``Exception`` class:
44+
``public __construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]] )``
45+
This means that sometimes, when you get an exception from an
46+
application, you might actually get several of them.
47+
48+
What to look for in a Stack Trace
49+
---------------------------------
50+
51+
When using a library, you will call code that you did not write. When
52+
using a framework, it is the opposite: because you follow the
53+
conventions of the framework, `the framework finds your code and calls
54+
it <https://en.wikipedia.org/wiki/Inversion_of_control>`_, and does
55+
things for you beforehand, like routing or access control.
56+
Symfony being both a framework and library of components, it calls your
57+
code and then your code might call it. This means you will always have
58+
at least 2 parts, very often 3 in your stack traces when using Symfony:
59+
a part that starts in one of the entrypoints of the framework
60+
(``bin/console`` or ``public/index.php`` in most cases), and ends when
61+
reaching your code, most times in a command or in a controller found under
62+
``src``. Then, either the exception is thrown in your code or in
63+
libraries you call. If it is the latter, there should be a third part in
64+
the stack trace with calls made in files under ``vendor``. Before
65+
landing in that directory, code goes through numerous review processes
66+
and CI pipelines, which means it should be less likely to be the source
67+
of the issue than code from your application, so it is important that
68+
you focus first on lines starting with ``src``, and look for anything
69+
suspicious or unexpected, like method calls that are not supposed to
70+
happen.
71+
72+
Next, you can have a look at what packages are involved. Files under
73+
``vendor`` are organized by Composer in the following way:
74+
``vendor/acme/router`` where ``acme`` is the vendor, ``router`` the
75+
library and ``acme/router`` the Composer package. If you plan on
76+
reporting the bug, make sure to report it to the library throwing the
77+
exception. ``composer home acme/router`` should lead you to the right
78+
place for that. As Symfony is a monorepository, use ``composer home
79+
symfony/symfony`` when reporting a bug for any component.
80+
81+
Getting Stack Traces with Symfony
82+
---------------------------------
83+
84+
Now that we have all this in mind, let us see how to get a stack trace
85+
with Symfony.
86+
87+
Stack Traces in your Web Browser
88+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
89+
90+
Several things need to be paid attention to when picking a stack trace
91+
from your development environment through a web browser:
92+
93+
1. Are there several exceptions? If yes, the most interesting one is
94+
often exception 1/n which, is shown _last_ in the example below (it
95+
is the one marked as exception [1/2]).
96+
2. Under the "Stack Traces" tab, you will find exceptions in plain
97+
text, so that you can easily share them in e.g. bug reports. Make
98+
sure to **remove any sensitive information** before doing so.
99+
3. You may notice there is a logs tab too; this tab does not have to do
100+
with stack traces, it only contains logs produced in arbitrary places
101+
in your application. They may or may not relate to the exception you
102+
are getting, but are not what the term "stack trace" refers to.
103+
104+
.. image:: /_images/contributing/code/stack-trace.gif
105+
:align: center
106+
:class: with-browser
107+
108+
Since stack traces may contain sensitive data, they should not be
109+
exposed in production. Getting a stack trace from your production
110+
environment, although more involving, is still possible with solutions
111+
that include but are not limited to sending them to an email address
112+
with monolog.
113+
114+
Stack Traces in the CLI
115+
~~~~~~~~~~~~~~~~~~~~~~~
116+
117+
Exceptions might occur when running a Symfony command. By default, only
118+
the message is shown because it is often enough to understand what is
119+
going on:
120+
121+
.. code-block:: terminal
122+
123+
$ php bin/console debug:exception
124+
125+
126+
Command "debug:exception" is not defined.
127+
128+
Did you mean one of these?
129+
debug:autowiring
130+
debug:config
131+
debug:container
132+
debug:event-dispatcher
133+
debug:form
134+
debug:router
135+
debug:translation
136+
debug:twig
137+
138+
139+
If that is not the case, you can obtain a stack trace by increasing the
140+
:doc:`verbosity level</console/verbosity>` with ``--verbose``:
141+
142+
.. code-block:: terminal
143+
144+
$ php bin/console --verbose debug:exception
145+
146+
In Application.php line 644:
147+
148+
[Symfony\Component\Console\Exception\CommandNotFoundException]
149+
Command "debug:exception" is not defined.
150+
151+
Did you mean one of these?
152+
debug:autowiring
153+
debug:config
154+
debug:container
155+
debug:event-dispatcher
156+
debug:form
157+
debug:router
158+
debug:translation
159+
debug:twig
160+
161+
162+
Exception trace:
163+
at /app/vendor/symfony/console/Application.php:644
164+
Symfony\Component\Console\Application->find() at /app/vendor/symfony/framework-bundle/Console/Application.php:116
165+
Symfony\Bundle\FrameworkBundle\Console\Application->find() at /app/vendor/symfony/console/Application.php:228
166+
Symfony\Component\Console\Application->doRun() at /app/vendor/symfony/framework-bundle/Console/Application.php:82
167+
Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /app/vendor/symfony/console/Application.php:140
168+
Symfony\Component\Console\Application->run() at /app/bin/console:42
169+
170+
Stack Traces and API Calls
171+
~~~~~~~~~~~~~~~~~~~~~~~~~~
172+
173+
When getting an exception from an API, you might not get a stack trace,
174+
or it might be displayed in a way that is not suitable for sharing.
175+
Luckily, when in the dev environment, you can obtain a plain text stack
176+
trace by using the profiler. To find the profile, you can have a look
177+
at the ``X-Debug-Token-Link`` response headers:
178+
179+
.. code-block:: terminal
180+
181+
$ curl --head http://localhost:8000/api/posts/1
182+
… more headers
183+
X-Debug-Token: 110e1e
184+
X-Debug-Token-Link: http://localhost:8000/_profiler/110e1e
185+
X-Robots-Tag: noindex
186+
X-Previous-Debug-Token: 209101
187+
188+
Following that link will lead you to a page very similar to the one
189+
described above in `Stack Traces in your Web Browser`_.

contributing/map.rst.inc

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* **Code**
99

1010
* :doc:`Bugs </contributing/code/bugs>`
11+
* :doc:`Getting a Stack Trace </contributing/code/stack_trace>`
1112
* :doc:`Pull Requests </contributing/code/pull_requests>`
1213
* :doc:`Reviewing Issues and Pull Requests </contributing/community/reviews>`
1314
* :doc:`Maintenance </contributing/code/maintenance>`

0 commit comments

Comments
 (0)