Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions | Variables

auto_explain.c File Reference

#include "postgres.h"
#include <limits.h>
#include "commands/explain.h"
#include "executor/instrument.h"
#include "utils/guc.h"
Include dependency graph for auto_explain.c:

Go to the source code of this file.

Defines

#define auto_explain_enabled()

Functions

void _PG_init (void)
void _PG_fini (void)
static void explain_ExecutorStart (QueryDesc *queryDesc, int eflags)
static void explain_ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, long count)
static void explain_ExecutorFinish (QueryDesc *queryDesc)
static void explain_ExecutorEnd (QueryDesc *queryDesc)

Variables

 PG_MODULE_MAGIC
static int auto_explain_log_min_duration = -1
static bool auto_explain_log_analyze = false
static bool auto_explain_log_verbose = false
static bool auto_explain_log_buffers = false
static bool auto_explain_log_timing = false
static int auto_explain_log_format = EXPLAIN_FORMAT_TEXT
static bool auto_explain_log_nested_statements = false
static struct config_enum_entry format_options []
static int nesting_level = 0
static ExecutorStart_hook_type prev_ExecutorStart = NULL
static ExecutorRun_hook_type prev_ExecutorRun = NULL
static ExecutorFinish_hook_type prev_ExecutorFinish = NULL
static ExecutorEnd_hook_type prev_ExecutorEnd = NULL

Define Documentation

#define auto_explain_enabled (  ) 

Function Documentation

void _PG_fini ( void   ) 
void _PG_init ( void   ) 

Definition at line 68 of file auto_explain.c.

References auto_explain_log_analyze, auto_explain_log_buffers, auto_explain_log_format, auto_explain_log_min_duration, auto_explain_log_nested_statements, auto_explain_log_timing, auto_explain_log_verbose, DefineCustomBoolVariable(), DefineCustomEnumVariable(), DefineCustomIntVariable(), EmitWarningsOnPlaceholders(), ExecutorEnd_hook, ExecutorFinish_hook, ExecutorRun_hook, ExecutorStart_hook, EXPLAIN_FORMAT_TEXT, GUC_UNIT_MS, NULL, PGC_SUSET, prev_ExecutorEnd, prev_ExecutorFinish, prev_ExecutorRun, and prev_ExecutorStart.

{
    /* Define custom GUC variables. */
    DefineCustomIntVariable("auto_explain.log_min_duration",
         "Sets the minimum execution time above which plans will be logged.",
                         "Zero prints all plans. -1 turns this feature off.",
                            &auto_explain_log_min_duration,
                            -1,
                            -1, INT_MAX / 1000,
                            PGC_SUSET,
                            GUC_UNIT_MS,
                            NULL,
                            NULL,
                            NULL);

    DefineCustomBoolVariable("auto_explain.log_analyze",
                             "Use EXPLAIN ANALYZE for plan logging.",
                             NULL,
                             &auto_explain_log_analyze,
                             false,
                             PGC_SUSET,
                             0,
                             NULL,
                             NULL,
                             NULL);

    DefineCustomBoolVariable("auto_explain.log_verbose",
                             "Use EXPLAIN VERBOSE for plan logging.",
                             NULL,
                             &auto_explain_log_verbose,
                             false,
                             PGC_SUSET,
                             0,
                             NULL,
                             NULL,
                             NULL);

    DefineCustomBoolVariable("auto_explain.log_buffers",
                             "Log buffers usage.",
                             NULL,
                             &auto_explain_log_buffers,
                             false,
                             PGC_SUSET,
                             0,
                             NULL,
                             NULL,
                             NULL);

    DefineCustomEnumVariable("auto_explain.log_format",
                             "EXPLAIN format to be used for plan logging.",
                             NULL,
                             &auto_explain_log_format,
                             EXPLAIN_FORMAT_TEXT,
                             format_options,
                             PGC_SUSET,
                             0,
                             NULL,
                             NULL,
                             NULL);

    DefineCustomBoolVariable("auto_explain.log_nested_statements",
                             "Log nested statements.",
                             NULL,
                             &auto_explain_log_nested_statements,
                             false,
                             PGC_SUSET,
                             0,
                             NULL,
                             NULL,
                             NULL);

    DefineCustomBoolVariable("auto_explain.log_timing",
                             "Collect timing data, not just row counts.",
                             NULL,
                             &auto_explain_log_timing,
                             true,
                             PGC_SUSET,
                             0,
                             NULL,
                             NULL,
                             NULL);

    EmitWarningsOnPlaceholders("auto_explain");

    /* Install hooks. */
    prev_ExecutorStart = ExecutorStart_hook;
    ExecutorStart_hook = explain_ExecutorStart;
    prev_ExecutorRun = ExecutorRun_hook;
    ExecutorRun_hook = explain_ExecutorRun;
    prev_ExecutorFinish = ExecutorFinish_hook;
    ExecutorFinish_hook = explain_ExecutorFinish;
    prev_ExecutorEnd = ExecutorEnd_hook;
    ExecutorEnd_hook = explain_ExecutorEnd;
}

static void explain_ExecutorEnd ( QueryDesc queryDesc  )  [static]

Definition at line 271 of file auto_explain.c.

References ExplainState::analyze, auto_explain_enabled, auto_explain_log_analyze, auto_explain_log_buffers, auto_explain_log_format, auto_explain_log_min_duration, auto_explain_log_verbose, ExplainState::buffers, StringInfoData::data, ereport, errhidestmt(), errmsg(), EXPLAIN_FORMAT_JSON, ExplainBeginOutput(), ExplainEndOutput(), ExplainInitState(), ExplainPrintPlan(), ExplainQueryText(), ExplainState::format, InstrEndLoop(), QueryDesc::instrument_options, StringInfoData::len, LOG, pfree(), prev_ExecutorEnd, standard_ExecutorEnd(), ExplainState::str, Instrumentation::total, QueryDesc::totaltime, and ExplainState::verbose.

{
    if (queryDesc->totaltime && auto_explain_enabled())
    {
        double      msec;

        /*
         * Make sure stats accumulation is done.  (Note: it's okay if several
         * levels of hook all do this.)
         */
        InstrEndLoop(queryDesc->totaltime);

        /* Log plan if duration is exceeded. */
        msec = queryDesc->totaltime->total * 1000.0;
        if (msec >= auto_explain_log_min_duration)
        {
            ExplainState es;

            ExplainInitState(&es);
            es.analyze = (queryDesc->instrument_options && auto_explain_log_analyze);
            es.verbose = auto_explain_log_verbose;
            es.buffers = (es.analyze && auto_explain_log_buffers);
            es.format = auto_explain_log_format;

            ExplainBeginOutput(&es);
            ExplainQueryText(&es, queryDesc);
            ExplainPrintPlan(&es, queryDesc);
            ExplainEndOutput(&es);

            /* Remove last line break */
            if (es.str->len > 0 && es.str->data[es.str->len - 1] == '\n')
                es.str->data[--es.str->len] = '\0';

            /* Fix JSON to output an object */
            if (auto_explain_log_format == EXPLAIN_FORMAT_JSON)
            {
                es.str->data[0] = '{';
                es.str->data[es.str->len - 1] = '}';
            }

            /*
             * Note: we rely on the existing logging of context or
             * debug_query_string to identify just which statement is being
             * reported.  This isn't ideal but trying to do it here would
             * often result in duplication.
             */
            ereport(LOG,
                    (errmsg("duration: %.3f ms  plan:\n%s",
                            msec, es.str->data),
                     errhidestmt(true)));

            pfree(es.str->data);
        }
    }

    if (prev_ExecutorEnd)
        prev_ExecutorEnd(queryDesc);
    else
        standard_ExecutorEnd(queryDesc);
}

static void explain_ExecutorFinish ( QueryDesc queryDesc  )  [static]
static void explain_ExecutorRun ( QueryDesc queryDesc,
ScanDirection  direction,
long  count 
) [static]

Definition at line 225 of file auto_explain.c.

References nesting_level, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, prev_ExecutorRun, and standard_ExecutorRun().

{
    nesting_level++;
    PG_TRY();
    {
        if (prev_ExecutorRun)
            prev_ExecutorRun(queryDesc, direction, count);
        else
            standard_ExecutorRun(queryDesc, direction, count);
        nesting_level--;
    }
    PG_CATCH();
    {
        nesting_level--;
        PG_RE_THROW();
    }
    PG_END_TRY();
}

static void explain_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
) [static]

Definition at line 180 of file auto_explain.c.

References auto_explain_enabled, auto_explain_log_analyze, auto_explain_log_buffers, auto_explain_log_timing, EState::es_query_cxt, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, InstrAlloc(), INSTRUMENT_ALL, QueryDesc::instrument_options, MemoryContextSwitchTo(), NULL, prev_ExecutorStart, standard_ExecutorStart(), and QueryDesc::totaltime.

{
    if (auto_explain_enabled())
    {
        /* Enable per-node instrumentation iff log_analyze is required. */
        if (auto_explain_log_analyze && (eflags & EXEC_FLAG_EXPLAIN_ONLY) == 0)
        {
            if (auto_explain_log_timing)
                queryDesc->instrument_options |= INSTRUMENT_TIMER;
            else
                queryDesc->instrument_options |= INSTRUMENT_ROWS;


            if (auto_explain_log_buffers)
                queryDesc->instrument_options |= INSTRUMENT_BUFFERS;
        }
    }

    if (prev_ExecutorStart)
        prev_ExecutorStart(queryDesc, eflags);
    else
        standard_ExecutorStart(queryDesc, eflags);

    if (auto_explain_enabled())
    {
        /*
         * Set up to track total elapsed time in ExecutorRun.  Make sure the
         * space is allocated in the per-query context so it will go away at
         * ExecutorEnd.
         */
        if (queryDesc->totaltime == NULL)
        {
            MemoryContext oldcxt;

            oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt);
            queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL);
            MemoryContextSwitchTo(oldcxt);
        }
    }
}


Variable Documentation

bool auto_explain_log_analyze = false [static]

Definition at line 25 of file auto_explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and explain_ExecutorStart().

bool auto_explain_log_buffers = false [static]

Definition at line 27 of file auto_explain.c.

Referenced by _PG_init(), explain_ExecutorEnd(), and explain_ExecutorStart().

int auto_explain_log_format = EXPLAIN_FORMAT_TEXT [static]

Definition at line 29 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

int auto_explain_log_min_duration = -1 [static]

Definition at line 24 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

Definition at line 30 of file auto_explain.c.

Referenced by _PG_init().

bool auto_explain_log_timing = false [static]

Definition at line 28 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorStart().

bool auto_explain_log_verbose = false [static]

Definition at line 26 of file auto_explain.c.

Referenced by _PG_init(), and explain_ExecutorEnd().

struct config_enum_entry format_options[] [static]
Initial value:
 {
    {"text", EXPLAIN_FORMAT_TEXT, false},
    {"xml", EXPLAIN_FORMAT_XML, false},
    {"json", EXPLAIN_FORMAT_JSON, false},
    {"yaml", EXPLAIN_FORMAT_YAML, false},
    {NULL, 0, false}
}

Definition at line 32 of file auto_explain.c.

int nesting_level = 0 [static]

Definition at line 41 of file auto_explain.c.

Referenced by explain_ExecutorFinish(), and explain_ExecutorRun().

Definition at line 21 of file auto_explain.c.

Definition at line 47 of file auto_explain.c.

Referenced by _PG_fini(), _PG_init(), and explain_ExecutorEnd().

Definition at line 46 of file auto_explain.c.

Referenced by _PG_fini(), _PG_init(), and explain_ExecutorFinish().

Definition at line 45 of file auto_explain.c.

Referenced by _PG_fini(), _PG_init(), and explain_ExecutorRun().

Definition at line 44 of file auto_explain.c.

Referenced by _PG_fini(), _PG_init(), and explain_ExecutorStart().