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]