<?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: Physical CPU cores &amp;amp; Logical CPU cores Information in Open Q&amp;A</title>
    <link>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288858#M37891</link>
    <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://community.dynatrace.com/t5/user/viewprofilepage/user-id/22017"&gt;@Babar_Qayyum&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;you can use this script and send result as metrics:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# === KONFIGURACJA ===
DT_BASE_URL = "https://dynatrace.example.com/e/ENV-ID"  # Your Managed/SaaS base URL
DT_API_TOKEN = "dt0c01.xxxxx.yyyyy"                             # API token: entities.read

# (optional) entity selector filters:
MZ_NAME = None          # eg. "Production" or None
MZ_ID = None            # eg. "1234567890123456789" or None
TAG = None              # eg. "owner:team-a" lub "Linux" lub None
NAME_FILTER = None      # eg. "app-host*" -&amp;gt; startsWith; bez * -&amp;gt; equals; None to skip

# (optional) additional client-side "contains" filter:
CLIENT_FILTER_CONTAINS = None  # np. "k8s-node"

# exit:
OUTPUT_CSV = "cpu_cores.csv"
PAGE_SIZE = 500
VERIFY_TLS = True       # set to path to CA or False if you have a custom cert (not recommended)

# ====================

import csv
import sys
import time
from typing import Dict, Iterable, List, Optional

import requests

API_PATH = "/api/v2/entities"
TIMEOUT = 30
RETRIES = 3
BACKOFF = 2.0


def build_entity_selector(
    mz_name: Optional[str],
    mz_id: Optional[str],
    tag: Optional[str],
    name_filter: Optional[str],
) -&amp;gt; str:
    parts = ['type("HOST")']
    if mz_name:
        parts.append(f'mzName("{mz_name}")')
    if mz_id:
        parts.append(f'mzId({mz_id})')
    if tag:
        if any(c in tag for c in [' ', ':', '"']):
            parts.append(f'tag("{tag}")')
        else:
            parts.append(f'tag({tag})')
    if name_filter:
        if name_filter.endswith("*"):
            parts.append(f'entityName.startsWith("{name_filter[:-1]}")')
        else:
            parts.append(f'entityName.equals("{name_filter}")')
    return ",".join(parts)


def request_entities(session: requests.Session, base_url: str, token: str, params: Dict[str, str]):
    headers = {"Authorization": f"Api-Token {token}"}
    url = base_url.rstrip("/") + API_PATH
    last_err = None
    for attempt in range(1, RETRIES + 1):
        try:
            resp = session.get(url, headers=headers, params=params, timeout=TIMEOUT, verify=VERIFY_TLS)
            if resp.status_code in (429, 500, 502, 503, 504):
                last_err = Exception(f"HTTP {resp.status_code}: {resp.text[:300]}")
                time.sleep(BACKOFF * attempt)
                continue
            resp.raise_for_status()
            return resp.json()
        except requests.RequestException as e:
            last_err = e
            time.sleep(BACKOFF * attempt)
    raise SystemExit(f"API request failed after {RETRIES} retries: {last_err}")


def fetch_all_hosts(base_url: str, token: str, entity_selector: str, page_size: int = PAGE_SIZE) -&amp;gt; Iterable[Dict]:
    fields = ",".join([
        "+properties.cpuCores",
        "+properties.logicalCpuCores",
        "+properties.osType",
        "+properties.monitoringMode",
        "+managementZones",
        "+lastSeenTms",
    ])
    params = {
        "entitySelector": entity_selector,
        "pageSize": str(page_size),
        "fields": fields,
    }
    session = requests.Session()

    data = request_entities(session, base_url, token, params)
    for e in data.get("entities", []):
        yield e

    next_key = data.get("nextPageKey")
    while next_key:
        data = request_entities(session, base_url, token, {"nextPageKey": next_key})
        for e in data.get("entities", []):
            yield e
        next_key = data.get("nextPageKey")


def to_int_safe(v) -&amp;gt; Optional[int]:
    try:
        return int(v)
    except Exception:
        return None


def main():
    if not DT_BASE_URL or not DT_API_TOKEN or DT_API_TOKEN.strip().startswith("dt0c01.E"):
        print("fill in the DATABASE_URL and DT API TOKEN correctly (with the entities.read scope) in the CONFIGURATION section.", file=sys.stderr)
        sys.exit(1)

    selector = build_entity_selector(MZ_NAME, MZ_ID, TAG, NAME_FILTER)

    rows: List[Dict] = []
    for ent in fetch_all_hosts(DT_BASE_URL, DT_API_TOKEN, selector, PAGE_SIZE):
        if ent.get("type") != "HOST":
            continue
        name = ent.get("displayName") or ""
        if CLIENT_FILTER_CONTAINS and CLIENT_FILTER_CONTAINS.lower() not in name.lower():
            continue

        props = ent.get("properties", {}) or {}
        cpu_phys = to_int_safe(props.get("cpuCores"))
        cpu_log = to_int_safe(props.get("logicalCpuCores"))

        mz_list = ent.get("managementZones", []) or []
        mz_names = ";".join(sorted({mz.get("name", "") for mz in mz_list if mz.get("name")}))

        rows.append({
            "hostId": ent.get("entityId"),
            "hostName": name,
            "osType": props.get("osType"),
            "monitoringMode": props.get("monitoringMode"),
            "cpuCores_physical": cpu_phys,
            "cpuCores_logical": cpu_log,
            "managementZones": mz_names,
            "lastSeenTms": ent.get("lastSeenTms"),
        })

    rows.sort(key=lambda r: (r.get("hostName") or "").lower())

    fieldnames = [
        "hostId",
        "hostName",
        "osType",
        "monitoringMode",
        "cpuCores_physical",
        "cpuCores_logical",
        "managementZones",
        "lastSeenTms",
    ]
    with open(OUTPUT_CSV, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(rows)

    print(f"Saved  {len(rows)} records to: {OUTPUT_CSV}")


if __name__ == "__main__":
    main()&lt;/LI-CODE&gt;&lt;P&gt;you should recive csv like this:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="t_pawlak_0-1761821850804.png" style="width: 400px;"&gt;&lt;img src="https://community.dynatrace.com/t5/image/serverpage/image-id/30773i36AFD9CEDE5A19E5/image-size/medium?v=v2&amp;amp;px=400" role="button" title="t_pawlak_0-1761821850804.png" alt="t_pawlak_0-1761821850804.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
    <pubDate>Thu, 30 Oct 2025 10:57:46 GMT</pubDate>
    <dc:creator>t_pawlak</dc:creator>
    <dc:date>2025-10-30T10:57:46Z</dc:date>
    <item>
      <title>Physical CPU cores &amp; Logical CPU cores Information</title>
      <link>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288153#M37812</link>
      <description>&lt;P&gt;Dear All,&lt;/P&gt;&lt;P&gt;How to obtain the physical/logical cores of each host/VM to make a report?&lt;/P&gt;&lt;P&gt;Regards,&lt;/P&gt;&lt;P&gt;Babar Qayyum&lt;/P&gt;</description>
      <pubDate>Mon, 20 Oct 2025 07:03:21 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288153#M37812</guid>
      <dc:creator>Babar_Qayyum</dc:creator>
      <dc:date>2025-10-20T07:03:21Z</dc:date>
    </item>
    <item>
      <title>Re: Physical CPU cores &amp; Logical CPU cores Information</title>
      <link>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288179#M37815</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;Maybe using DQL, it was discussed in &lt;A title="this thread" href="https://community.dynatrace.com/t5/Open-Q-A/CPU-cores-visibility/m-p/254106" target="_blank" rel="noopener"&gt;this thread&lt;/A&gt;.&lt;/P&gt;&lt;P&gt;Best regards&lt;/P&gt;</description>
      <pubDate>Mon, 20 Oct 2025 13:17:32 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288179#M37815</guid>
      <dc:creator>AntonPineiro</dc:creator>
      <dc:date>2025-10-20T13:17:32Z</dc:date>
    </item>
    <item>
      <title>Re: Physical CPU cores &amp; Logical CPU cores Information</title>
      <link>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288213#M37825</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://community.dynatrace.com/t5/user/viewprofilepage/user-id/58682"&gt;@AntonPineiro&lt;/a&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you for your comments. We have Dynatrace Managed.&lt;/P&gt;&lt;P&gt;Regards,&lt;/P&gt;&lt;P&gt;Babar Qayyum&lt;/P&gt;</description>
      <pubDate>Mon, 20 Oct 2025 23:26:55 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288213#M37825</guid>
      <dc:creator>Babar_Qayyum</dc:creator>
      <dc:date>2025-10-20T23:26:55Z</dc:date>
    </item>
    <item>
      <title>Re: Physical CPU cores &amp; Logical CPU cores Information</title>
      <link>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288216#M37828</link>
      <description>&lt;P&gt;&lt;a href="https://community.dynatrace.com/t5/user/viewprofilepage/user-id/22017"&gt;@Babar_Qayyum&lt;/a&gt;&amp;nbsp;You can try the&amp;nbsp;Monitored entities API and extract fields&amp;nbsp;properties.cpuCores and properties.logicalCpuCores&lt;/P&gt;&lt;P&gt;&lt;A href="https://docs.dynatrace.com/managed/discover-dynatrace/references/dynatrace-api/environment-api/entity-v2/get-entities-list" target="_blank"&gt;https://docs.dynatrace.com/managed/discover-dynatrace/references/dynatrace-api/environment-api/entity-v2/get-entities-list&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 21 Oct 2025 00:45:41 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288216#M37828</guid>
      <dc:creator>p_devulapalli</dc:creator>
      <dc:date>2025-10-21T00:45:41Z</dc:date>
    </item>
    <item>
      <title>Re: Physical CPU cores &amp; Logical CPU cores Information</title>
      <link>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288858#M37891</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://community.dynatrace.com/t5/user/viewprofilepage/user-id/22017"&gt;@Babar_Qayyum&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;you can use this script and send result as metrics:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# === KONFIGURACJA ===
DT_BASE_URL = "https://dynatrace.example.com/e/ENV-ID"  # Your Managed/SaaS base URL
DT_API_TOKEN = "dt0c01.xxxxx.yyyyy"                             # API token: entities.read

# (optional) entity selector filters:
MZ_NAME = None          # eg. "Production" or None
MZ_ID = None            # eg. "1234567890123456789" or None
TAG = None              # eg. "owner:team-a" lub "Linux" lub None
NAME_FILTER = None      # eg. "app-host*" -&amp;gt; startsWith; bez * -&amp;gt; equals; None to skip

# (optional) additional client-side "contains" filter:
CLIENT_FILTER_CONTAINS = None  # np. "k8s-node"

# exit:
OUTPUT_CSV = "cpu_cores.csv"
PAGE_SIZE = 500
VERIFY_TLS = True       # set to path to CA or False if you have a custom cert (not recommended)

# ====================

import csv
import sys
import time
from typing import Dict, Iterable, List, Optional

import requests

API_PATH = "/api/v2/entities"
TIMEOUT = 30
RETRIES = 3
BACKOFF = 2.0


def build_entity_selector(
    mz_name: Optional[str],
    mz_id: Optional[str],
    tag: Optional[str],
    name_filter: Optional[str],
) -&amp;gt; str:
    parts = ['type("HOST")']
    if mz_name:
        parts.append(f'mzName("{mz_name}")')
    if mz_id:
        parts.append(f'mzId({mz_id})')
    if tag:
        if any(c in tag for c in [' ', ':', '"']):
            parts.append(f'tag("{tag}")')
        else:
            parts.append(f'tag({tag})')
    if name_filter:
        if name_filter.endswith("*"):
            parts.append(f'entityName.startsWith("{name_filter[:-1]}")')
        else:
            parts.append(f'entityName.equals("{name_filter}")')
    return ",".join(parts)


def request_entities(session: requests.Session, base_url: str, token: str, params: Dict[str, str]):
    headers = {"Authorization": f"Api-Token {token}"}
    url = base_url.rstrip("/") + API_PATH
    last_err = None
    for attempt in range(1, RETRIES + 1):
        try:
            resp = session.get(url, headers=headers, params=params, timeout=TIMEOUT, verify=VERIFY_TLS)
            if resp.status_code in (429, 500, 502, 503, 504):
                last_err = Exception(f"HTTP {resp.status_code}: {resp.text[:300]}")
                time.sleep(BACKOFF * attempt)
                continue
            resp.raise_for_status()
            return resp.json()
        except requests.RequestException as e:
            last_err = e
            time.sleep(BACKOFF * attempt)
    raise SystemExit(f"API request failed after {RETRIES} retries: {last_err}")


def fetch_all_hosts(base_url: str, token: str, entity_selector: str, page_size: int = PAGE_SIZE) -&amp;gt; Iterable[Dict]:
    fields = ",".join([
        "+properties.cpuCores",
        "+properties.logicalCpuCores",
        "+properties.osType",
        "+properties.monitoringMode",
        "+managementZones",
        "+lastSeenTms",
    ])
    params = {
        "entitySelector": entity_selector,
        "pageSize": str(page_size),
        "fields": fields,
    }
    session = requests.Session()

    data = request_entities(session, base_url, token, params)
    for e in data.get("entities", []):
        yield e

    next_key = data.get("nextPageKey")
    while next_key:
        data = request_entities(session, base_url, token, {"nextPageKey": next_key})
        for e in data.get("entities", []):
            yield e
        next_key = data.get("nextPageKey")


def to_int_safe(v) -&amp;gt; Optional[int]:
    try:
        return int(v)
    except Exception:
        return None


def main():
    if not DT_BASE_URL or not DT_API_TOKEN or DT_API_TOKEN.strip().startswith("dt0c01.E"):
        print("fill in the DATABASE_URL and DT API TOKEN correctly (with the entities.read scope) in the CONFIGURATION section.", file=sys.stderr)
        sys.exit(1)

    selector = build_entity_selector(MZ_NAME, MZ_ID, TAG, NAME_FILTER)

    rows: List[Dict] = []
    for ent in fetch_all_hosts(DT_BASE_URL, DT_API_TOKEN, selector, PAGE_SIZE):
        if ent.get("type") != "HOST":
            continue
        name = ent.get("displayName") or ""
        if CLIENT_FILTER_CONTAINS and CLIENT_FILTER_CONTAINS.lower() not in name.lower():
            continue

        props = ent.get("properties", {}) or {}
        cpu_phys = to_int_safe(props.get("cpuCores"))
        cpu_log = to_int_safe(props.get("logicalCpuCores"))

        mz_list = ent.get("managementZones", []) or []
        mz_names = ";".join(sorted({mz.get("name", "") for mz in mz_list if mz.get("name")}))

        rows.append({
            "hostId": ent.get("entityId"),
            "hostName": name,
            "osType": props.get("osType"),
            "monitoringMode": props.get("monitoringMode"),
            "cpuCores_physical": cpu_phys,
            "cpuCores_logical": cpu_log,
            "managementZones": mz_names,
            "lastSeenTms": ent.get("lastSeenTms"),
        })

    rows.sort(key=lambda r: (r.get("hostName") or "").lower())

    fieldnames = [
        "hostId",
        "hostName",
        "osType",
        "monitoringMode",
        "cpuCores_physical",
        "cpuCores_logical",
        "managementZones",
        "lastSeenTms",
    ]
    with open(OUTPUT_CSV, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(rows)

    print(f"Saved  {len(rows)} records to: {OUTPUT_CSV}")


if __name__ == "__main__":
    main()&lt;/LI-CODE&gt;&lt;P&gt;you should recive csv like this:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="t_pawlak_0-1761821850804.png" style="width: 400px;"&gt;&lt;img src="https://community.dynatrace.com/t5/image/serverpage/image-id/30773i36AFD9CEDE5A19E5/image-size/medium?v=v2&amp;amp;px=400" role="button" title="t_pawlak_0-1761821850804.png" alt="t_pawlak_0-1761821850804.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 30 Oct 2025 10:57:46 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Open-Q-A/Physical-CPU-cores-amp-Logical-CPU-cores-Information/m-p/288858#M37891</guid>
      <dc:creator>t_pawlak</dc:creator>
      <dc:date>2025-10-30T10:57:46Z</dc:date>
    </item>
  </channel>
</rss>

