[debug/emit/rql] add RQL debug channel and emit queries

This is used for the RQL debug panel but can be used as a generic mechanism for several tools.

authorLaurent Peuch <cortex@worlddomination.be>
changesetec834074ea25
branchdefault
phasepublic
hiddenno
parent revision#db95a417a5ec [debug/source_highlight] rename highlight to highlight_terminal
child revision#d5ae5abd0876 [debug-toolbar/rql] add RQL panel
files modified by this revision
cubicweb/server/querier.py
# HG changeset patch
# User Laurent Peuch <cortex@worlddomination.be>
# Date 1571891822 -7200
# Thu Oct 24 06:37:02 2019 +0200
# Node ID ec834074ea25983246cb5d0a64d36f611c3dd9cd
# Parent db95a417a5ecc5abc7107c7b8432a5d501e1ce9c
[debug/emit/rql] add RQL debug channel and emit queries

This is used for the RQL debug panel but can be used as a generic mechanism for
several tools.

diff --git a/cubicweb/server/querier.py b/cubicweb/server/querier.py
@@ -17,10 +17,12 @@
1  # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
2  """Helper classes to execute RQL queries on a set of sources, performing
3  security checking and data aggregation.
4  """
5  import uuid
6 +import time
7 +import traceback
8  from itertools import repeat
9 
10  from rql import RQLSyntaxError, CoercionError
11  from rql.stmts import Union
12  from rql.nodes import ETYPE_PYOBJ_MAP, etype_from_pyobj, Relation, Exists, Not
@@ -28,10 +30,11 @@
13 
14  from cubicweb import ValidationError, Unauthorized, UnknownEid, QueryError
15  from cubicweb.rqlrewrite import RQLRelationRewriter
16  from cubicweb import Binary, server
17  from cubicweb.rset import ResultSet
18 +from cubicweb.debug import emit_to_debug_channel
19 
20  from cubicweb.utils import QueryCache, RepeatList
21  from cubicweb.misc.source_highlight import highlight_terminal
22  from cubicweb.server.rqlannotation import SQLGenAnnotator, set_qdata
23  from cubicweb.server.ssplanner import READ_ONLY_RTYPES, add_types_restriction
@@ -556,10 +559,22 @@
24          # make an execution plan
25          plan = self.plan_factory(rqlst, args, cnx)
26          plan.cache_key = cachekey
27          plan.rql_query_tracing_token = str(uuid.uuid4())
28          self._planner.build_plan(plan)
29 +
30 +        query_debug_informations = {
31 +            "rql": rql,
32 +            "rql_query_tracing_token": plan.rql_query_tracing_token,
33 +            "args": args,
34 +            # remove the last part of the stack which is: this line
35 +            "callstack": "".join(traceback.format_stack()[:-1]),
36 +            "description": "",
37 +        }
38 +
39 +        start = time.time()
40 +
41          # execute the plan
42          try:
43              results = plan.execute()
44          except (Unauthorized, ValidationError):
45              # getting an Unauthorized/ValidationError exception means the
@@ -571,10 +586,14 @@
46              # * don't rollback if we're in the commit process, will be handled
47              #   by the connection
48              if cnx.commit_state is None:
49                  cnx.commit_state = 'uncommitable'
50              raise
51 +
52 +        query_debug_informations["time"] = ((time.time() - start) * 1000)
53 +        query_debug_informations["result"] = results
54 +
55          # build a description for the results if necessary
56          descr = ()
57          if build_descr:
58              if rqlst.TYPE == 'select':
59                  # sample selection
@@ -594,10 +613,14 @@
60                  basedescr = [None] * len(plan.selected)
61                  todetermine = list(zip(range(len(plan.selected)), repeat(False)))
62                  descr = _build_descr(cnx, results, basedescr, todetermine)
63              # FIXME: get number of affected entities / relations on non
64              # selection queries ?
65 +            query_debug_informations["description"] = descr
66 +
67 +        emit_to_debug_channel("rql", query_debug_informations)
68 +
69          # return a result set object
70          return ResultSet(results, rql, args, descr)
71 
72      # these are overridden by set_log_methods below
73      # only defining here to prevent pylint from complaining