Get/View Memory & CPU usage via NodeJS

后端 未结 4 1706
猫巷女王i
猫巷女王i 2020-12-13 03:34

I see there are several node packages that allow you to look up a specific process\'s usage, such as https://www.npmjs.com/package/usage

I am trying to get the overa

4条回答
  •  天命终不由人
    2020-12-13 04:14

    Of course it is possible. But you'll need a C++ native module to do that. And keep in mind that every OS has their own way of querying system resource usage.

    For example, if you're on Windows (which might be what you're looking for since usage doesn't support Windows), you could do something like

    performance.cpp

    #include 
    #include "performance_algorithm.hpp"
    
    using namespace v8;
    
    void InitAll(Handle exports) {
        PerformanceAlgorithm::Initialize();
        PerformanceAlgorithm::RegisterMethod(exports);
    }
    
    NODE_MODULE(Performance, InitAll)
    
    
    

    performance_algorithm.cpp

    #include 
    
    #include "baton.hpp"
    #include "structs.hpp"
    #include "performance_algorithm.hpp"
    
    void PerformanceAlgorithm::Initialize() {
        PdhOpenQuery(NULL, NULL, &cpuQuery);
        PdhAddCounter(cpuQuery, "\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
        PdhCollectQueryData(cpuQuery);
    }
    
    void PerformanceAlgorithm::RegisterMethod(Handle exports) {
        NODE_SET_METHOD(exports, "getPerformanceData", PerformanceAlgorithm::GetPerformanceDataAsync);
    }
    
    void PerformanceAlgorithm::GetPerformanceDataAsync(const FunctionCallbackInfo& args) {
        Isolate* isolate = Isolate::GetCurrent();
        HandleScope scope(isolate);
    
        if (args.Length() != 1) {
            isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
        } else {
            if (!args[0]->IsFunction()) {
                isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong arguments type")));
            } else {
                Local callbackFunction = Local::Cast(args[0]);
    
                Baton* baton = new Baton();
                baton->request.data = baton;
                baton->callbackFunction.Reset(isolate, callbackFunction);
    
                uv_queue_work(uv_default_loop(), &baton->request, PerformanceAlgorithm::GetPerformanceDataWork, PerformanceAlgorithm::GetPerformanceDataAsyncAfter);
            }
        }
    }
    
    void PerformanceAlgorithm::GetPerformanceDataWork(uv_work_t* request) {
        Baton* baton = static_cast*>(request->data);
    
        baton->result.memory_info.dwLength = sizeof(MEMORYSTATUSEX);
        GlobalMemoryStatusEx(&baton->result.memory_info);
    
        PDH_FMT_COUNTERVALUE counterVal;
        PdhCollectQueryData(cpuQuery);
        PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
        baton->result.cpu_usage = counterVal.doubleValue;
    
        DWORD processIDs[1024], bytesReturned;
        EnumProcesses(processIDs, sizeof(processIDs), &bytesReturned);
    
        DWORD numberOfProcesses = bytesReturned / sizeof(DWORD);
        for (int i = 0; i < numberOfProcesses; i++) {
            HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]);
    
            HMODULE hMods[1024];
            DWORD cbNeeded;
            if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
                for (int j = 0; j < (cbNeeded / sizeof(HMODULE)); j++) {
                    TCHAR szModName[MAX_PATH];
                    GetModuleFileNameEx(hProcess, hMods[j], szModName, sizeof(szModName) / sizeof(TCHAR));
    
                    ProcessInfo info;
                    info.process_id = processIDs[i];
                    info.path = string(szModName);
    
                    baton->result.processes.push_back(info);
    
                    break;
                }
            }
    
            CloseHandle(hProcess);
        }
    
        sort(baton->result.processes.begin(), baton->result.processes.end(), [](ProcessInfo a, ProcessInfo b) -> bool {
            return a.process_id < b.process_id;
        });
    
        GetPerformanceInfo(&baton->result.performance_info, sizeof(PERFORMACE_INFORMATION));
    }
    
    void PerformanceAlgorithm::GetPerformanceDataAsyncAfter(uv_work_t* request, int status) {
        Isolate* isolate = Isolate::GetCurrent();
        HandleScope scope(isolate);
        EscapableHandleScope escapableHandleScope(isolate);
    
        Baton* baton = static_cast*>(request->data);
        Local callbackFunction = Local::New(isolate, baton->callbackFunction);
    
        Local returnValue = Object::New(isolate);
        returnValue->Set(String::NewFromUtf8(isolate, "cpu_usage"), Number::New(isolate, baton->result.cpu_usage));
        returnValue->Set(String::NewFromUtf8(isolate, "ram_usage"), Number::New(isolate, baton->result.memory_info.dwMemoryLoad));
        returnValue->Set(String::NewFromUtf8(isolate, "total_physical_memory"), Number::New(isolate, baton->result.memory_info.ullTotalPhys));
        returnValue->Set(String::NewFromUtf8(isolate, "available_physical_memory"), Number::New(isolate, baton->result.memory_info.ullAvailPhys));
        returnValue->Set(String::NewFromUtf8(isolate, "total_page_file"), Number::New(isolate, baton->result.memory_info.ullTotalPageFile));
        returnValue->Set(String::NewFromUtf8(isolate, "available_page_file"), Number::New(isolate, baton->result.memory_info.ullAvailPageFile));
        returnValue->Set(String::NewFromUtf8(isolate, "total_virtual"), Number::New(isolate, baton->result.memory_info.ullTotalVirtual));
        returnValue->Set(String::NewFromUtf8(isolate, "available_virtual"), Number::New(isolate, baton->result.memory_info.ullAvailVirtual));
    
        Local processes = Array::New(isolate, baton->result.processes.size());
        for (int i = 0; i < baton->result.processes.size(); i++) {
            Local processInfo = Object::New(isolate);
            processInfo->Set(String::NewFromUtf8(isolate, "process_id"), Number::New(isolate, baton->result.processes[i].process_id));
            processInfo->Set(String::NewFromUtf8(isolate, "path"), String::NewFromUtf8(isolate, baton->result.processes[i].path.c_str()));
    
            processes->Set(i, processInfo);
        }
        returnValue->Set(String::NewFromUtf8(isolate, "running_processes"), processes);
    
        const unsigned int argc = 1;
        Handle argv[argc] = { escapableHandleScope.Escape(returnValue) };
        callbackFunction->Call(isolate->GetCurrentContext()->Global(), argc, argv);
    
        baton->callbackFunction.Reset();
        delete baton;
    }
    
        

    提交回复
    热议问题