From fdaa7173fb42bd62be77a5ecc027a1104203d407 Mon Sep 17 00:00:00 2001 From: Joshua Lockerman Date: Thu, 17 Jan 2019 13:18:47 -0500 Subject: [PATCH] Update telemetry with prettier os info The info gotten from uname is difficult to work with, so read the os name from /etc/os-release if it's available. --- sql/updates/latest-dev.sql | 2 ++ sql/version.sql | 2 +- src/telemetry/telemetry.c | 3 ++ src/version.c | 67 +++++++++++++++++++++++++++++++++++-- src/version.h | 2 ++ test/expected/telemetry.out | 5 +-- test/sql/telemetry.sql | 3 +- 7 files changed, 78 insertions(+), 6 deletions(-) diff --git a/sql/updates/latest-dev.sql b/sql/updates/latest-dev.sql index e4715f4f8..6aaeaa618 100644 --- a/sql/updates/latest-dev.sql +++ b/sql/updates/latest-dev.sql @@ -32,3 +32,5 @@ GRANT SELECT ON _timescaledb_internal.bgw_policy_chunk_stats TO PUBLIC; DROP FUNCTION IF EXISTS _timescaledb_internal.drop_chunks_impl(REGCLASS, "any", "any", BOOLEAN); DROP FUNCTION IF EXISTS drop_chunks("any", NAME, NAME, BOOLEAN, "any"); + +DROP FUNCTION IF EXISTS _timescaledb_internal.get_os_info(); diff --git a/sql/version.sql b/sql/version.sql index 47845514f..322f710c4 100644 --- a/sql/version.sql +++ b/sql/version.sql @@ -6,7 +6,7 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT AS '@MODULE_PATHNAME@', 'ts_get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; CREATE OR REPLACE FUNCTION _timescaledb_internal.get_os_info() - RETURNS TABLE(sysname TEXT, version TEXT, release TEXT) + RETURNS TABLE(sysname TEXT, version TEXT, release TEXT, version_pretty TEXT) AS '@MODULE_PATHNAME@', 'ts_get_os_info' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; CREATE OR REPLACE FUNCTION get_telemetry_report() RETURNS TEXT diff --git a/src/telemetry/telemetry.c b/src/telemetry/telemetry.c index 8faa008b4..ec5e4979e 100644 --- a/src/telemetry/telemetry.c +++ b/src/telemetry/telemetry.c @@ -40,6 +40,7 @@ #define REQ_OS "os_name" #define REQ_OS_VERSION "os_version" #define REQ_OS_RELEASE "os_release" +#define REQ_OS_VERSION_PRETTY "os_name_pretty" #define REQ_PS_VERSION "postgresql_version" #define REQ_TS_VERSION "timescaledb_version" #define REQ_BUILD_OS "build_os_name" @@ -223,6 +224,8 @@ build_version_body(void) ts_jsonb_add_str(parseState, REQ_OS, osinfo.sysname); ts_jsonb_add_str(parseState, REQ_OS_VERSION, osinfo.version); ts_jsonb_add_str(parseState, REQ_OS_RELEASE, osinfo.release); + if (osinfo.has_pretty_version) + ts_jsonb_add_str(parseState, REQ_OS_VERSION_PRETTY, osinfo.pretty_version); } else ts_jsonb_add_str(parseState, REQ_OS, "Unknown"); diff --git a/src/version.c b/src/version.c index 17b325b42..6f961ae70 100644 --- a/src/version.c +++ b/src/version.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "fmgr.h" #include "compat.h" @@ -82,6 +83,63 @@ error: #include +#define OS_RELEASE_FILE "/etc/os-release" +#define MAX_READ_LEN 1024 + +#define NAME_FIELD "PRETTY_NAME=\"" + +static bool +get_pretty_version(char *pretty_version) +{ + FILE *version_file; + char *contents = palloc(MAX_READ_LEN); + size_t bytes_read; + bool got_pretty_version = false; + int i; + + memset(pretty_version, '\0', VERSION_INFO_LEN); + + /* we cannot use pg_read_file because it doesn't allow absolute paths */ + version_file = AllocateFile(OS_RELEASE_FILE, PG_BINARY_R); + if (version_file == NULL) + return false; + + fseeko(version_file, 0, SEEK_SET); + + bytes_read = fread(contents, 1, (size_t) MAX_READ_LEN, version_file); + + if (bytes_read <= 0) + goto cleanup; + + if (bytes_read < MAX_READ_LEN) + contents[bytes_read] = '\0'; + else + contents[MAX_READ_LEN - 1] = '\0'; + + contents = strstr(contents, NAME_FIELD); + + if (contents == NULL) + goto cleanup; + + contents += sizeof(NAME_FIELD) - 1; + + for (i = 0; i < (VERSION_INFO_LEN - 1); i++) + { + char c = contents[i]; + + if (c == '\0' || c == '\n' || c == '\r' || c == '"') + break; + + pretty_version[i] = c; + } + + got_pretty_version = true; + +cleanup: + FreeFile(version_file); + return got_pretty_version; +} + bool ts_version_get_os_info(VersionOSInfo *info) { @@ -94,6 +152,7 @@ ts_version_get_os_info(VersionOSInfo *info) strncpy(info->sysname, os_info.sysname, VERSION_INFO_LEN - 1); strncpy(info->version, os_info.version, VERSION_INFO_LEN - 1); strncpy(info->release, os_info.release, VERSION_INFO_LEN - 1); + info->has_pretty_version = get_pretty_version(info->pretty_version); return true; } @@ -112,8 +171,8 @@ Datum ts_get_os_info(PG_FUNCTION_ARGS) { TupleDesc tupdesc; - Datum values[3]; - bool nulls[3] = {false}; + Datum values[4]; + bool nulls[4] = {false}; HeapTuple tuple; VersionOSInfo info; @@ -128,6 +187,10 @@ ts_get_os_info(PG_FUNCTION_ARGS) values[0] = CStringGetTextDatum(info.sysname); values[1] = CStringGetTextDatum(info.version); values[2] = CStringGetTextDatum(info.release); + if (info.has_pretty_version) + values[3] = CStringGetTextDatum(info.pretty_version); + else + nulls[3] = true; } else memset(nulls, true, sizeof(nulls)); diff --git a/src/version.h b/src/version.h index b577f2122..50177d652 100644 --- a/src/version.h +++ b/src/version.h @@ -15,6 +15,8 @@ typedef struct VersionOSInfo char sysname[VERSION_INFO_LEN]; char version[VERSION_INFO_LEN]; char release[VERSION_INFO_LEN]; + char pretty_version[VERSION_INFO_LEN]; + bool has_pretty_version; } VersionOSInfo; extern bool ts_version_get_os_info(VersionOSInfo *info); diff --git a/test/expected/telemetry.out b/test/expected/telemetry.out index 446052709..2f41d2112 100644 --- a/test/expected/telemetry.out +++ b/test/expected/telemetry.out @@ -282,8 +282,9 @@ WARNING: telemetry could not connect to "noservice.timescale.com" (1 row) SET timescaledb.telemetry_level=off; -select json_object_keys(get_telemetry_report()::json); - json_object_keys +SELECT * FROM json_object_keys(get_telemetry_report()::json) AS key +WHERE key != 'os_name_pretty'; + key --------------------- db_uuid license diff --git a/test/sql/telemetry.sql b/test/sql/telemetry.sql index 4771a3d98..04c364b11 100644 --- a/test/sql/telemetry.sql +++ b/test/sql/telemetry.sql @@ -121,4 +121,5 @@ SELECT _timescaledb_internal.test_telemetry_main_conn('noservice.timescale.com', SET timescaledb.telemetry_level=off; -select json_object_keys(get_telemetry_report()::json); +SELECT * FROM json_object_keys(get_telemetry_report()::json) AS key +WHERE key != 'os_name_pretty';