Ejemplo n.º 1
0
/*
 * Function: pg_connect
 *
 * Parses a Zabbix agent request and returns a PostgreSQL connection.
 *
 * See: http://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-PQCONNECTDB
 *
 * Parameter [request]: Zabbix agent request structure.
 *          The following parameters may be set:
 *
 *          0: connection string (default: DEFAULT_CONN_STRING)
 *          1: connection database (default: DEFAULT_CONN_DBNAME)
 *
 * Returns: Valid PostgreSQL connection or NULL on error
 */
 PGconn    *pg_connect(AGENT_REQUEST *request)
 {
    const char  *__function_name = "pg_connect";
    PGconn      *conn = NULL;
    char        *param_connstring = NULL, *param_dbname = NULL;
    char        connstring[MAX_STRING_LEN], *c = NULL;
    int         param_connstring_len = 0, param_dbname_len = 0, connstring_len = 0;;

    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
    
    // get connection string from first parameter
    param_connstring = get_rparam(request, PARAM_CONN_STRING);
    param_connstring = (NULL == param_connstring) ? DEFAULT_CONN_STRING : param_connstring;
    param_connstring_len = strlen(param_connstring);

    // get database name from second parameter
    param_dbname = get_rparam(request, PARAM_DBNAME);
    param_dbname = (NULL == param_dbname) ? DEFAULT_CONN_DBNAME : param_dbname;
    param_dbname_len = strisnull(param_dbname) ? 0 : strlen(param_dbname);

    // create buffer to concat connection string and database name
    zbx_strlcpy(connstring, param_connstring, sizeof(connstring));
    c = connstring;

    // append dbname= key
    if (!strisnull(param_dbname)) {
        if (!strisnull(connstring))
            c = strcat2(c, " ");

        c = strcat(c, "dbname=");
        c = strcat(c, param_dbname);
    }

    /*
     * Breaks in ~ v8.4
    // append application name
    if (!strisnull(connstring))
        c = strcat2(c, " ");
    c = strcat(c, "application_name='" STRVER "'");
    */
    
    // connect
    zabbix_log(LOG_LEVEL_DEBUG, "Connecting to PostgreSQL with: %s", connstring);
    conn = PQconnectdb(connstring);
    if(CONNECTION_OK != PQstatus(conn)) {
        zabbix_log(LOG_LEVEL_ERR, "Failed to connect to PostgreSQL in %s():\n%s", __function_name, PQerrorMessage(conn));
        PQfinish(conn);
        conn = NULL;
    }

    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return conn;
}
Ejemplo n.º 2
0
/*
 * Custom key pg.checkpoint_time_perc
 *
 * Returns the percentage of time spent writing or syncing checkpoints since
 * statistics were reset.
 *
 * Parameters:
 *   0:  connection string
 *   1:  connection database
 *   2:  action: all (default) | write | sync
 *
 * Returns: d
 */
int     PG_BG_TIME_PERC(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    int         ret = SYSINFO_RET_FAIL;                 // Request result code
    const char  *__function_name = "PG_BG_TIME_PERC";   // Function name for log file

    char        query[MAX_STRING_LEN];
    char        *action = NULL, *field = NULL;
    
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

    // parse action parameter
    action = get_rparam(request, PARAM_FIRST);
    if (strisnull(action) || 0 == strcmp(action, "all"))
        field = "(checkpoint_write_time + checkpoint_sync_time)";
    else if (0 == strcmp(action, "write"))
        field = "checkpoint_write_time";
    else if (0 == strcmp(action, "sync"))
        field = "checkpoint_sync_time";
    else {
        SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Invalid action parameter: %s", action));
        return ret;
    }

    // build query
    zbx_snprintf(query, sizeof(query), PGSQL_BG_TIME_PERC, field);

    // get result
    ret = pg_get_dbl(request, result, query, NULL);

    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return ret;
}
Ejemplo n.º 3
0
int     PG_INDEX_IDX_BLKS_PERC(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    int         ret = SYSINFO_RET_FAIL;                         // Request result code
    const char  *__function_name = "PG_INDEX_IDX_BLKS_PERC";    // Function name for log file
    
    char        *index = NULL;
    
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
    
    index = get_rparam(request, PARAM_FIRST);

    if(strisnull(index)) {
        ret = pg_get_percentage(
            request,
            result,
            "pg_statio_all_indexes",
            "sum(idx_blks_hit)",
            "sum(idx_blks_hit) + sum(idx_blks_read)",
            NULL,
            NULL);

    } else {
        ret = pg_get_percentage(
            request,
            result,
            "pg_statio_all_indexes",
            "idx_blks_hit",
            "idx_blks_hit + idx_blks_read",
            "indexrelname",
            index);
    }
    
    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return ret; 
}
Ejemplo n.º 4
0
/*
 * Custom keys pg.index.* (for each field in pg_statio_all_indexes)
 *
 * Returns the requested IO statistic for the specified index
 *
 * Parameters:
 *   0:  connection string
 *   1:  connection database
 *   2:  filter by index name (default: sum of all indexes)
 *
 * Returns: u
 */
int    PG_STATIO_ALL_INDEXES(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    int         ret = SYSINFO_RET_FAIL;                     // Request result code
    const char  *__function_name = "PG_STAT_ALL_INDEXES";   // Function name for log file
    
    char        *index = NULL;

    char        *field;
    char        query[MAX_STRING_LEN];
    
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
    
    // Get stat field from requested key name "pb.index.<field>"
    field = &request->key[9];
    
    // Build query
    index = get_rparam(request, PARAM_FIRST);
    if(strisnull(index))
        zbx_snprintf(query, sizeof(query), PGSQL_GET_INDEX_STATIO_SUM, field);
    else
        zbx_snprintf(query, sizeof(query),  "SELECT %s FROM pg_statio_all_indexes WHERE indexrelname = $1", field);

    ret = pg_get_int(request, result, query, param_new(index));
    
    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return ret;
}
Ejemplo n.º 5
0
/*
 * Custom key pg.index.discovery
 *
 * Parameters:
 *   0:  connection string
 *   1:  connection database
 *   2:  search mode: deep (default) | shallow
 *   3:  filter by schema name
 *   4:  filter by table name
 *
 * Returns all known indexes in a PostgreSQL database
 *
 * Returns:
 * {
 *        "data":[
 *                {
 *                        "{#OID}":"12345",
 *                        "{#INDEX}":"MyIndex",
 *                        "{#DATABASE}":"MyDatabase",
 *                        "{#SCHEMA}":"public",
 *                        "{#TABLE}":"MyTable",
 *                        "{#OWNER}":"postgres",
 *                        "{#ACCESS}":"btree|hash"}]}
 */
int    PG_INDEX_DISCOVERY(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    int         ret = SYSINFO_RET_FAIL;                 // Request result code
    const char  *__function_name = "PG_DB_DISCOVERY";   // Function name for log file
    
    char        query[MAX_STRING_LEN], buffer[MAX_STRING_LEN];
    char        *c = NULL;

    char        *param_mode = NULL, *param_table = NULL, *param_schema = NULL;
    
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

    // build the query
    zbx_strlcpy(query, PGSQL_DISCOVER_INDEXES, sizeof(query));
    c = query;

    // filter by schema name
    param_schema = get_rparam(request, PARAM_FIRST + 1);
    if(!strisnull(param_schema)) {
        zbx_snprintf(buffer, sizeof(buffer), " AND n.nspname = '%s'", param_schema);
        c = strcat2(c, buffer);
    }

    // filter by table name
    param_table = get_rparam(request, PARAM_FIRST + 2);
    if(!strisnull(param_table)) {
        zbx_snprintf(buffer, sizeof(buffer), " AND t.relname = '%s'", param_table);
        c = strcat2(c, buffer);
    }

    // build results
    param_mode = get_rparam(request, PARAM_FIRST);
    if (strisnull(param_mode) || 0 == strcmp(param_mode, "deep")) {
        ret = pg_get_discovery_wide(request, result, query, NULL);
    } else if (0 == strcmp(param_mode, "shallow")) {
        ret = pg_get_discovery(request, result, query, NULL);
    } else {
        SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Invalid search mode parameter: %s", param_mode));
    }

    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return ret;
}
Ejemplo n.º 6
0
/*
 * Custom keys pg.index.* (for each field in pg_stat_all_indexes)
 *
 * Returns the requested statistic for the specified index
 *
 * Parameters:
 *   0:  connection string
 *   1:  connection database
 *   2:  filter by index name (default: sum of all indexes)
 *
 * Returns: u
 */
int    PG_STAT_ALL_INDEXES(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    int         ret = SYSINFO_RET_FAIL;                     // Request result code
    const char  *__function_name = "PG_STAT_ALL_INDEXES";   // Function name for log file
    
    char        *index = NULL;
    
    PGconn      *conn = NULL;
    PGresult    *res = NULL;
    
    char        *field;
    char        query[MAX_STRING_LEN];
    char        *buffer = NULL;
    
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
    
    // Get stat field from requested key name "pb.table.<field>"
    field = &request->key[9];
    
    // Build query
    index = get_rparam(request, PARAM_FIRST);
    if(strisnull(index))
        zbx_snprintf(query, sizeof(query), "SELECT SUM(%s) FROM pg_stat_all_indexes", field);
    else
        zbx_snprintf(query, sizeof(query),  "SELECT %s FROM pg_stat_all_indexes WHERE indexrelname = $1", field);

    // Connect to PostreSQL
    if(NULL == (conn = pg_connect_request(request)))
        goto out;
    
    // Execute a query
    res = pg_exec(conn, query, param_new(index));
    if(PQresultStatus(res) != PGRES_TUPLES_OK) {
        zabbix_log(LOG_LEVEL_ERR, "Failed to execute PostgreSQL query in %s() with: %s", __function_name, PQresultErrorMessage(res));
        goto out;
    }
    
    if(0 == PQntuples(res)) {
        zabbix_log(LOG_LEVEL_ERR, "No results returned for query \"%s\" in %s()", query, __function_name);
        goto out;
    }
    
    // Set result
    buffer = strdup(PQgetvalue(res, 0, 0));
    SET_UI64_RESULT(result, atoi(buffer));
    ret = SYSINFO_RET_OK;
        
out:
    PQclear(res);
    PQfinish(conn);
    
    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return ret;
}
Ejemplo n.º 7
0
/*
 * Custom key pg.index.size
 *
 * Returns the disk usage in bytes for the specified index
 *
 * Parameters:
 *   0:  connection string
 *   1:  connection database
 *   2:  filter by index name (default: sum of all indexes)
 *
 * Returns: u
 */
int    PG_INDEX_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    int         ret = SYSINFO_RET_FAIL;             // Request result code
    const char  *__function_name = "PG_INDEX_SIZE"; // Function name for log file
    char        *index = NULL; //, *include = NULL;
            
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
    
    // Parse parameters
    index = get_rparam(request, PARAM_FIRST);
    
    // Build query  
    if(strisnull(index))
        ret = pg_get_int(request, result, PGSQL_GET_INDEX_SIZE_SUM, NULL);
    else
        ret = pg_get_int(request, result, PGSQL_GET_INDEX_SIZE, param_new(index));
    
    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return ret;
}
Ejemplo n.º 8
0
/*
 * Custom key pg.tablespace.size
 *
 * Returns the size of the specified tablespace in bytes
 *
 * Parameters:
 *   0:  connection string
 *   1:  tablespace name
 *
 * Returns: u
 */
int    PG_TABLESPACE_SIZE(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    int         ret = SYSINFO_RET_FAIL;                     // Request result code
    const char  *__function_name = "PG_TABLESPACE_SIZE";    // Function name for log file
    char        *tablespace = NULL;
    
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
    
    // Build query
    tablespace = get_rparam(request, PARAM_FIRST);
    if(strisnull(tablespace)) {
        zabbix_log(LOG_LEVEL_ERR, "No tablespace specified in %s()", __function_name);
        goto out;
    }
    
    // execute query
    ret = pg_get_int(request, result, PGSQL_GET_TS_SIZE, param_new(tablespace));
    
out:
    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return ret;
}
Ejemplo n.º 9
0
/*
 * build_activity_clause takes agent request parameters for an item key which
 * targets the pg_stat_actity table and creates an SQL clause to filter
 * results.
 *
 * This function should be reused for all items which query the pg_stat_activity
 * table.
 *
 * request is the agent request containing the user parameters.
 * buf is the character buffer to which the clause is written.
 * params is a pointer to a PGparams type which stores query parameters.
 * has_clause determines if the the clause starts with "WITH" or "AND".
 *
 * Returns non-zero on success.
 */
static int build_activity_clause(const AGENT_REQUEST *request, char *buf, PGparams *params, int has_clause) {
    const char  *__function_name = "build_activity_clause";  // Function name for log file

    int         i = 0;
    char        *param = NULL;
    char        *clause = (0 < has_clause ? PG_AND : PG_WHERE);
    int         pgi = 0;
    
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

    // iterate over the available parameters
    for(i = 0; i < 4; i++) {
        param = get_rparam(request, PARAM_FIRST + i);
        if(!strisnull(param)) {
            switch(i) {
                case 0: // <database>
                    *params = param_append(*params, param);
                    if(is_oid(param))
                        zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s datid = $%i", clause, ++pgi);
                    else
                        zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s datname = $%i", clause, ++pgi);
                    break;

                case 1: // <user>
                    *params = param_append(*params, param);
                    if(is_oid(param))
                        zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s usesysid = $%i", clause, ++pgi);
                    else
                        zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s usename = $%i", clause, ++pgi);
                    break;

                case 2: // <client>
                    *params = param_append(*params, param);
                    if(is_valid_ip(param))
                        zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s client_addr = $%i::inet", clause, ++pgi);
                    else
                        // requires v9.1+
                        zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s client_hostname = $%i", clause, ++pgi);
                    break;

                case 3: // <waiting>                
                    if(0 == strncmp("true\0", param, 5)) {
                        zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s waiting = TRUE", clause);
                    } else if(0 == strncmp("false\0", param, 6)) {
                        zbx_snprintf(buf, MAX_CLAUSE_LEN, " %s waiting = FALSE", clause);
                    } else {
                        zabbix_log(LOG_LEVEL_ERR, "Unsupported parameter value: \"%s\" in %s", param, request->key);
                        return 0;
                    }

                    break;
            }

            buf += strlen(buf);
            clause = PG_AND;
        }
    }

    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);

    return 1;
}
Ejemplo n.º 10
0
/*
 * Custom key pg.backends.count
 *
 * Returns statistics for connected backends (remote clients)
 *
 * Parameters:
 *   0:  connection string
 *   1:  connection database
 *   2:  filter by database oid name
 *   3:  filter by user OID or name
 *   4:  filter by hostname or IP address of the connected host
 *   5:  return only waiting backends
 *
 * Returns: u
 */
 int    PG_BACKENDS_COUNT(AGENT_REQUEST *request, AGENT_RESULT *result)
 {
    int         ret = SYSINFO_RET_FAIL;                  // Request result code
    const char  *__function_name = "PG_BACKENDS_COUNT";  // Function name for log file
	char        query[MAX_QUERY_LEN];
	char        *p = &query[0];
	int         i = 0;
	char        *param = NULL;
	char        *clause = PG_WHERE;
    PGparams    pgparams = NULL;
    int         pgi = 0;
    
    zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

    // Build the sql query
    memset(query, 0, MAX_QUERY_LEN);
    zbx_strlcpy(p, PGSQL_GET_BACKENDS, MAX_QUERY_LEN);
    p += strlen(p);

    // iterate over the available parameters
    for(i = 0; i < 4; i++) {
    	param = get_rparam(request, PARAM_FIRST + i);
    	if(!strisnull(param)) {
    		switch(i) {
    			case 0: // <database>
                    pgparams = param_append(pgparams, param);
    				if(is_oid(param))
    					zbx_snprintf(p, MAX_CLAUSE_LEN, " %s datid=$%i", clause, ++pgi);
    				else
    					zbx_snprintf(p, MAX_CLAUSE_LEN, " %s datname=$%i", clause, ++pgi);
    				break;

    			case 1: // <user>
                    pgparams = param_append(pgparams, param);
    			    if(is_oid(param))
    			    	zbx_snprintf(p, MAX_CLAUSE_LEN, " %s usesysid=$%i", clause, ++pgi);
    				else
    					zbx_snprintf(p, MAX_CLAUSE_LEN, " %s usename=$%i", clause, ++pgi);
    				break;

    			case 2: // <client>
                    pgparams = param_append(pgparams, param);
    			    if(is_valid_ip(param))
                    	zbx_snprintf(p, MAX_CLAUSE_LEN, " %s client_addr = $%i::inet", clause, ++pgi);
    				else
                        // requires v9.1+
    					zbx_snprintf(p, MAX_CLAUSE_LEN, " %s client_hostname=$%i", clause, ++pgi);
    				break;

    			case 3: // <waiting>
    				if(0 == strncmp("true", param, 4)) {
                        zbx_snprintf(p, MAX_CLAUSE_LEN, " %s waiting=TRUE", clause);
                    } else if(0 == strncmp("false", param, 5)) {
                        zbx_snprintf(p, MAX_CLAUSE_LEN, " %s waiting=FALSE", clause);
                    } else {
                        zabbix_log(LOG_LEVEL_ERR, "Unsupported 'Waiting' parameter: %s in %s()", param, __function_name);
                        goto out;
                    }
                    
    				break;
    		}

    		p += strlen(p);
    		clause = PG_AND;
    	}
    }

    ret = pg_get_int(request, result, query, pgparams);

out:  
    zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
    return ret;
}