Changeset: 535adcf7be11 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/535adcf7be11
Modified Files:
        monetdb5/mal/mal_profiler.c
        monetdb5/mal/mal_profiler.h
        sql/backends/monet5/sql.c
Branch: sql_profiler
Log Message:

Logging SQL events to stethoscope stream


diffs (169 lines):

diff --git a/monetdb5/mal/mal_profiler.c b/monetdb5/mal/mal_profiler.c
--- a/monetdb5/mal/mal_profiler.c
+++ b/monetdb5/mal/mal_profiler.c
@@ -8,10 +8,11 @@
 
 /* (c) M.L. Kersten
  * Performance tracing
- * The stethoscope/tachograph and tomograph performance monitors have 
exclusive access
- * to a single event stream, which avoids concurrency conflicts amongst 
clients.
- * It also avoid cluthered event records on the stream. Since this event 
stream is owned
- * by a client, we should ensure that the profiler is automatically
+ * The stethoscope/tachograph and tomograph performance monitors have exclusive
+ * access to a single event stream, which avoids concurrency conflicts amongst
+ * clients.
+ * It also avoid cluthered event records on the stream. Since this event stream
+ * is owned by a client, we should ensure that the profiler is automatically
  * reset once the owner leaves.
  */
 #include "monetdb_config.h"
@@ -75,24 +76,29 @@ static void logjsonInternal(char *logbuf
 }
 
 /*
- * We use a buffer (`logbuffer`) where we incrementally create the output JSON 
object. Initially we allocate LOGLEN (8K)
- * bytes and we keep the capacity of the buffer (`logcap`) and the length of 
the current string (`loglen`).
+ * We use a buffer (`logbuffer`) where we incrementally create the output JSON
+ * object. Initially we allocate LOGLEN (8K)
+ * bytes and we keep the capacity of the buffer (`logcap`) and the length of 
the
+ * current string (`loglen`).
  *
- * We use the `logadd` function to add data to our buffer (usually key-value 
pairs). This macro offers an interface similar
- * to printf.
+ * We use the `logadd` function to add data to our buffer (usually key-value
+ * pairs). This macro offers an interface similar to printf.
  *
- * The first snprintf below happens in a statically allocated buffer that 
might be much smaller than logcap. We do not
- * care. We only need to perform this snprintf to get the actual length of the 
string that is to be produced.
+ * The first snprintf below happens in a statically allocated buffer that might
+ * be much smaller than logcap. We do not care. We only need to perform this
+ * snprintf to get the actual length of the string that is to be produced.
  *
  * There are three cases:
  *
  * 1. The new string fits in the current buffer -> we just update the buffer
  *
- * 2. The new string does not fit in the current buffer, but is smaller than 
the capacity of the buffer -> we output the
- * current contents of the buffer and start at the beginning.
+ * 2. The new string does not fit in the current buffer, but is smaller than 
the
+ * capacity of the buffer -> we output the current contents of the buffer and
+ * start at the beginning.
  *
- * 3. The new string exceeds the current capacity of the buffer -> we output 
the current contents and reallocate the
- * buffer. The new capacity is 1.5 times the length of the new string.
+ * 3. The new string exceeds the current capacity of the buffer -> we output 
the
+ * current contents and reallocate the buffer. The new capacity is 1.5 times 
the
+ * length of the new string.
  */
 struct logbuf {
        char *logbuffer;
@@ -169,6 +175,64 @@ logadd(struct logbuf *logbuf, const char
        return true;
 }
 
+/*
+ * Generic events refer to all events that are useful to profile since the
+ * beginning of a query execution up until the MAL execution. This includes
+ * transaction events, SQL parsing, relational tree creation, unnesting,
+ * relational optimizers, rel2bin, and MAL optimizers.
+ *
+ * Profiling a generic event follows the same implementation of ProfilerEvent.
+ */
+static str
+prepareGenericEvent(str msg, struct GenericEvent e, int state)
+{
+       struct logbuf logbuf = {0};
+
+       if (logadd(&logbuf,
+                          "{\""
+                          "msg\":\"%s\""
+                          ",\"client_id\":\"%d\""
+                          ",\"tag\":\""OIDFMT
+                          ",\"transaction_id\":\"%d\""
+                          ",\"query\":\"%s\""
+                          ",\"error\":\"%s\""
+                          ",\"state\":\"%d\""
+                          "}\n",
+                          msg ? msg : "",
+                          0,
+                          (oid)0,
+                          e.transaction_id ? *e.transaction_id : 0,
+                          e.query ? e.query : "",
+                          e.error ? e.error : "",
+                          state))
+               return logbuf.logbuffer;
+       else {
+               logdel(&logbuf);
+               return NULL;;
+       }
+}
+
+static void
+renderGenericEvent(str msg, struct GenericEvent e, int state)
+{
+       str event;
+       MT_lock_set(&mal_profileLock);
+       event = prepareGenericEvent(msg, e, state);
+       if( event ){
+               logjsonInternal(event, true);
+               free(event);
+       }
+       MT_lock_unset(&mal_profileLock);
+}
+
+void
+genericEvent(str msg, struct GenericEvent e, int state)
+{
+       if( maleventstream ) {
+               renderGenericEvent(msg, e, state);
+       }
+}
+
 /* JSON rendering method of performance data.
  * The eventparser may assume this layout for ease of parsing
  EXAMPLE:
diff --git a/monetdb5/mal/mal_profiler.h b/monetdb5/mal/mal_profiler.h
--- a/monetdb5/mal/mal_profiler.h
+++ b/monetdb5/mal/mal_profiler.h
@@ -20,6 +20,12 @@
 typedef struct rusage Rusage;
 #endif
 
+struct GenericEvent {
+       int* transaction_id;
+       str query;
+       str error;
+};
+
 mal_export int malProfileMode;
 
 mal_export void initProfiler(void);
@@ -27,6 +33,7 @@ mal_export str openProfilerStream(Client
 mal_export str closeProfilerStream(Client cntxt);
 
 mal_export void profilerEvent(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci, int start);
+mal_export void genericEvent(str msg, struct GenericEvent e, int state);
 mal_export void sqlProfilerEvent(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 
 mal_export str startProfiler(Client cntxt);
diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -129,8 +129,17 @@ sql_symbol2relation(backend *be, symbol 
        int profile = be->mvc->emode == m_plan;
 
        // TODO PROFILER: EVENT("start of SQL compiler", "program_id", 
TYPE_int, log c->curprg->def->tag)
+       genericEvent("SQL compiler",
+                                (struct GenericEvent){ 0, NULL, NULL},
+                                0);
+
        rel = rel_semantic(query, sym);
+
        // TODO PROFILER: EVENT("end of SQL compiler;start of relational 
optimizer","program_id", TYPE_int, be->c->curprg->def->tag, "error", TYPE_int, 
rel == NULL)
+       genericEvent("SQL compiler",
+                                (struct GenericEvent){ 0, NULL, NULL},
+                                1);
+
        storage_based_opt = value_based_opt && rel && !is_ddl(rel->op);
        Tbegin = GDKusec();
        if (rel)
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to