prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Document LogFormatter
  Currently, the `LogFormatter` class is only mentioned in the [Release notes](https://docs.scrapy.org/en/latest/news.html) page of the documentation. This class should be properly documented, both its API members and a small section introducing it on the documentation page about [Logging](https://docs.scrapy.org/en/latest/topics/logging.html).
  
  The responses to [Scrapy - Silently drop an item](https://stackoverflow.com/q/13527921/939364) in StackOverflow would be a good starting point.
  
  </issue>
  <code>
  [start of scrapy/logformatter.py]
  1 import os
  2 import logging
  3 
  4 from twisted.python.failure import Failure
  5 
  6 from scrapy.utils.request import referer_str
  7 
  8 SCRAPEDMSG = u"Scraped from %(src)s" + os.linesep + "%(item)s"
  9 DROPPEDMSG = u"Dropped: %(exception)s" + os.linesep + "%(item)s"
  10 CRAWLEDMSG = u"Crawled (%(status)s) %(request)s%(request_flags)s (referer: %(referer)s)%(response_flags)s"
  11 
  12 
  13 class LogFormatter(object):
  14     """Class for generating log messages for different actions.
  15 
  16     All methods must return a dictionary listing the parameters ``level``,
  17     ``msg`` and ``args`` which are going to be used for constructing the log
  18     message when calling logging.log.
  19 
  20     Dictionary keys for the method outputs:
  21         * ``level`` should be the log level for that action, you can use those
  22         from the python logging library: logging.DEBUG, logging.INFO,
  23         logging.WARNING, logging.ERROR and logging.CRITICAL.
  24 
  25         * ``msg`` should be a string that can contain different formatting
  26         placeholders. This string, formatted with the provided ``args``, is
  27         going to be the log message for that action.
  28 
  29         * ``args`` should be a tuple or dict with the formatting placeholders
  30         for ``msg``.  The final log message is computed as output['msg'] %
  31         output['args'].
  32     """
  33 
  34     def crawled(self, request, response, spider):
  35         request_flags = ' %s' % str(request.flags) if request.flags else ''
  36         response_flags = ' %s' % str(response.flags) if response.flags else ''
  37         return {
  38             'level': logging.DEBUG,
  39             'msg': CRAWLEDMSG,
  40             'args': {
  41                 'status': response.status,
  42                 'request': request,
  43                 'request_flags' : request_flags,
  44                 'referer': referer_str(request),
  45                 'response_flags': response_flags,
  46                 # backward compatibility with Scrapy logformatter below 1.4 version
  47                 'flags': response_flags
  48             }
  49         }
  50 
  51     def scraped(self, item, response, spider):
  52         if isinstance(response, Failure):
  53             src = response.getErrorMessage()
  54         else:
  55             src = response
  56         return {
  57             'level': logging.DEBUG,
  58             'msg': SCRAPEDMSG,
  59             'args': {
  60                 'src': src,
  61                 'item': item,
  62             }
  63         }
  64 
  65     def dropped(self, item, exception, response, spider):
  66         return {
  67             'level': logging.WARNING,
  68             'msg': DROPPEDMSG,
  69             'args': {
  70                 'exception': exception,
  71                 'item': item,
  72             }
  73         }
  74 
  75     @classmethod
  76     def from_crawler(cls, crawler):
  77         return cls()
  78
  [end of scrapy/logformatter.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/scrapy/logformatter.py b/scrapy/logformatter.py
  --- a/scrapy/logformatter.py
  +++ b/scrapy/logformatter.py
  @@ -12,26 +12,40 @@
   
   class LogFormatter(object):
       """Class for generating log messages for different actions.
  -
  -    All methods must return a dictionary listing the parameters ``level``,
  -    ``msg`` and ``args`` which are going to be used for constructing the log
  -    message when calling logging.log.
  +    
  +    All methods must return a dictionary listing the parameters ``level``, ``msg``
  +    and ``args`` which are going to be used for constructing the log message when
  +    calling ``logging.log``.
   
       Dictionary keys for the method outputs:
  -        * ``level`` should be the log level for that action, you can use those
  -        from the python logging library: logging.DEBUG, logging.INFO,
  -        logging.WARNING, logging.ERROR and logging.CRITICAL.
   
  -        * ``msg`` should be a string that can contain different formatting
  -        placeholders. This string, formatted with the provided ``args``, is
  -        going to be the log message for that action.
  +    *   ``level`` is the log level for that action, you can use those from the
  +        `python logging library <https://docs.python.org/3/library/logging.html>`_ :
  +        ``logging.DEBUG``, ``logging.INFO``, ``logging.WARNING``, ``logging.ERROR``
  +        and ``logging.CRITICAL``.
  +    *   ``msg`` should be a string that can contain different formatting placeholders.
  +        This string, formatted with the provided ``args``, is going to be the long message
  +        for that action.
  +    *   ``args`` should be a tuple or dict with the formatting placeholders for ``msg``.
  +        The final log message is computed as ``msg % args``.
   
  -        * ``args`` should be a tuple or dict with the formatting placeholders
  -        for ``msg``.  The final log message is computed as output['msg'] %
  -        output['args'].
  -    """
  +    Here is an example on how to create a custom log formatter to lower the severity level of
  +    the log message when an item is dropped from the pipeline::
   
  +            class PoliteLogFormatter(logformatter.LogFormatter):
  +                def dropped(self, item, exception, response, spider):
  +                    return {
  +                        'level': logging.INFO, # lowering the level from logging.WARNING
  +                        'msg': u"Dropped: %(exception)s" + os.linesep + "%(item)s",
  +                        'args': {
  +                            'exception': exception,
  +                            'item': item,
  +                        }
  +                    }
  +    """
  +    
       def crawled(self, request, response, spider):
  +        """Logs a message when the crawler finds a webpage."""
           request_flags = ' %s' % str(request.flags) if request.flags else ''
           response_flags = ' %s' % str(response.flags) if response.flags else ''
           return {
  @@ -40,7 +54,7 @@
               'args': {
                   'status': response.status,
                   'request': request,
  -                'request_flags' : request_flags,
  +                'request_flags': request_flags,
                   'referer': referer_str(request),
                   'response_flags': response_flags,
                   # backward compatibility with Scrapy logformatter below 1.4 version
  @@ -49,6 +63,7 @@
           }
   
       def scraped(self, item, response, spider):
  +        """Logs a message when an item is scraped by a spider."""
           if isinstance(response, Failure):
               src = response.getErrorMessage()
           else:
  @@ -63,6 +78,7 @@
           }
   
       def dropped(self, item, exception, response, spider):
  +        """Logs a message when an item is dropped while it is passing through the item pipeline."""
           return {
               'level': logging.WARNING,
               'msg': DROPPEDMSG,
  
verification_info: {"golden_diff": "diff --git a/scrapy/logformatter.py b/scrapy/logformatter.py\n--- a/scrapy/logformatter.py\n+++ b/scrapy/logformatter.py\n@@ -12,26 +12,40 @@\n \n class LogFormatter(object):\n     \"\"\"Class for generating log messages for different actions.\n-\n-    All methods must return a dictionary listing the parameters ``level``,\n-    ``msg`` and ``args`` which are going to be used for constructing the log\n-    message when calling logging.log.\n+    \n+    All methods must return a dictionary listing the parameters ``level``, ``msg``\n+    and ``args`` which are going to be used for constructing the log message when\n+    calling ``logging.log``.\n \n     Dictionary keys for the method outputs:\n-        * ``level`` should be the log level for that action, you can use those\n-        from the python logging library: logging.DEBUG, logging.INFO,\n-        logging.WARNING, logging.ERROR and logging.CRITICAL.\n \n-        * ``msg`` should be a string that can contain different formatting\n-        placeholders. This string, formatted with the provided ``args``, is\n-        going to be the log message for that action.\n+    *   ``level`` is the log level for that action, you can use those from the\n+        `python logging library <https://docs.python.org/3/library/logging.html>`_ :\n+        ``logging.DEBUG``, ``logging.INFO``, ``logging.WARNING``, ``logging.ERROR``\n+        and ``logging.CRITICAL``.\n+    *   ``msg`` should be a string that can contain different formatting placeholders.\n+        This string, formatted with the provided ``args``, is going to be the long message\n+        for that action.\n+    *   ``args`` should be a tuple or dict with the formatting placeholders for ``msg``.\n+        The final log message is computed as ``msg % args``.\n \n-        * ``args`` should be a tuple or dict with the formatting placeholders\n-        for ``msg``.  The final log message is computed as output['msg'] %\n-        output['args'].\n-    \"\"\"\n+    Here is an example on how to create a custom log formatter to lower the severity level of\n+    the log message when an item is dropped from the pipeline::\n \n+            class PoliteLogFormatter(logformatter.LogFormatter):\n+                def dropped(self, item, exception, response, spider):\n+                    return {\n+                        'level': logging.INFO, # lowering the level from logging.WARNING\n+                        'msg': u\"Dropped: %(exception)s\" + os.linesep + \"%(item)s\",\n+                        'args': {\n+                            'exception': exception,\n+                            'item': item,\n+                        }\n+                    }\n+    \"\"\"\n+    \n     def crawled(self, request, response, spider):\n+        \"\"\"Logs a message when the crawler finds a webpage.\"\"\"\n         request_flags = ' %s' % str(request.flags) if request.flags else ''\n         response_flags = ' %s' % str(response.flags) if response.flags else ''\n         return {\n@@ -40,7 +54,7 @@\n             'args': {\n                 'status': response.status,\n                 'request': request,\n-                'request_flags' : request_flags,\n+                'request_flags': request_flags,\n                 'referer': referer_str(request),\n                 'response_flags': response_flags,\n                 # backward compatibility with Scrapy logformatter below 1.4 version\n@@ -49,6 +63,7 @@\n         }\n \n     def scraped(self, item, response, spider):\n+        \"\"\"Logs a message when an item is scraped by a spider.\"\"\"\n         if isinstance(response, Failure):\n             src = response.getErrorMessage()\n         else:\n@@ -63,6 +78,7 @@\n         }\n \n     def dropped(self, item, exception, response, spider):\n+        \"\"\"Logs a message when an item is dropped while it is passing through the item pipeline.\"\"\"\n         return {\n             'level': logging.WARNING,\n             'msg': DROPPEDMSG,\n", "issue": "Document LogFormatter\nCurrently, the `LogFormatter` class is only mentioned in the [Release notes](https://docs.scrapy.org/en/latest/news.html) page of the documentation. This class should be properly documented, both its API members and a small section introducing it on the documentation page about [Logging](https://docs.scrapy.org/en/latest/topics/logging.html).\r\n\r\nThe responses to [Scrapy - Silently drop an item](https://stackoverflow.com/q/13527921/939364) in StackOverflow would be a good starting point.\n", "before_files": [{"content": "import os\nimport logging\n\nfrom twisted.python.failure import Failure\n\nfrom scrapy.utils.request import referer_str\n\nSCRAPEDMSG = u\"Scraped from %(src)s\" + os.linesep + \"%(item)s\"\nDROPPEDMSG = u\"Dropped: %(exception)s\" + os.linesep + \"%(item)s\"\nCRAWLEDMSG = u\"Crawled (%(status)s) %(request)s%(request_flags)s (referer: %(referer)s)%(response_flags)s\"\n\n\nclass LogFormatter(object):\n    \"\"\"Class for generating log messages for different actions.\n\n    All methods must return a dictionary listing the parameters ``level``,\n    ``msg`` and ``args`` which are going to be used for constructing the log\n    message when calling logging.log.\n\n    Dictionary keys for the method outputs:\n        * ``level`` should be the log level for that action, you can use those\n        from the python logging library: logging.DEBUG, logging.INFO,\n        logging.WARNING, logging.ERROR and logging.CRITICAL.\n\n        * ``msg`` should be a string that can contain different formatting\n        placeholders. This string, formatted with the provided ``args``, is\n        going to be the log message for that action.\n\n        * ``args`` should be a tuple or dict with the formatting placeholders\n        for ``msg``.  The final log message is computed as output['msg'] %\n        output['args'].\n    \"\"\"\n\n    def crawled(self, request, response, spider):\n        request_flags = ' %s' % str(request.flags) if request.flags else ''\n        response_flags = ' %s' % str(response.flags) if response.flags else ''\n        return {\n            'level': logging.DEBUG,\n            'msg': CRAWLEDMSG,\n            'args': {\n                'status': response.status,\n                'request': request,\n                'request_flags' : request_flags,\n                'referer': referer_str(request),\n                'response_flags': response_flags,\n                # backward compatibility with Scrapy logformatter below 1.4 version\n                'flags': response_flags\n            }\n        }\n\n    def scraped(self, item, response, spider):\n        if isinstance(response, Failure):\n            src = response.getErrorMessage()\n        else:\n            src = response\n        return {\n            'level': logging.DEBUG,\n            'msg': SCRAPEDMSG,\n            'args': {\n                'src': src,\n                'item': item,\n            }\n        }\n\n    def dropped(self, item, exception, response, spider):\n        return {\n            'level': logging.WARNING,\n            'msg': DROPPEDMSG,\n            'args': {\n                'exception': exception,\n                'item': item,\n            }\n        }\n\n    @classmethod\n    def from_crawler(cls, crawler):\n        return cls()\n", "path": "scrapy/logformatter.py"}]}