Log CPU usage
Last modification: Thursday, April 30, 2009 06:04 pmMeant to be run as a Stay Open AppleScript Application this script will sample the CPU usage and write the results to a log file.
Implementation
property pSAMPLE_INTERVAL : 5 -- Interval between samples in secondsproperty pLOG_FILE_PATH : (path to home folder from user domain as string) & "Library:Logs:cpu_history.log"
global gFIRST_RUN
global gOUTPUT_PARSEABLE
on run
set gFIRST_RUN to true
main()
end run
on idle
main()
return pSAMPLE_INTERVAL
end idle
on main()
try
-- Sample with the top command three times and get the values of the last one
try
set _values to words of paragraph -1 of (do shell script "top -l 3 | grep 'CPU usage'")
set _timeStamp to timeStamp(current date, 1)
on error _eMsg number _eNum
error "Sampling failed. " & _eMsg number _eNum
end try
-- Convert the values from the sample
copy parseValues(_values) to {_loadAverage, _userCPU, _sysCPU, _allCPU, _allCPUInt}
-- Format the values
set _logMessage to _timeStamp & " " & ¬
paddedString(_loadAverage as string, " ", 5) & " " & ¬
paddedString((_userCPU as string) & "%", " ", 7) & " " & ¬
paddedString((_sysCPU as string) & "%", " ", 7) & " " & ¬
paddedString((_allCPU as string) & "%", " ", 7) & " [" & ¬
paddedString("|", "-", _allCPUInt - 1) & paddedString("]", "-", 51 - _allCPUInt)
set _logMessage to searchAndReplace(_logMessage, ",", ".")
-- Write values to file
logMessage(_logMessage, false)
on error _eMsg number _eNum
logMessage(_eMsg & " (" & (_eNum as string) & ")", true)
if _eNum is 70000 then quit
end try
end main
on logMessage(_message, _addTimeStamp)
try
if _addTimeStamp then
try
set _message to timeStamp(current date, 1) & " " & _message
end try
end if
set _message to quoted form of _message
do shell script "echo " & _message & " >> " & quoted form of (POSIX path of (pLOG_FILE_PATH))
end try
end logMessage
on parseValues(_values)
try
-- Check the output of the top command on first run
if gFIRST_RUN then
set gFIRST_RUN to false
if (count of _values) is not 13 then error "Count of values should be 13, but is " & ((count of values) as string) & "."
if item 6 of _values is not "CPU" then "Value 6 should be \"CPU\", but is \"" & (item 6 of _values) & "\"."
if item 9 of _values is not "user" then "Value 9 should be \"CPU\", but is \"" & (item 9 of _values) & "\"."
if item 11 of _values is not "sys" then "Value 11 should be \"CPU\", but is \"" & (item 11 of _values) & "\"."
end if
-- Parse the sampled values
set _loadAverage to item 3 of _values as string
try
set _userCPU to item 8 of _values as real
on error
-- Strings like "12.3" cannot be converted to real numbers
-- on systems with German number formats
set _userCPU to (searchAndReplace(item 8 of _values, ".", ",")) as real
end try
try
set _sysCPU to item 10 of _values as real
on error
-- Strings like "12.3" cannot be converted to real numbers
-- on systems with German number formats
set _sysCPU to (searchAndReplace(item 10 of _values, ".", ",")) as real
end try
set _allCPU to _userCPU + _sysCPU
set _allCPUInt to (_allCPU / 2) as integer
return {_loadAverage, _userCPU, _sysCPU, _allCPU, _allCPUInt}
on error _eMsg number _eNum
error "Could not parse output. " & _eMsg & " (" & (_eNum as string) & ")" number 70000
end try
end parseValues
on paddedString(_string, _padding, _length)
repeat _length - (count of _string) times
set _string to _padding & _string
end repeat
return _string
end paddedString
on timeStamp(_date, _format)
set _month to month of _date as integer
set _day to day of _date
set _year to year of _date as string
set _time to (time of _date)
set _hour to _time div 60 div 60
set _minute to (_time div 60) - (_hour * 60)
set _second to _time - (_minute * 60) - (_hour * 60 * 60)
if _month is less than 10 then set _month to "0" & _month
if _day is less than 10 then set _day to "0" & _day
set _yearShort to characters -2 thru -1 of _year
if _hour is less than 10 then set _hour to "0" & _hour
if _minute is less than 10 then set _minute to "0" & _minute
if _second is less than 10 then set _second to "0" & _second
if _format is 1 then
return ((_year & "-" & _month & "-" & _day & " " & _hour & ":" & _minute & ":" & _second) as string)
else if _format is 2 then
return ((_year & "-" & _month & "-" & _day & "_" & _hour & "-" & _minute & "-" & _second) as string)
else
return ""
end if
end timeStamp
on searchAndReplace(_string, _search, _replace)
if _string does not contain _search then return _string
set _prvDlmt to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to _search
set _stringItems to text items of _string
set AppleScript's text item delimiters to _replace
set _string to _stringItems as string
end try
set AppleScript's text item delimiters to _prvDlmt
return _string
end searchAndReplace