{
  "updated_at": "2026-10-02 16:19:46",
  "health_score": 100,
  "health_rows": [
    {
      "key": "apache",
      "name": "Apache 웹서버",
      "host": "127.0.0.1",
      "port": 80,
      "protocol": "http",
      "port_ok": true,
      "port_ms": 15,
      "health_ok": true,
      "health_ms": 34,
      "health_note": "200",
      "managed": false
    },
    {
      "key": "filezilla",
      "name": "FileZilla FTP",
      "host": "127.0.0.1",
      "port": 21,
      "protocol": "tcp",
      "port_ok": true,
      "port_ms": 13,
      "health_ok": true,
      "health_ms": 13,
      "health_note": "",
      "managed": false
    },
    {
      "key": "server_manager",
      "name": "Server Manager 상황판",
      "host": "127.0.0.1",
      "port": 9200,
      "protocol": "http",
      "port_ok": true,
      "port_ms": 0,
      "health_ok": true,
      "health_ms": 0,
      "health_note": "self",
      "managed": false
    },
    {
      "key": "blog_analysis_api",
      "name": "블로그 분석 API",
      "script": "D:\\honghee\\blog_api\\app.py",
      "port": 5000,
      "port_ok": true,
      "port_ms": 14,
      "health_url": "http://127.0.0.1:5000/",
      "health_ok": false,
      "health_ms": 1,
      "health_note": "HTTP Error 404: NOT FOUND",
      "auto_start": true,
      "pid": 5832,
      "manager_pid": 5832,
      "port_pid": 5832,
      "process_name": "python.exe",
      "command_line": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe D:\\honghee\\blog_api\\app.py",
      "executable_path": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe",
      "process_exists": true,
      "manager_owned": true,
      "owner_label": "Manager",
      "started_at": "2026-09-29 23:29:05",
      "managed": true
    },
    {
      "key": "shorts_ai_api",
      "name": "숏츠 생성 API",
      "script": "D:\\honghee\\blog_api\\shorts_ai_api.py",
      "port": 9000,
      "port_ok": true,
      "port_ms": 0,
      "health_url": "http://127.0.0.1:9000/health",
      "health_ok": true,
      "health_ms": 22,
      "health_note": "200",
      "auto_start": true,
      "pid": 6004,
      "manager_pid": 6004,
      "port_pid": 6004,
      "process_name": "python.exe",
      "command_line": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe D:\\honghee\\blog_api\\shorts_ai_api.py",
      "executable_path": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe",
      "process_exists": true,
      "manager_owned": true,
      "owner_label": "Manager",
      "started_at": "2026-09-29 23:29:06",
      "managed": true
    },
    {
      "key": "realestate_content_api",
      "name": "부동산 콘텐츠 API",
      "script": "D:\\honghee\\blog_api\\realestate_api.py",
      "port": 9100,
      "port_ok": true,
      "port_ms": 14,
      "health_url": "http://127.0.0.1:9100/health",
      "health_ok": true,
      "health_ms": 16,
      "health_note": "200",
      "auto_start": true,
      "pid": 7752,
      "manager_pid": 7752,
      "port_pid": 7752,
      "process_name": "python.exe",
      "command_line": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe D:\\honghee\\blog_api\\realestate_api.py",
      "executable_path": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe",
      "process_exists": true,
      "manager_owned": true,
      "owner_label": "Manager",
      "started_at": "2026-09-29 23:29:07",
      "managed": true
    },
    {
      "key": "multi_shorts_daemon",
      "name": "웹진 숏츠 자동생성·YouTube 업로드",
      "script": "D:\\honghee\\blog_api\\jobs\\multi_shorts_daemon.py",
      "port": 9300,
      "port_ok": true,
      "port_ms": 18,
      "health_url": "http://127.0.0.1:9300/",
      "health_ok": true,
      "health_ms": 0,
      "health_note": "200",
      "auto_start": true,
      "pid": 10904,
      "manager_pid": null,
      "port_pid": 10904,
      "process_name": "python.exe",
      "command_line": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe D:\\honghee\\blog_api\\jobs\\multi_shorts_daemon.py",
      "executable_path": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe",
      "process_exists": true,
      "manager_owned": false,
      "owner_label": "External",
      "started_at": "",
      "managed": true
    }
  ],
  "services": [
    {
      "key": "blog_analysis_api",
      "name": "블로그 분석 API",
      "script": "D:\\honghee\\blog_api\\app.py",
      "port": 5000,
      "port_ok": true,
      "port_ms": 24,
      "health_url": "http://127.0.0.1:5000/",
      "health_ok": false,
      "health_ms": 16,
      "health_note": "HTTP Error 404: NOT FOUND",
      "auto_start": true,
      "pid": 5832,
      "manager_pid": 5832,
      "port_pid": 5832,
      "process_name": "python.exe",
      "command_line": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe D:\\honghee\\blog_api\\app.py",
      "executable_path": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe",
      "process_exists": true,
      "manager_owned": true,
      "owner_label": "Manager",
      "started_at": "2026-09-29 23:29:05",
      "managed": true
    },
    {
      "key": "shorts_ai_api",
      "name": "숏츠 생성 API",
      "script": "D:\\honghee\\blog_api\\shorts_ai_api.py",
      "port": 9000,
      "port_ok": true,
      "port_ms": 0,
      "health_url": "http://127.0.0.1:9000/health",
      "health_ok": true,
      "health_ms": 0,
      "health_note": "200",
      "auto_start": true,
      "pid": 6004,
      "manager_pid": 6004,
      "port_pid": 6004,
      "process_name": "python.exe",
      "command_line": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe D:\\honghee\\blog_api\\shorts_ai_api.py",
      "executable_path": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe",
      "process_exists": true,
      "manager_owned": true,
      "owner_label": "Manager",
      "started_at": "2026-09-29 23:29:06",
      "managed": true
    },
    {
      "key": "realestate_content_api",
      "name": "부동산 콘텐츠 API",
      "script": "D:\\honghee\\blog_api\\realestate_api.py",
      "port": 9100,
      "port_ok": true,
      "port_ms": 16,
      "health_url": "http://127.0.0.1:9100/health",
      "health_ok": true,
      "health_ms": 16,
      "health_note": "200",
      "auto_start": true,
      "pid": 7752,
      "manager_pid": 7752,
      "port_pid": 7752,
      "process_name": "python.exe",
      "command_line": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe D:\\honghee\\blog_api\\realestate_api.py",
      "executable_path": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe",
      "process_exists": true,
      "manager_owned": true,
      "owner_label": "Manager",
      "started_at": "2026-09-29 23:29:07",
      "managed": true
    },
    {
      "key": "multi_shorts_daemon",
      "name": "웹진 숏츠 자동생성·YouTube 업로드",
      "script": "D:\\honghee\\blog_api\\jobs\\multi_shorts_daemon.py",
      "port": 9300,
      "port_ok": true,
      "port_ms": 23,
      "health_url": "http://127.0.0.1:9300/",
      "health_ok": true,
      "health_ms": 0,
      "health_note": "200",
      "auto_start": true,
      "pid": 10904,
      "manager_pid": null,
      "port_pid": 10904,
      "process_name": "python.exe",
      "command_line": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe D:\\honghee\\blog_api\\jobs\\multi_shorts_daemon.py",
      "executable_path": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe",
      "process_exists": true,
      "manager_owned": false,
      "owner_label": "External",
      "started_at": "",
      "managed": true
    }
  ],
  "external_ports": [
    {
      "key": "apache",
      "name": "Apache 웹서버",
      "host": "127.0.0.1",
      "port": 80,
      "protocol": "http",
      "port_ok": true,
      "port_ms": 14,
      "health_ok": true,
      "health_ms": 28,
      "health_note": "200",
      "managed": false
    },
    {
      "key": "filezilla",
      "name": "FileZilla FTP",
      "host": "127.0.0.1",
      "port": 21,
      "protocol": "tcp",
      "port_ok": true,
      "port_ms": 17,
      "health_ok": true,
      "health_ms": 17,
      "health_note": "",
      "managed": false
    },
    {
      "key": "server_manager",
      "name": "Server Manager 상황판",
      "host": "127.0.0.1",
      "port": 9200,
      "protocol": "http",
      "port_ok": true,
      "port_ms": 0,
      "health_ok": true,
      "health_ms": 0,
      "health_note": "self",
      "managed": false
    }
  ],
  "job": {
    "running": false,
    "pid": null,
    "source": "db_stale",
    "run_id": 2459,
    "run_type": "check_removed_articles",
    "label": "DB stale: check_removed_articles",
    "detail": "run_id 2459 / 16224분 / 실제 프로세스 없음",
    "command_line": ""
  },
  "scheduler": {
    "last_tick": "2026-10-02 16:19:47",
    "next_runs": [
      {
        "key": "day_pipeline",
        "name": "수집/상세/초안/비공개대기 18:05~09:55",
        "times": [
          "18:05"
        ],
        "next_run": "2026-10-02 18:05:00",
        "max_run_minutes": 950,
        "kind": "collect_draft",
        "steps": 1,
        "cmd_preview": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe jobs\\daily_pipeline_runner.py --draft-buffer 1 --replenish-count 1 --fast-max-pages 5 --end-hour 9 --end-minute 55"
      },
      {
        "key": "night_private",
        "name": "비공개 처리 04:30~06:45",
        "times": [
          "04:30"
        ],
        "next_run": "2026-10-03 04:30:00",
        "max_run_minutes": 135,
        "kind": "unknown",
        "steps": 1,
        "cmd_preview": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe workers\\private_queue_worker.py --limit-realtors 1000 --per-realtor-limit 20 --headless 1"
      },
      {
        "key": "webzine_round_1",
        "name": "웹진 1회차 + 서버 발행 10:00~12:20",
        "times": [
          "10:00"
        ],
        "next_run": "2026-10-03 10:00:00",
        "max_run_minutes": 150,
        "kind": "server_publish",
        "steps": 2,
        "cmd_preview": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe -B jobs\\multi_webzine_safe_step.py"
      },
      {
        "key": "webzine_round_2",
        "name": "웹진 2회차 + 서버 발행 12:30~15:20",
        "times": [
          "12:30"
        ],
        "next_run": "2026-10-03 12:30:00",
        "max_run_minutes": 170,
        "kind": "server_publish",
        "steps": 2,
        "cmd_preview": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe -B jobs\\multi_webzine_safe_step.py"
      },
      {
        "key": "webzine_round_3",
        "name": "웹진 3회차 + 서버 발행 15:30~18:00",
        "times": [
          "15:30"
        ],
        "next_run": "2026-10-03 15:30:00",
        "max_run_minutes": 150,
        "kind": "server_publish",
        "steps": 2,
        "cmd_preview": "C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe -B jobs\\multi_webzine_safe_step.py"
      }
    ],
    "last_started": {
      "night_private": "2026-10-02 04:30 night_private",
      "webzine_round_1": "2026-10-02 10:00 webzine_round_1",
      "webzine_round_2": "2026-10-02 12:30 webzine_round_2",
      "webzine_round_3": "2026-10-02 15:30 webzine_round_3",
      "day_pipeline": "2026-10-01 18:05 day_pipeline"
    },
    "last_skipped": ""
  },
  "events": [
    {
      "time": "2026-10-02 15:38:15",
      "level": "info",
      "message": "작업 완료: 웹진 3회차 + 서버 발행 15:30~18:00 (webzine_round_3)"
    },
    {
      "time": "2026-10-02 15:38:15",
      "level": "error",
      "message": "[webzine_round_3] 서버 발행 no-op 의심: 시작 전 pending=17, 종료 후 pending=17, elapsed=488s. publish_worker 옵션/대상조건 확인 필요"
    },
    {
      "time": "2026-10-02 15:38:15",
      "level": "info",
      "message": "[webzine_round_3] 서버 발행 3회차 15:30~18:00 완료"
    },
    {
      "time": "2026-10-02 15:38:15",
      "level": "info",
      "message": "[webzine_round_3] CMD: C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe workers\\publish_worker.py --limit 1000 --sleep 30 --until-time 18:00 --smart-sleep --per-realtor-daily-limit 1"
    },
    {
      "time": "2026-10-02 15:38:15",
      "level": "info",
      "message": "[webzine_round_3] 2/2 서버 발행 3회차 15:30~18:00 시작"
    },
    {
      "time": "2026-10-02 15:38:15",
      "level": "info",
      "message": "[webzine_round_3] 웹진 전체 중개사 최신 매물 최대 20건 완료"
    },
    {
      "time": "2026-10-02 15:30:07",
      "level": "info",
      "message": "[webzine_round_3] CMD: C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe -B jobs\\multi_webzine_safe_step.py"
    },
    {
      "time": "2026-10-02 15:30:07",
      "level": "info",
      "message": "[webzine_round_3] 1/2 웹진 전체 중개사 최신 매물 최대 20건 시작"
    },
    {
      "time": "2026-10-02 15:30:07",
      "level": "info",
      "message": "[webzine_round_3] 서버 발행 시작 전 pending=17 / realtor=5"
    },
    {
      "time": "2026-10-02 15:30:07",
      "level": "info",
      "message": "작업 시작: 웹진 3회차 + 서버 발행 15:30~18:00 (webzine_round_3)"
    },
    {
      "time": "2026-10-02 15:30:07",
      "level": "info",
      "message": "[SCHEDULER RUN] 웹진 3회차 + 서버 발행 15:30~18:00 예약시간=15:30"
    },
    {
      "time": "2026-10-02 15:29:54",
      "level": "info",
      "message": "[노출검사] 대상=1, ON=0, 미발견=1, 오류=0"
    },
    {
      "time": "2026-10-02 14:29:54",
      "level": "info",
      "message": "[노출검사] 대상=2, ON=1, 미발견=1, 오류=0"
    },
    {
      "time": "2026-10-02 13:29:54",
      "level": "info",
      "message": "[노출검사] 대상=2, ON=0, 미발견=2, 오류=0"
    },
    {
      "time": "2026-10-02 12:39:28",
      "level": "info",
      "message": "작업 완료: 웹진 2회차 + 서버 발행 12:30~15:20 (webzine_round_2)"
    },
    {
      "time": "2026-10-02 12:39:28",
      "level": "error",
      "message": "[webzine_round_2] 서버 발행 no-op 의심: 시작 전 pending=17, 종료 후 pending=17, elapsed=560s. publish_worker 옵션/대상조건 확인 필요"
    },
    {
      "time": "2026-10-02 12:39:28",
      "level": "info",
      "message": "[webzine_round_2] 서버 발행 2회차 12:30~15:20 완료"
    },
    {
      "time": "2026-10-02 12:39:27",
      "level": "info",
      "message": "[webzine_round_2] CMD: C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe workers\\publish_worker.py --limit 1000 --sleep 30 --until-time 15:20 --smart-sleep --per-realtor-daily-limit 1"
    },
    {
      "time": "2026-10-02 12:39:27",
      "level": "info",
      "message": "[webzine_round_2] 2/2 서버 발행 2회차 12:30~15:20 시작"
    },
    {
      "time": "2026-10-02 12:39:27",
      "level": "info",
      "message": "[webzine_round_2] 웹진 전체 중개사 최신 매물 최대 20건 완료"
    },
    {
      "time": "2026-10-02 12:30:07",
      "level": "info",
      "message": "[webzine_round_2] CMD: C:\\Users\\owner\\AppData\\Local\\Programs\\Python\\Python313\\python.exe -B jobs\\multi_webzine_safe_step.py"
    },
    {
      "time": "2026-10-02 12:30:07",
      "level": "info",
      "message": "[webzine_round_2] 1/2 웹진 전체 중개사 최신 매물 최대 20건 시작"
    },
    {
      "time": "2026-10-02 12:30:07",
      "level": "info",
      "message": "[webzine_round_2] 서버 발행 시작 전 pending=17 / realtor=5"
    },
    {
      "time": "2026-10-02 12:30:07",
      "level": "info",
      "message": "작업 시작: 웹진 2회차 + 서버 발행 12:30~15:20 (webzine_round_2)"
    },
    {
      "time": "2026-10-02 12:30:07",
      "level": "info",
      "message": "[SCHEDULER RUN] 웹진 2회차 + 서버 발행 12:30~15:20 예약시간=12:30"
    },
    {
      "time": "2026-10-02 12:29:53",
      "level": "info",
      "message": "[노출검사] 대상=16, ON=2, 미발견=14, 오류=0"
    },
    {
      "time": "2026-10-02 11:32:21",
      "level": "info",
      "message": "작업 완료: 웹진 1회차 + 서버 발행 10:00~12:20 (webzine_round_1)"
    },
    {
      "time": "2026-10-02 11:32:21",
      "level": "info",
      "message": "[webzine_round_1] 서버 발행 큐 변화: pending 20 → 17, elapsed=5535s"
    },
    {
      "time": "2026-10-02 11:32:21",
      "level": "info",
      "message": "[webzine_round_1] 서버 발행 1회차 10:00~12:20 완료"
    },
    {
      "time": "2026-10-02 11:29:51",
      "level": "info",
      "message": "[노출검사] 대상=20, ON=2, 미발견=18, 오류=0"
    }
  ]
}