<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: report on all enrolled hosts irrespective of inactive status in Alerting</title>
    <link>https://community.dynatrace.com/t5/Alerting/report-on-all-enrolled-hosts-irrespective-of-inactive-status/m-p/287955#M5944</link>
    <description>&lt;P&gt;Hi,&lt;BR /&gt;you can achive this only by API. U can use this script:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;#!/usr/bin/env python3
import requests
import datetime as dt
import time
# === KONFIGURACJA ===
DT_BASE_URL = "https://dynatrace.example.com/e/ENV-ID"  # Your Managed/SaaS base URL
DT_API_TOKEN = "dt0c01.xxxxx.yyyyy"                     # Token with correct permissions (oneAgents.read and DataExport)

DAYS_BACK = 150                                         # Default timeframe (max 214 days)
INCLUDE_DETAILS = "false"                               # "true" or "false"
MANAGEMENT_ZONE = None                                  # e.g., "PROD" or None
MANAGEMENT_ZONE_ID = None                               # e.g., 123456789012345 or None
TAGS = []                                               # e.g., ["env:prod","team:backend"]
NETWORK_ZONE_ID = None                                  # e.g., "NETWORK_ZONE-123456789"

# ====================
MAX_DAYS = 214

def iso_utc(ms: int) -&amp;gt; str:
    return dt.datetime.utcfromtimestamp(ms/1000.0).strftime("%Y-%m-%dT%H:%M:%SZ")

def build_time_params(days_back: int):
    days = min(max(int(days_back), 1), MAX_DAYS)
    end_ts = int(time.time() * 1000) 
    start_ts = end_ts - days * 24 * 60 * 60 * 1000
    return {"startTimestamp": start_ts, "endTimestamp": end_ts}

def fetch_unmonitored():
    url = f"{DT_BASE_URL.rstrip('/')}/api/v1/oneagents"
    headers = {"Authorization": f"Api-Token {DT_API_TOKEN}"}

    params = {
        "availabilityState": "UNMONITORED",
        "includeDetails": INCLUDE_DETAILS,
        **build_time_params(DAYS_BACK),
    }
    if MANAGEMENT_ZONE_ID:
        params["managementZoneId"] = MANAGEMENT_ZONE_ID
    elif MANAGEMENT_ZONE:
        params["managementZone"] = MANAGEMENT_ZONE
    if TAGS:
        params["tag"] = TAGS
    if NETWORK_ZONE_ID:
        params["networkZoneId"] = NETWORK_ZONE_ID

    results = []
    while True:
        resp = requests.get(url, headers=headers, params=params, timeout=30)
        resp.raise_for_status()
        data = resp.json()

        for ha in data.get("hosts", []):
            host = ha.get("hostInfo", {}) or {}
            name = host.get("displayName") or host.get("discoveredName") or host.get("entityId")
            availability = ha.get("availabilityState")
            detailed = ha.get("detailedAvailabilityState")
            last_seen = host.get("lastSeenTimestamp")

            if availability == "UNMONITORED":
                results.append({
                    "name": name,
                    "since": last_seen,
                    "detail": detailed or "-",
                })

        next_key = data.get("nextPageKey")
        if not next_key:
            break
        params["nextPageKey"] = next_key

    return results

if __name__ == "__main__":
    try:
        rows = fetch_unmonitored()
    except requests.HTTPError as e:
        body = e.response.text if e.response is not None else ""
        print(f"HTTP error: {e}\nBody: {body}")
        raise SystemExit(1)

    if not rows:
        print("No UNMONITORED hosts found in the given timeframe.")
        raise SystemExit(0)

    # longest unmonitored at the top
    rows.sort(key=lambda r: (r["since"] or 0))

    print(f"{'HOST':50}  {'SINCE (UTC)':20}  {'DETAIL'}")
    print("-"*50 + "  " + "-"*20 + "  " + "-"*20)
    for r in rows:
        since = iso_utc(r["since"]) if r["since"] else "-"
        print(f"{r['name'][:50]:50}  {since:20}  {r['detail']}")&lt;/LI-CODE&gt;&lt;P&gt;This script:&lt;/P&gt;&lt;P&gt;Queries /api/v1/oneagents for hosts with availabilityState=UNMONITORED over the last DAYS_BACK days (max 214).&lt;/P&gt;&lt;P&gt;Supports optional filters: management zone (name/ID), tags, network zone.&lt;/P&gt;&lt;P&gt;Paginates with nextPageKey to fetch all results.&lt;/P&gt;&lt;P&gt;Collects each host’s name, last seen timestamp (approx. when it became unmonitored), and detailed availability state.&lt;/P&gt;&lt;P&gt;Sorts by oldest lastSeenTimestamp first and prints a table: HOST | SINCE (UTC) | DETAIL.&lt;/P&gt;&lt;P&gt;Optionally, you can extend it to push results via Metric Ingest (e.g. custom.unmonitored.hosts.total, custom.unmonitored.host.present) so you can visualize them directly in Dynatrace dashboards.&lt;BR /&gt;&lt;BR /&gt;There was a similar question &lt;A href="https://community.dynatrace.com/t5/Dashboarding/Dashboard-tile-showing-Hosts-currently-in-an-Unmonitored-state/m-p/286384#M5396" target="_self"&gt;here&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
    <pubDate>Wed, 15 Oct 2025 12:45:14 GMT</pubDate>
    <dc:creator>t_pawlak</dc:creator>
    <dc:date>2025-10-15T12:45:14Z</dc:date>
    <item>
      <title>report on all enrolled hosts irrespective of inactive status</title>
      <link>https://community.dynatrace.com/t5/Alerting/report-on-all-enrolled-hosts-irrespective-of-inactive-status/m-p/287926#M5943</link>
      <description>&lt;P&gt;when we take report of hosts it only list out monitored ones .&amp;nbsp;&lt;/P&gt;
&lt;P&gt;how to take report of all enrolled hosts irrespective of monitored , inactive , active etc&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 15 Oct 2025 12:57:17 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Alerting/report-on-all-enrolled-hosts-irrespective-of-inactive-status/m-p/287926#M5943</guid>
      <dc:creator>Vijayt</dc:creator>
      <dc:date>2025-10-15T12:57:17Z</dc:date>
    </item>
    <item>
      <title>Re: report on all enrolled hosts irrespective of inactive status</title>
      <link>https://community.dynatrace.com/t5/Alerting/report-on-all-enrolled-hosts-irrespective-of-inactive-status/m-p/287955#M5944</link>
      <description>&lt;P&gt;Hi,&lt;BR /&gt;you can achive this only by API. U can use this script:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;#!/usr/bin/env python3
import requests
import datetime as dt
import time
# === KONFIGURACJA ===
DT_BASE_URL = "https://dynatrace.example.com/e/ENV-ID"  # Your Managed/SaaS base URL
DT_API_TOKEN = "dt0c01.xxxxx.yyyyy"                     # Token with correct permissions (oneAgents.read and DataExport)

DAYS_BACK = 150                                         # Default timeframe (max 214 days)
INCLUDE_DETAILS = "false"                               # "true" or "false"
MANAGEMENT_ZONE = None                                  # e.g., "PROD" or None
MANAGEMENT_ZONE_ID = None                               # e.g., 123456789012345 or None
TAGS = []                                               # e.g., ["env:prod","team:backend"]
NETWORK_ZONE_ID = None                                  # e.g., "NETWORK_ZONE-123456789"

# ====================
MAX_DAYS = 214

def iso_utc(ms: int) -&amp;gt; str:
    return dt.datetime.utcfromtimestamp(ms/1000.0).strftime("%Y-%m-%dT%H:%M:%SZ")

def build_time_params(days_back: int):
    days = min(max(int(days_back), 1), MAX_DAYS)
    end_ts = int(time.time() * 1000) 
    start_ts = end_ts - days * 24 * 60 * 60 * 1000
    return {"startTimestamp": start_ts, "endTimestamp": end_ts}

def fetch_unmonitored():
    url = f"{DT_BASE_URL.rstrip('/')}/api/v1/oneagents"
    headers = {"Authorization": f"Api-Token {DT_API_TOKEN}"}

    params = {
        "availabilityState": "UNMONITORED",
        "includeDetails": INCLUDE_DETAILS,
        **build_time_params(DAYS_BACK),
    }
    if MANAGEMENT_ZONE_ID:
        params["managementZoneId"] = MANAGEMENT_ZONE_ID
    elif MANAGEMENT_ZONE:
        params["managementZone"] = MANAGEMENT_ZONE
    if TAGS:
        params["tag"] = TAGS
    if NETWORK_ZONE_ID:
        params["networkZoneId"] = NETWORK_ZONE_ID

    results = []
    while True:
        resp = requests.get(url, headers=headers, params=params, timeout=30)
        resp.raise_for_status()
        data = resp.json()

        for ha in data.get("hosts", []):
            host = ha.get("hostInfo", {}) or {}
            name = host.get("displayName") or host.get("discoveredName") or host.get("entityId")
            availability = ha.get("availabilityState")
            detailed = ha.get("detailedAvailabilityState")
            last_seen = host.get("lastSeenTimestamp")

            if availability == "UNMONITORED":
                results.append({
                    "name": name,
                    "since": last_seen,
                    "detail": detailed or "-",
                })

        next_key = data.get("nextPageKey")
        if not next_key:
            break
        params["nextPageKey"] = next_key

    return results

if __name__ == "__main__":
    try:
        rows = fetch_unmonitored()
    except requests.HTTPError as e:
        body = e.response.text if e.response is not None else ""
        print(f"HTTP error: {e}\nBody: {body}")
        raise SystemExit(1)

    if not rows:
        print("No UNMONITORED hosts found in the given timeframe.")
        raise SystemExit(0)

    # longest unmonitored at the top
    rows.sort(key=lambda r: (r["since"] or 0))

    print(f"{'HOST':50}  {'SINCE (UTC)':20}  {'DETAIL'}")
    print("-"*50 + "  " + "-"*20 + "  " + "-"*20)
    for r in rows:
        since = iso_utc(r["since"]) if r["since"] else "-"
        print(f"{r['name'][:50]:50}  {since:20}  {r['detail']}")&lt;/LI-CODE&gt;&lt;P&gt;This script:&lt;/P&gt;&lt;P&gt;Queries /api/v1/oneagents for hosts with availabilityState=UNMONITORED over the last DAYS_BACK days (max 214).&lt;/P&gt;&lt;P&gt;Supports optional filters: management zone (name/ID), tags, network zone.&lt;/P&gt;&lt;P&gt;Paginates with nextPageKey to fetch all results.&lt;/P&gt;&lt;P&gt;Collects each host’s name, last seen timestamp (approx. when it became unmonitored), and detailed availability state.&lt;/P&gt;&lt;P&gt;Sorts by oldest lastSeenTimestamp first and prints a table: HOST | SINCE (UTC) | DETAIL.&lt;/P&gt;&lt;P&gt;Optionally, you can extend it to push results via Metric Ingest (e.g. custom.unmonitored.hosts.total, custom.unmonitored.host.present) so you can visualize them directly in Dynatrace dashboards.&lt;BR /&gt;&lt;BR /&gt;There was a similar question &lt;A href="https://community.dynatrace.com/t5/Dashboarding/Dashboard-tile-showing-Hosts-currently-in-an-Unmonitored-state/m-p/286384#M5396" target="_self"&gt;here&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 15 Oct 2025 12:45:14 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Alerting/report-on-all-enrolled-hosts-irrespective-of-inactive-status/m-p/287955#M5944</guid>
      <dc:creator>t_pawlak</dc:creator>
      <dc:date>2025-10-15T12:45:14Z</dc:date>
    </item>
  </channel>
</rss>

