i want to slightly change my approach, 1. first create a script that will identify stale series and create jason, save jason 2. I will use inputs from jason in my cleanup script only to clean those metric id strings...please change below code in these two formats...give those codes to me seprately ...import requests
import json
from datetime import datetime, timedelta
from concurrent.futures import ThreadPoolExecutor, as_completed
from dateutil.parser import isoparse  # You need to install python-dateutil package
 
# Configuration
INFLUX_HOST = "localhost"
INFLUX_PORT = 8086
DATABASE = "mydb"
RETENTION_POLICY = "autogen"
MEASUREMENT = "SIS"
USER = ""
PASSWORD = ""
USE_HTTPS = False
 
STALE_DAYS = 200
MAX_WORKERS = 10
 
DROPPED_JSON_FILE = "dropped_metric_ids.json"
 
def influx_request(path, params=None, method="GET"):
    protocol = "https" if USE_HTTPS else "http"
    url = f"{protocol}://{INFLUX_HOST}:{INFLUX_PORT}{path}"
    auth = (USER, PASSWORD) if USER and PASSWORD else None
    headers = {"Accept": "application/json"}
 
    for attempt in range(3):
        try:
            if method == "GET":
                resp = requests.get(url, params=params, auth=auth, headers=headers, timeout=30)
            elif method == "POST":
                resp = requests.post(url, params=params, auth=auth, headers=headers, timeout=30)
            else:
                raise ValueError("Unsupported HTTP method")
            resp.raise_for_status()
            return resp.json()
        except Exception as e:
            print(f"Request error on {url}: {e}, retrying...")
            import time; time.sleep(2 ** attempt)
    raise RuntimeError(f"Failed after retries: {url}")
 
def list_metric_id_strings():
    qry = f'SHOW TAG VALUES FROM "{MEASUREMENT}" WITH KEY = "metric_id_string"'
    res = influx_request("/query", params={"db": DATABASE, "q": qry})
    try:
        return [v[1] for v in res["results"][0]["series"][0]["values"]]
    except Exception as e:
        print(f"Error parsing metric_id_string values: {e}")
        return []
 
def get_last_timestamp(metric_id_string):
    qry = f'SELECT LAST(VALUE) FROM "{MEASUREMENT}" WHERE "metric_id_string" = \'{metric_id_string}\''
    res = influx_request("/query", params={"db": DATABASE, "q": qry})
    try:
        points = res["results"][0]["series"][0]["values"]
        ts_str = points[0][0]  # ISO8601 timestamp string
        return isoparse(ts_str)
    except Exception:
        return None
 
# Optional: check if series exists before drop (uncomment if you want to use)
# def series_exists(metric_id_string):
#     qry = f'SHOW SERIES FROM "{MEASUREMENT}" WHERE "metric_id_string" = \'{metric_id_string}\' LIMIT 1'
#     res = influx_request("/query", params={"db": DATABASE, "q": qry})
#     try:
#         return "series" in res["results"][0]
#     except Exception:
#         return False
 
def drop_series(metric_id_string):
    escaped_metric_id = metric_id_string.replace("'", r"\'")
    qry = f'DROP SERIES FROM "{MEASUREMENT}" WHERE "metric_id_string" = \'{escaped_metric_id}\''
    res = influx_request("/query", params={"db": DATABASE, "q": qry}, method="GET")
    if "results" in res and not ("error" in res["results"][0]):
        print(f"Dropped metric_id_string: {metric_id_string}")
        return True
    else:
        print(f"Failed to drop metric_id_string {metric_id_string}: {json.dumps(res, indent=2)}")
        return False
 
def load_dropped():
    try:
        with open(DROPPED_JSON_FILE, "r") as f:
            return set(json.load(f))
    except Exception:
        return set()
 
def save_dropped(dropped):
    with open(DROPPED_JSON_FILE, "w") as f:
        json.dump(list(dropped), f, indent=2)
 
def main():
    from datetime import timezone
    stale_threshold = datetime.now(timezone.utc) - timedelta(days=STALE_DAYS)
    print(f"Deleting series with last data older than: {stale_threshold.isoformat()}Z")
 
    dropped_metric_ids = load_dropped()
    all_metric_ids = list_metric_id_strings()
    to_check = [m for m in all_metric_ids if m not in dropped_metric_ids]
 
    print(f"Total metric_id_strings: {len(all_metric_ids)}")
    print(f"Metric_id_strings remaining after cache: {len(to_check)}")
 
    stale_metric_ids = []
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        futures = {executor.submit(get_last_timestamp, m): m for m in to_check}
        for future in as_completed(futures):
            m = futures[future]
            try:
                last_ts = future.result()
                if last_ts is None or last_ts < stale_threshold:
                    print(f"Stale: {m} (last timestamp: {last_ts})")
                    stale_metric_ids.append(m)
                else:
                    print(f"Active: {m} (last timestamp: {last_ts})")
            except Exception as e:
                print(f"Error fetching timestamp for {m}: {e}")
 
    print(f"Found {len(stale_metric_ids)} stale metric_id_strings to drop")
 
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        futures = {executor.submit(drop_series, m): m for m in stale_metric_ids}
        for future in as_completed(futures):
            m = futures[future]
            try:
                success = future.result()
                if success:
                    dropped_metric_ids.add(m)
                    if len(dropped_metric_ids) % 50 == 0:
                        save_dropped(dropped_metric_ids)
                else:
                    print(f"Failed to drop {m}")
            except Exception as e:
                print(f"Exception dropping {m}: {e}")
 
    save_dropped(dropped_metric_ids)
    print("Cleanup complete.")
 
 
if __name__ == "__main__":
    main()