Index: /branches/amp_4_0/platform/tools/install_telegraf.sh
===================================================================
--- /branches/amp_4_0/platform/tools/install_telegraf.sh	(revision 2695)
+++ /branches/amp_4_0/platform/tools/install_telegraf.sh	(working copy)
@@ -1,143 +1,44 @@
 #!/bin/bash
+# install_telegraf.sh
+# - Installs Telegraf from system repos.
+# - Leaves ALL configuration to configure_telegraf_timescale.sh
 
-set -e
+set -euo pipefail
 
-# --- Configuration ---
 LOG_FILE="/var/log/install_telegraf.log"
-CONFIG_FILE="/opt/influxdb3_token.toml"
 TELEGRAF_CONFIG_DIR="/etc/telegraf/telegraf.d"
 TELEGRAF_CONFIG="/etc/telegraf/telegraf.conf"
-INFLUXDB_HOST="http://localhost:8086"
-INFLUXDB_ORG="AN"
-TELEGRAF_BUCKET="AMP"
 TELEGRAF_VERSION="1.34.1"
 
-# Function to log messages
-log_message() {
-  local level="$1"
-  local message="$2"
-  local timestamp="$(date +'%Y-%m-%d %H:%M:%S')"
-  local log_line="[$level] $timestamp - $message"
-  echo "$log_line"
-  echo "$log_line" >> "$LOG_FILE"
-}
+# --- Logging helpers ---
+log() { echo "[$(date +'%F %T')] $*"; echo "[$(date +'%F %T')] $*" >> "$LOG_FILE"; }
+need() { command -v "$1" >/dev/null 2>&1 || { log "ERROR: $1 not found"; exit 1; }; }
 
-log_info()    { log_message "INFO" "$1"; }
-log_error()   { log_message "ERROR" "$1" >&2; }
-log_warning() { log_message "WARNING" "$1"; }
-
-check_command() {
-  if ! command -v "$1" &>/dev/null; then
-    log_error "$1 command not found. Please install it."
-    exit 1
-  fi
-}
-
-# --- Check directory permissions ---
-log_info "Checking directory permissions..."
+# --- Check directories ---
+log "Checking directory permissions..."
 for dir in "/var/log" "/etc/telegraf" "$TELEGRAF_CONFIG_DIR"; do
   if [[ ! -d "$dir" ]]; then
-    log_warning "$dir directory does not exist. Creating it..."
+    log "WARN: $dir does not exist. Creating..."
     sudo mkdir -p "$dir"
-    [[ $? -ne 0 ]] && log_error "Failed to create directory $dir." && exit 1
   fi
-  [[ ! -w "$dir" ]] && log_error "$dir directory is not writable. Please check permissions." && exit 1
+  [[ ! -w "$dir" ]] && { log "ERROR: $dir not writable"; exit 1; }
 done
-log_info "Directory permissions check complete."
 
-# --- Prerequisites ---
-log_info "Checking for required commands..."
-for cmd in curl sudo dnf grep sed; do check_command "$cmd"; done
-log_info "All required commands are present."
+# --- Prereqs ---
+log "Checking required commands..."
+for cmd in sudo dnf grep sed; do need "$cmd"; done
+log "All required commands are present."
 
-# --- Add InfluxData Repo ---
-log_info "Adding InfluxData repository..."
-REPO_URL="https://repos.influxdata.com/centos/9/x86_64/stable"
-REPO_FILE="/etc/yum.repos.d/influxdata.repo"
-
-if [[ ! -f "$REPO_FILE" ]]; then
-  cat <<EOF | sudo tee "$REPO_FILE"
-[influxdata]
-name = InfluxData Repository - Stable
-baseurl = $REPO_URL
-gpgcheck = 1
-gpgkey = https://repos.influxdata.com/influxdata-archive_compat.key
-enabled = 1
-EOF
-  sudo dnf update -y
-  [[ $? -ne 0 ]] && log_error "Failed to add repo or update system." && exit 1
-  log_info "InfluxData repo added and system updated."
-else
-  log_info "InfluxData repo already exists."
-fi
-
 # --- Install Telegraf ---
-log_info "Installing Telegraf version $TELEGRAF_VERSION..."
-sudo dnf install -y "telegraf-${TELEGRAF_VERSION}"
-[[ $? -ne 0 ]] && log_error "Telegraf installation failed." && exit 1
-log_info "Telegraf $TELEGRAF_VERSION installed successfully."
-
-# --- Read Token ---
-log_info "Reading InfluxDB token from $CONFIG_FILE..."
-if [[ ! -f "$CONFIG_FILE" ]]; then
-  log_error "Token file not found. Please run the InfluxDB setup first."
+log "Installing Telegraf version $TELEGRAF_VERSION..."
+if ! sudo dnf install -y "telegraf-${TELEGRAF_VERSION}"; then
+  log "ERROR: Failed to install Telegraf"
   exit 1
 fi
+log "Telegraf $TELEGRAF_VERSION installed successfully."
 
-STORED_TOKEN=$(grep '^token *= *"' "$CONFIG_FILE" | sed -E 's/token *= *"([^"]+)"/\1/')
-[[ -z "$STORED_TOKEN" ]] && log_error "Failed to extract token." && exit 1
-log_info "Token read successfully."
+log "Enabling Telegraf service (will start after configuration)…"
+sudo systemctl enable telegraf
 
-# --- Configure Telegraf ---
-log_info "Creating Telegraf configuration..."
-sudo mkdir -p "$TELEGRAF_CONFIG_DIR"
-sudo tee "$TELEGRAF_CONFIG" > /dev/null <<EOF
-[agent]
-  interval = "10s"
-  round_interval = true
-  metric_batch_size = 1000
-  metric_buffer_limit = 10000
-  collection_jitter = "0s"
-  flush_interval = "10s"
-  precision = ""
-  hostname = ""
-  omit_hostname = false
-
-[[outputs.influxdb_v2]]
-  urls = ["$INFLUXDB_HOST"]
-  token = "$STORED_TOKEN"
-  organization = "$INFLUXDB_ORG"
-  bucket = "$TELEGRAF_BUCKET"
-
-[[inputs.cpu]]
-  percpu = true
-  totalcpu = true
-
-[[inputs.disk]]
-  ignore_fs = ["tmpfs", "devtmpfs", "overlay", "rootfs"]
-
-[[inputs.mem]]
-
-[[inputs.system]]
-  fieldpass = ["load1", "load5", "load15", "uptime"]
-EOF
-
-[[ $? -ne 0 ]] && log_error "Failed to write config." && cat "$TELEGRAF_CONFIG" && exit 1
-log_info "Telegraf configuration written to $TELEGRAF_CONFIG"
-
-# --- Start and Enable Telegraf ---
-log_info "Enabling and starting Telegraf service..."
-sudo systemctl enable --now telegraf
-[[ $? -ne 0 ]] && log_error "Failed to start Telegraf service." && exit 1
-
-# --- Final Check ---
-log_info "Checking if Telegraf is active..."
-if sudo systemctl is-active --quiet telegraf; then
-  log_info "Telegraf is active and running."
-else
-  log_error "Telegraf is not running."
-  exit 1
-fi
-
-log_info "Telegraf setup complete. Logs at $LOG_FILE"
+log "Install complete. Next run: configure_telegraf_timescale.sh"
 exit 0
Index: /branches/amp_4_0/platform/tools/install_timescaledb.sh
===================================================================
--- /branches/amp_4_0/platform/tools/install_timescaledb.sh	(nonexistent)
+++ /branches/amp_4_0/platform/tools/install_timescaledb.sh	(working copy)
@@ -0,0 +1,115 @@
+#!/bin/bash
+# Minimal TimescaleDB CE enable script for Rocky Linux 9 + PostgreSQL 17
+# Assumes PostgreSQL 17 is already installed and running.
+set -euo pipefail
+
+### Config (edit as needed)
+PG_VERSION="17"
+DB_SUPERUSER="postgres"                 # local superuser
+DB_SUPERUSER_PASSWORD="Arr@y2050"       # password for the postgres user (local auth)
+NEW_DB_NAME="amp_ts"
+NEW_USER="amp_ts_user"
+NEW_USER_PASSWORD="Array@123$"
+
+# Derived paths
+PGDATA="/var/lib/pgsql/${PG_VERSION}/data"
+CONF_FILE="${PGDATA}/postgresql.conf"
+PG_SERVICE="postgresql-${PG_VERSION}"
+PG_BIN_DIR="/usr/pgsql-${PG_VERSION}/bin"
+
+log()   { echo "[$(date +'%F %T')] $*"; }
+error() { echo "[ERROR $(date +'%F %T')] $*" >&2; }
+
+require() { command -v "$1" &>/dev/null || { error "Missing command: $1"; exit 1; } }
+
+[[ $EUID -eq 0 ]] || { error "Run as root (sudo)."; exit 1; }
+require dnf
+require systemctl
+require sed
+require tee
+
+log "Adding TimescaleDB repository…"
+tee /etc/yum.repos.d/timescale_timescaledb.repo > /dev/null <<'EOF'
+[timescale_timescaledb]
+name=timescale_timescaledb
+baseurl=https://packagecloud.io/timescale/timescaledb/el/9/$basearch
+repo_gpgcheck=1
+enabled=1
+gpgcheck=0
+gpgkey=https://packagecloud.io/timescale/timescaledb/gpgkey
+sslverify=1
+metadata_expire=300
+EOF
+
+dnf clean all -y
+dnf makecache -y
+
+log "Installing TimescaleDB CE for PostgreSQL ${PG_VERSION}…"
+dnf -y install "timescaledb-2-postgresql-${PG_VERSION}"
+
+# Optional tuning tool
+dnf -y install timescaledb-tools || true
+
+# Ensure shared_preload_libraries includes timescaledb
+if ! grep -q "^shared_preload_libraries.*timescaledb" "$CONF_FILE"; then
+  if grep -q "^shared_preload_libraries" "$CONF_FILE"; then
+    sed -i "s/^shared_preload_libraries.*/shared_preload_libraries = 'timescaledb'/" "$CONF_FILE"
+  else
+    echo "shared_preload_libraries = 'timescaledb'" >> "$CONF_FILE"
+  fi
+fi
+
+# Run timescaledb-tune if available (non-interactive)
+if command -v timescaledb-tune &>/dev/null; then
+  log "Running timescaledb-tune…"
+  timescaledb-tune --quiet --yes --pg-config "${PG_BIN_DIR}/pg_config" || true
+fi
+
+log "Restarting ${PG_SERVICE}…"
+systemctl restart "${PG_SERVICE}"
+
+# Wait for server
+log "Waiting for PostgreSQL to accept connections…"
+for i in {1..20}; do
+  sleep 2
+  PGPASSWORD="$DB_SUPERUSER_PASSWORD" "${PG_BIN_DIR}/psql" -U "$DB_SUPERUSER" -h 127.0.0.1 -c "SELECT 1" &>/dev/null && break
+  [[ $i -eq 20 ]] && { error "PostgreSQL not accepting connections."; exit 1; }
+done
+
+# Create role if missing
+export PGPASSWORD="$DB_SUPERUSER_PASSWORD"
+sudo -E -u postgres "${PG_BIN_DIR}/psql" -v ON_ERROR_STOP=1 <<SQL
+DO \$\$ BEGIN
+  IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${NEW_USER}') THEN
+    CREATE ROLE ${NEW_USER} LOGIN PASSWORD '${NEW_USER_PASSWORD}';
+  END IF;
+END \$\$;
+SQL
+
+# Create DB if missing
+DB_EXISTS="$(sudo -E -u postgres "${PG_BIN_DIR}/psql" -tAc "SELECT 1 FROM pg_database WHERE datname='${NEW_DB_NAME}'" 2>/dev/null || true)"
+if [[ "${DB_EXISTS:-}" != "1" ]]; then
+  log "Creating database ${NEW_DB_NAME}…"
+  sudo -E -u postgres "${PG_BIN_DIR}/psql" -c "CREATE DATABASE ${NEW_DB_NAME}"
+else
+  log "Database ${NEW_DB_NAME} already exists."
+fi
+
+# Enable extension + grants
+sudo -E -u postgres "${PG_BIN_DIR}/psql" -v ON_ERROR_STOP=1 <<SQL
+\c ${NEW_DB_NAME}
+CREATE EXTENSION IF NOT EXISTS timescaledb;
+GRANT ALL PRIVILEGES ON DATABASE ${NEW_DB_NAME} TO ${NEW_USER};
+ALTER DATABASE ${NEW_DB_NAME} OWNER TO ${NEW_USER};
+SQL
+unset PGPASSWORD
+
+log "Done. TimescaleDB CE enabled on PostgreSQL ${PG_VERSION}."
+
+echo
+echo "psql test:"
+echo "  PGPASSWORD='${NEW_USER_PASSWORD}' psql -h 127.0.0.1 -U ${NEW_USER} -d ${NEW_DB_NAME} -c '\dx timescaledb'"
+echo
+echo "Next steps:"
+echo "  - Create hypertables and (optionally) continuous aggregates for your metrics."
+echo "  - Point Telegraf PostgreSQL output plugin to DB=${NEW_DB_NAME}, user=${NEW_USER}."
Index: /branches/amp_4_0/platform/tools/telegraf_snmp_timescale.sql
===================================================================
--- /branches/amp_4_0/platform/tools/telegraf_snmp_timescale.sql	(nonexistent)
+++ /branches/amp_4_0/platform/tools/telegraf_snmp_timescale.sql	(working copy)
@@ -0,0 +1,240 @@
+-- telegraf_snmp_timescale_fixed.sql
+-- TimescaleDB schema for Telegraf SNMP inputs (Array Networks)
+-- Compatible with TimescaleDB OSS; uses standard row compression (NOT columnstore).
+-- Creates hypertables, indexes, compression + retention, and 5-minute CAs (WITH NO DATA).
+
+BEGIN;
+
+-- 0) Enable TimescaleDB (first run requires superuser)
+CREATE EXTENSION IF NOT EXISTS timescaledb;
+
+-- 1) MEASUREMENT: an_device_metrics
+CREATE TABLE IF NOT EXISTS an_device_metrics (
+    time TIMESTAMPTZ NOT NULL,
+    agent_host TEXT NOT NULL,
+    cpu_usage DOUBLE PRECISION,
+    mem_usage DOUBLE PRECISION,
+    net_mem_usage DOUBLE PRECISION,
+    total_openssl_conns BIGINT,
+    connections BIGINT,
+    requests BIGINT,
+    total_in BIGINT,
+    total_out BIGINT,
+    PRIMARY KEY (time, agent_host)
+);
+SELECT create_hypertable('an_device_metrics','time','agent_host', number_partitions => 4, if_not_exists => TRUE);
+CREATE INDEX IF NOT EXISTS idx_metrics_agent_time ON an_device_metrics (agent_host, time DESC);
+
+-- 2) MEASUREMENT: an_device_performance
+CREATE TABLE IF NOT EXISTS an_device_performance (
+    time TIMESTAMPTZ NOT NULL,
+    agent_host TEXT NOT NULL,
+    ssl_ae_core_utilization DOUBLE PRECISION,
+    ssl_se_core_utilization DOUBLE PRECISION,
+    PRIMARY KEY (time, agent_host)
+);
+SELECT create_hypertable('an_device_performance','time','agent_host', number_partitions => 4, if_not_exists => TRUE);
+CREATE INDEX IF NOT EXISTS idx_perf_agent_time ON an_device_performance (agent_host, time DESC);
+
+-- 3) TABLE: an_device_storage (HOST-RESOURCES-MIB hrStorageTable)
+-- hrStorage values are in allocation units; store alloc_unit to compute bytes later.
+CREATE TABLE IF NOT EXISTS an_device_storage (
+    time TIMESTAMPTZ NOT NULL,
+    agent_host TEXT NOT NULL,
+    prefix TEXT NOT NULL,
+    size BIGINT,          -- hrStorageSize
+    used BIGINT,          -- hrStorageUsed
+    alloc_unit BIGINT,    -- hrStorageAllocationUnits
+    PRIMARY KEY (time, agent_host, prefix)
+);
+SELECT create_hypertable('an_device_storage','time','agent_host', number_partitions => 4, if_not_exists => TRUE);
+CREATE INDEX IF NOT EXISTS idx_storage_prefix ON an_device_storage (prefix);
+CREATE INDEX IF NOT EXISTS idx_storage_agent_time ON an_device_storage (agent_host, time DESC);
+
+-- 4) TABLE: apv_virtual_stats
+CREATE TABLE IF NOT EXISTS apv_virtual_stats (
+    time TIMESTAMPTZ NOT NULL,
+    agent_host TEXT NOT NULL,
+    serverid TEXT NOT NULL,
+    addr TEXT NOT NULL,
+    port TEXT NOT NULL,
+    protocol TEXT NOT NULL,
+    url_hits BIGINT,
+    hostname_hits BIGINT,
+    perstnt_cookie_hits BIGINT,
+    qos_cookie_hits BIGINT,
+    default_hits BIGINT,
+    perstnt_url_hits BIGINT,
+    static_hits BIGINT,
+    qos_network_hits BIGINT,
+    qos_url_hits BIGINT,
+    backup_hits BIGINT,
+    cache_hits BIGINT,
+    regex_hits BIGINT,
+    rcookie_hits BIGINT,
+    icookie_hits BIGINT,
+    conn_cnt BIGINT,
+    qos_client_port_hits BIGINT,
+    qos_body_hits BIGINT,
+    header_hits BIGINT,
+    hash_url_hits BIGINT,
+    redirect_hits BIGINT,
+    conn_per_sec DOUBLE PRECISION,
+    in_byte_per_sec DOUBLE PRECISION,
+    out_byte_per_sec DOUBLE PRECISION,
+    in_packet_per_sec DOUBLE PRECISION,
+    out_packet_per_sec DOUBLE PRECISION,
+    health_status TEXT,
+    PRIMARY KEY (time, agent_host, serverid, addr, port, protocol)
+);
+SELECT create_hypertable('apv_virtual_stats','time','agent_host', number_partitions => 8, if_not_exists => TRUE);
+CREATE INDEX IF NOT EXISTS idx_virtual_serverid ON apv_virtual_stats (serverid);
+CREATE INDEX IF NOT EXISTS idx_virtual_agent_time ON apv_virtual_stats (agent_host, time DESC);
+CREATE INDEX IF NOT EXISTS idx_virtual_server_time ON apv_virtual_stats (serverid, time DESC);
+
+-- 5) TABLE: apv_real_stats
+CREATE TABLE IF NOT EXISTS apv_real_stats (
+    time TIMESTAMPTZ NOT NULL,
+    agent_host TEXT NOT NULL,
+    real_server_id TEXT NOT NULL,
+    addr TEXT NOT NULL,
+    port TEXT NOT NULL,
+    protocol TEXT NOT NULL,
+    status TEXT NOT NULL,
+    rs_cnt_of_req BIGINT,
+    rs_conn_cnt BIGINT,
+    rs_total_hits BIGINT,
+    rs_conn_per_sec DOUBLE PRECISION,
+    rs_in_byte_per_sec DOUBLE PRECISION,
+    rs_out_byte_per_sec DOUBLE PRECISION,
+    rs_in_packet_per_sec DOUBLE PRECISION,
+    rs_out_packet_per_sec DOUBLE PRECISION,
+    PRIMARY KEY (time, agent_host, real_server_id, addr, port, protocol)
+);
+SELECT create_hypertable('apv_real_stats','time','agent_host', number_partitions => 8, if_not_exists => TRUE);
+CREATE INDEX IF NOT EXISTS idx_real_realserverid ON apv_real_stats (real_server_id);
+CREATE INDEX IF NOT EXISTS idx_real_agent_time ON apv_real_stats (agent_host, time DESC);
+CREATE INDEX IF NOT EXISTS idx_real_server_time ON apv_real_stats (real_server_id, time DESC);
+
+-- 6) TABLE: apv_llb_stats
+-- Note: several fields arrive as strings (e.g., "7.502ms", "7+00:33:52"); keep TEXT.
+CREATE TABLE IF NOT EXISTS apv_llb_stats (
+    time TIMESTAMPTZ NOT NULL,
+    agent_host TEXT NOT NULL,
+    link_index BIGINT,
+    link_name TEXT NOT NULL,
+    link_gateway TEXT,
+    link_status TEXT NOT NULL,
+    link_resp_time TEXT,
+    link_up_time TEXT,
+    link_down_time TEXT,
+    link_down_count BIGINT,
+    link_down_event TEXT,
+    link_bandwid_in BIGINT,
+    link_bandwid_out BIGINT,
+    link_thresh BIGINT,
+    link_hits BIGINT,
+    link_conn BIGINT,
+    link_usage BIGINT,
+    PRIMARY KEY (time, agent_host, link_name)
+);
+SELECT create_hypertable('apv_llb_stats','time','agent_host', number_partitions => 4, if_not_exists => TRUE);
+CREATE INDEX IF NOT EXISTS idx_llb_linkname ON apv_llb_stats (link_name);
+CREATE INDEX IF NOT EXISTS idx_llb_agent_time ON apv_llb_stats (agent_host, time DESC);
+
+-- 7) Ensure NOT using columnstore policies (ignore if function/policy doesn’t exist)
+DO $$ BEGIN PERFORM remove_columnstore_policy('apv_virtual_stats');     EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+DO $$ BEGIN PERFORM remove_columnstore_policy('apv_real_stats');        EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+DO $$ BEGIN PERFORM remove_columnstore_policy('apv_llb_stats');         EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+DO $$ BEGIN PERFORM remove_columnstore_policy('an_device_metrics');     EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+DO $$ BEGIN PERFORM remove_columnstore_policy('an_device_performance'); EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+DO $$ BEGIN PERFORM remove_columnstore_policy('an_device_storage');     EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+
+-- 8) Standard row-compression (NOT columnstore)
+ALTER TABLE IF EXISTS apv_virtual_stats     SET (timescaledb.compress, timescaledb.compress_segmentby = 'agent_host, serverid',         timescaledb.compress_orderby = 'time DESC');
+ALTER TABLE IF EXISTS apv_real_stats        SET (timescaledb.compress, timescaledb.compress_segmentby = 'agent_host, real_server_id',   timescaledb.compress_orderby = 'time DESC');
+ALTER TABLE IF EXISTS apv_llb_stats         SET (timescaledb.compress, timescaledb.compress_segmentby = 'agent_host, link_name',        timescaledb.compress_orderby = 'time DESC');
+ALTER TABLE IF EXISTS an_device_metrics     SET (timescaledb.compress, timescaledb.compress_segmentby = 'agent_host',                   timescaledb.compress_orderby = 'time DESC');
+ALTER TABLE IF EXISTS an_device_performance SET (timescaledb.compress, timescaledb.compress_segmentby = 'agent_host',                   timescaledb.compress_orderby = 'time DESC');
+ALTER TABLE IF EXISTS an_device_storage     SET (timescaledb.compress, timescaledb.compress_segmentby = 'agent_host, prefix',           timescaledb.compress_orderby = 'time DESC');
+
+-- 9) Compression policies (compress after 7 days)
+SELECT add_compression_policy('apv_virtual_stats',     INTERVAL '7 days');
+SELECT add_compression_policy('apv_real_stats',        INTERVAL '7 days');
+SELECT add_compression_policy('apv_llb_stats',         INTERVAL '7 days');
+SELECT add_compression_policy('an_device_metrics',     INTERVAL '7 days');
+SELECT add_compression_policy('an_device_performance', INTERVAL '7 days');
+SELECT add_compression_policy('an_device_storage',     INTERVAL '7 days');
+
+-- 10) Retention policies (drop after 180 days)
+SELECT add_retention_policy('apv_virtual_stats',     INTERVAL '180 days');
+SELECT add_retention_policy('apv_real_stats',        INTERVAL '180 days');
+SELECT add_retention_policy('apv_llb_stats',         INTERVAL '180 days');
+SELECT add_retention_policy('an_device_metrics',     INTERVAL '180 days');
+SELECT add_retention_policy('an_device_performance', INTERVAL '180 days');
+SELECT add_retention_policy('an_device_storage',     INTERVAL '180 days');
+
+-- 11) Continuous aggregates (5-minute) — WITH NO DATA
+-- 11.1) Virtual stats
+CREATE MATERIALIZED VIEW IF NOT EXISTS cag_apv_virtual_stats_5m
+WITH (timescaledb.continuous) AS
+SELECT
+  time_bucket('5 minutes', time) AS bucket,
+  agent_host,
+  serverid,
+  avg(conn_per_sec)     AS avg_connps,
+  avg(in_byte_per_sec)  AS avg_in_bps,
+  avg(out_byte_per_sec) AS avg_out_bps,
+  avg(in_packet_per_sec)  AS avg_in_pps,
+  avg(out_packet_per_sec) AS avg_out_pps
+FROM apv_virtual_stats
+GROUP BY bucket, agent_host, serverid
+WITH NO DATA;
+
+-- 11.2) Real stats
+CREATE MATERIALIZED VIEW IF NOT EXISTS cag_apv_real_stats_5m
+WITH (timescaledb.continuous) AS
+SELECT
+  time_bucket('5 minutes', time) AS bucket,
+  agent_host,
+  real_server_id,
+  avg(rs_conn_per_sec)      AS avg_connps,
+  avg(rs_in_byte_per_sec)   AS avg_in_bps,
+  avg(rs_out_byte_per_sec)  AS avg_out_bps,
+  avg(rs_in_packet_per_sec)  AS avg_in_pps,
+  avg(rs_out_packet_per_sec) AS avg_out_pps
+FROM apv_real_stats
+GROUP BY bucket, agent_host, real_server_id
+WITH NO DATA;
+
+-- 11.3) LLB stats (link_resp_time is TEXT → parse number before averaging, assume milliseconds)
+CREATE MATERIALIZED VIEW IF NOT EXISTS cag_apv_llb_stats_5m
+WITH (timescaledb.continuous) AS
+SELECT
+  time_bucket('5 minutes', time) AS bucket,
+  agent_host,
+  link_name,
+  avg( NULLIF(regexp_replace(link_resp_time, '[^0-9.]', '', 'g'), '')::double precision ) AS avg_resp_time_ms,
+  avg(link_usage)      AS avg_usage,
+  avg(link_bandwid_in)  AS avg_bandwid_in,
+  avg(link_bandwid_out) AS avg_bandwid_out,
+  max(link_down_count)  AS max_down_count
+FROM apv_llb_stats
+GROUP BY bucket, agent_host, link_name
+WITH NO DATA;
+
+-- 12) Refresh policies (remove if present, then add)
+DO $$ BEGIN PERFORM remove_continuous_aggregate_policy('cag_apv_virtual_stats_5m'); EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+DO $$ BEGIN PERFORM remove_continuous_aggregate_policy('cag_apv_real_stats_5m');    EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+DO $$ BEGIN PERFORM remove_continuous_aggregate_policy('cag_apv_llb_stats_5m');     EXCEPTION WHEN undefined_function THEN NULL; WHEN others THEN NULL; END $$;
+
+SELECT add_continuous_aggregate_policy('cag_apv_virtual_stats_5m', start_offset => INTERVAL '30 days', end_offset => INTERVAL '1 hour', schedule_interval => INTERVAL '15 minutes');
+SELECT add_continuous_aggregate_policy('cag_apv_real_stats_5m',    start_offset => INTERVAL '30 days', end_offset => INTERVAL '1 hour', schedule_interval => INTERVAL '15 minutes');
+SELECT add_continuous_aggregate_policy('cag_apv_llb_stats_5m',     start_offset => INTERVAL '30 days', end_offset => INTERVAL '1 hour', schedule_interval => INTERVAL '15 minutes');
+
+COMMIT;
+
+-- 13) Optional immediate backfill (outside tx)
+CALL refresh_continuous_aggregate('cag_apv_virtual_stats_5m', now() - INTERVAL '30 days', now());
+CALL refresh_continuous_aggregate('cag_apv_real_stats_5m',    now() - INTERVAL '30 days', now());
+CALL refresh_continuous_aggregate('cag_apv_llb_stats_5m',     now() - INTERVAL '30 days', now());
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/hive/storage.py
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/hive/storage.py	(revision 2695)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/hive/storage.py	(working copy)
@@ -114,6 +114,7 @@
             if path['type'] == "file_system":
                 path['size'] = getdirsize(path['path'])
             elif path['type'] == "es_query":
+                httpClient = None
                 try:
                     httpClient = http.client.HTTPConnection(CMDATA['ELASTICSEARCH_IP'],
                                                             str(CMDATA['ELASTICSEARCH_PORT']),
