]> git.openstreetmap.org Git - nominatim.git/blobdiff - nominatim/api/logging.py
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / nominatim / api / logging.py
index 351da9a1d6ebe81272df4b45a09e569a9dce65da..6c8b1b388224f8a787977b15e7c2e2fce5aaab03 100644 (file)
@@ -9,6 +9,7 @@ Functions for specialised logging with HTML output.
 """
 from typing import Any, Iterator, Optional, List, Tuple, cast
 from contextvars import ContextVar
 """
 from typing import Any, Iterator, Optional, List, Tuple, cast
 from contextvars import ContextVar
+import datetime as dt
 import textwrap
 import io
 
 import textwrap
 import io
 
@@ -98,11 +99,16 @@ class HTMLLogger(BaseLogger):
         self.buffer = io.StringIO()
 
 
         self.buffer = io.StringIO()
 
 
+    def _timestamp(self) -> None:
+        self._write(f'<p class="timestamp">[{dt.datetime.now()}]</p>')
+
+
     def get_buffer(self) -> str:
         return HTML_HEADER + self.buffer.getvalue() + HTML_FOOTER
 
 
     def function(self, func: str, **kwargs: Any) -> None:
     def get_buffer(self) -> str:
         return HTML_HEADER + self.buffer.getvalue() + HTML_FOOTER
 
 
     def function(self, func: str, **kwargs: Any) -> None:
+        self._timestamp()
         self._write(f"<h1>Debug output for {func}()</h1>\n<p>Parameters:<dl>")
         for name, value in kwargs.items():
             self._write(f'<dt>{name}</dt><dd>{self._python_var(value)}</dd>')
         self._write(f"<h1>Debug output for {func}()</h1>\n<p>Parameters:<dl>")
         for name, value in kwargs.items():
             self._write(f'<dt>{name}</dt><dd>{self._python_var(value)}</dd>')
@@ -110,14 +116,17 @@ class HTMLLogger(BaseLogger):
 
 
     def section(self, heading: str) -> None:
 
 
     def section(self, heading: str) -> None:
+        self._timestamp()
         self._write(f"<h2>{heading}</h2>")
 
 
     def comment(self, text: str) -> None:
         self._write(f"<h2>{heading}</h2>")
 
 
     def comment(self, text: str) -> None:
+        self._timestamp()
         self._write(f"<p>{text}</p>")
 
 
     def var_dump(self, heading: str, var: Any) -> None:
         self._write(f"<p>{text}</p>")
 
 
     def var_dump(self, heading: str, var: Any) -> None:
+        self._timestamp()
         if callable(var):
             var = var()
 
         if callable(var):
             var = var()
 
@@ -125,6 +134,7 @@ class HTMLLogger(BaseLogger):
 
 
     def table_dump(self, heading: str, rows: Iterator[Optional[List[Any]]]) -> None:
 
 
     def table_dump(self, heading: str, rows: Iterator[Optional[List[Any]]]) -> None:
+        self._timestamp()
         head = next(rows)
         assert head
         self._write(f'<table><thead><tr><th colspan="{len(head)}">{heading}</th></tr><tr>')
         head = next(rows)
         assert head
         self._write(f'<table><thead><tr><th colspan="{len(head)}">{heading}</th></tr><tr>')
@@ -143,6 +153,7 @@ class HTMLLogger(BaseLogger):
     def result_dump(self, heading: str, results: Iterator[Tuple[Any, Any]]) -> None:
         """ Print a list of search results generated by the generator function.
         """
     def result_dump(self, heading: str, results: Iterator[Tuple[Any, Any]]) -> None:
         """ Print a list of search results generated by the generator function.
         """
+        self._timestamp()
         def format_osm(osm_object: Optional[Tuple[str, int]]) -> str:
             if not osm_object:
                 return '-'
         def format_osm(osm_object: Optional[Tuple[str, int]]) -> str:
             if not osm_object:
                 return '-'
@@ -167,12 +178,13 @@ class HTMLLogger(BaseLogger):
             self._write(f"rank={res.rank_address}, ")
             self._write(f"osm={format_osm(res.osm_object)}, ")
             self._write(f'cc={res.country_code}, ')
             self._write(f"rank={res.rank_address}, ")
             self._write(f"osm={format_osm(res.osm_object)}, ")
             self._write(f'cc={res.country_code}, ')
-            self._write(f'importance={res.importance or -1:.5f})</dd>')
+            self._write(f'importance={res.importance or float("nan"):.5f})</dd>')
             total += 1
         self._write(f'</dl><b>TOTAL:</b> {total}</p>')
 
 
     def sql(self, conn: AsyncConnection, statement: 'sa.Executable') -> None:
             total += 1
         self._write(f'</dl><b>TOTAL:</b> {total}</p>')
 
 
     def sql(self, conn: AsyncConnection, statement: 'sa.Executable') -> None:
+        self._timestamp()
         sqlstr = self.format_sql(conn, statement)
         if CODE_HIGHLIGHT:
             sqlstr = highlight(sqlstr, PostgresLexer(),
         sqlstr = self.format_sql(conn, statement)
         if CODE_HIGHLIGHT:
             sqlstr = highlight(sqlstr, PostgresLexer(),
@@ -184,7 +196,7 @@ class HTMLLogger(BaseLogger):
 
     def _python_var(self, var: Any) -> str:
         if CODE_HIGHLIGHT:
 
     def _python_var(self, var: Any) -> str:
         if CODE_HIGHLIGHT:
-            fmt = highlight(repr(var), PythonLexer(), HtmlFormatter(nowrap=True))
+            fmt = highlight(str(var), PythonLexer(), HtmlFormatter(nowrap=True))
             return f'<div class="highlight"><code class="lang-python">{fmt}</code></div>'
 
         return f'<code class="lang-python">{str(var)}</code>'
             return f'<div class="highlight"><code class="lang-python">{fmt}</code></div>'
 
         return f'<code class="lang-python">{str(var)}</code>'
@@ -348,6 +360,26 @@ HTML_HEADER: str = """<!DOCTYPE html>
         padding: 3pt;
         border: solid lightgrey 0.1pt
     }
         padding: 3pt;
         border: solid lightgrey 0.1pt
     }
+
+    table, th, tbody {
+        border: thin solid;
+        border-collapse: collapse;
+    }
+    td {
+        border-right: thin solid;
+        padding-left: 3pt;
+        padding-right: 3pt;
+    }
+
+    .timestamp {
+        font-size: 0.8em;
+        color: darkblue;
+        width: calc(100% - 5pt);
+        text-align: right;
+        position: absolute;
+        left: 0;
+        margin-top: -5px;
+    }
   </style>
 </head>
 <body>
   </style>
 </head>
 <body>