Skip to main content
When a Windows Curator server hits 100% CPU, the spike is usually over before anyone can look at the server. Windows keeps no CPU history on its own. The only way to explain a spike after the fact is to line up the records the server does keep: the Apache access and error logs, the PHP and Curator logs, the Windows event logs, the Task Scheduler history, and any Performance Monitor logs. The CPU investigation script lines those records up for you. It reads each source and builds one timeline in 5-minute buckets. The report names the busiest periods, lists what else was happening at the same time, and ranks the configuration problems it found by severity. Two more modes capture the next spike as it happens.
The script is for self-hosted Curator installations on Windows Server that use the bundled Apache web server. It reads the server; it does not change anything unless you ask it to register a Performance Monitor collector. Nothing is uploaded anywhere. The report is written to the Desktop for you to review and send to the Curator support team.

Requirements

  • Windows Server 2016, 2019 or 2022 with Windows PowerShell 5.1 (installed by default).
  • A PowerShell session started with Run as administrator. Without it, the Task Scheduler history, some event logs and the Windows Defender settings cannot be read, and the report says so in its “Collection problems” section.
  • Enough time: the first run reads every access log in the window. A busy server with 14 days of logs takes a few minutes.

Step 1: Run the historical analysis

Open an elevated PowerShell window on the Curator server and run:
The script finds the Curator installation on its own (any drive, any folder name), reads the Apache configuration to learn where the access logs are and what format they use, and then works through each source. Progress prints to the console as it goes. When it finishes, two files are on the Desktop of the account that ran it: Use -OutputDir to write the files somewhere other than the Desktop.

Step 2: Read the report

The report opens with a Findings block, ranked HIGH, MEDIUM, LOW and INFO. HIGH findings are known CPU sinks on Windows Curator servers and are worth fixing whether or not they explain the spikes. The most common ones are:
  • OPcache is not enabled. Without it, every request compiles Curator’s PHP from source again. Apply the recommended OPcache settings and restart Apache.
  • Windows Defender is scanning the Curator folder. Real-time scanning of every PHP file, cache file and database page write shows up as MsMpEng.exe using the CPU and Apache looking slow. Exclude the Curator folder and the httpd.exe, php.exe and mariadbd.exe processes.
  • Scheduled task runs are taking longer than a minute. Curator’s scheduled task runs artisan schedule:run every minute and is meant to finish well inside that. Long runs mean a scheduled job (an export, a cache warm, a Tableau sync) is doing heavy work in the foreground, and the report lists the longest runs so you can line them up with the spikes.
  • Monitoring or bot traffic is a large share of requests. A health check that hits a Curator page instead of a static file runs the full application on every poll.
Below the findings, the Busiest periods section lists the buckets with the most dynamic (PHP) requests, ranked by how far above the average they are. Each bucket shows the sites, top paths and top client addresses that made up the traffic, plus every event, error and task run that happened within a few minutes of it. Compare the times you were told about with this list:
  • If the reported spike times line up with a traffic peak, the CPU is going to users. Look at the top paths and clients in that bucket, and at the findings that make each request cheaper.
  • If they do not line up with traffic, the CPU is going to background work. Look at the task runs, Defender scans, Windows Update installs and errors listed next to the nearest buckets.
The CPU history section is empty on a first run unless the server already had Performance Monitor logs, because Windows records no CPU history by default. The next step fixes that.
The report also lists any source the script could not read in full under Collection problems. An empty section for one of those sources means “could not look”, not “nothing happened”. Re-run from an elevated PowerShell if the list mentions access or permissions.

Step 3: Capture the next spike

Register a lightweight Performance Monitor collector so the next spike is recorded with per-process CPU:
The collector samples total CPU and the CPU of httpd.exe, php.exe, mariadbd.exe, MsMpEng.exe and a few other processes every 15 seconds into a 512 MB circular file under C:\PerfLogs\Curator. A scheduled task restarts it after a reboot. The overhead is negligible. After the next spike, run Step 1 again. The report will now include a CPU history section with the highest CPU buckets, the top process in each, and a correlation figure between traffic and CPU that says whether the spikes come from users or from background work. When the investigation is over, remove the collector:
The recorded .blg files are left in place so they can still be analyzed.

Step 4: Watch a spike live

If a spike is happening now, or is expected at a known time, sample the server live:
The script samples CPU every 5 seconds and prints the top processes each time. Whenever total CPU crosses the threshold, it records a snapshot: the top processes, the command lines of the php.exe processes (which shows which artisan command is running), the number of open web connections, and the queries MariaDB is executing. Press Ctrl+C to stop early. The report and a CSV of every sample are written to the Desktop either way.

Parameters

What the report contains

The report is internal material. It contains hostnames, file paths, client IP addresses and request paths from the access logs, and messages from the error logs. A -Watch snapshot adds process command lines and the shape of the running database queries. Before the script writes any of those, it strips query strings from URLs, replaces credential-looking values, and replaces the literal values in SQL statements with placeholders. The database credentials in each site’s .env file are used only to run read-only status queries. The password is never written to the report, the console or a command line.

Send the report for analysis

Email the report and the CSV to the Curator support team, together with the files described in Performance Diagnostics, and say which spike times you were told about. The support team will read the timeline against those times and recommend specific changes.

Troubleshooting

  • “No Apache access logs were found.” The access log is declared by a CustomLog line in curator.conf or httpd.conf. If logging was turned off, turn it back on and re-run after a day of traffic.
  • “Task Scheduler history is disabled on this server.” Open Task Scheduler and choose Enable All Tasks History in the Actions pane, or run wevtutil sl Microsoft-Windows-TaskScheduler/Operational /e:true from an elevated prompt. The next run can then measure how long each schedule:run takes.
  • “The access log format has no request duration field.” Adding %D to the LogFormat line in curator.conf lets the next run report how long each request took, which separates slow pages from busy ones. Restart Apache after the change.
  • The CPU history section is empty. Windows keeps no CPU history unless a collector is running. Follow Step 3 and re-run after the next spike.