diff --git a/server/python/plugin_remote.py b/server/python/plugin_remote.py index b884f637f..fe8e9e812 100644 --- a/server/python/plugin_remote.py +++ b/server/python/plugin_remote.py @@ -547,8 +547,6 @@ class PluginRemote: self.nativeIds: Mapping[str, DeviceStorage] = {} self.mediaManager: MediaManager self.consoles: Mapping[str, Future[Tuple[StreamReader, StreamWriter]]] = {} - self.ptimeSum = 0 - self.allMemoryStats = {} self.peer = clusterSetup.peer self.clusterSetup = clusterSetup self.api = api @@ -755,8 +753,6 @@ class PluginRemote: self.deviceManager = DeviceManager(self.nativeIds, self.systemManager) self.mediaManager = MediaManager(await self.api.getMediaManager()) - await self.start_stats_runner(zipAPI.updateStats) - try: from scrypted_sdk import sdk_init2 # type: ignore @@ -801,7 +797,6 @@ class PluginRemote: # traceback.print_exc() print("fork read loop exited") finally: - self.allMemoryStats.pop(forkPeer) parent_conn.close() rpcTransport.executor.shutdown() pluginFork.worker.kill() @@ -819,10 +814,7 @@ class PluginRemote: forkOptions["debug"] = debug class PluginZipAPI: - async def updateStats(stats): - self.ptimeSum += stats["cpu"]["user"] - self.allMemoryStats[forkPeer] = stats - + async def getZip(self): return await zipAPI.getZip() @@ -918,39 +910,6 @@ class PluginRemote: return [self.replPort, os.getenv("SCRYPTED_CLUSTER_ADDRESS", None)] raise Exception(f"unknown service {name}") - async def start_stats_runner(self, update_stats): - def stats_runner(): - ptime = round(time.process_time() * 1000000) + self.ptimeSum - try: - import psutil - - process = psutil.Process(os.getpid()) - heapTotal = process.memory_info().rss - except: - try: - import resource - - heapTotal = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss - except: - heapTotal = 0 - - for _, stats in self.allMemoryStats.items(): - heapTotal += stats["memoryUsage"]["heapTotal"] - - stats = { - "cpu": { - "user": ptime, - "system": 0, - }, - "memoryUsage": { - "heapTotal": heapTotal, - }, - } - asyncio.run_coroutine_threadsafe(update_stats(stats), self.loop) - self.loop.call_later(10, stats_runner) - - stats_runner() - async def plugin_async_main( loop: AbstractEventLoop, rpcTransport: rpc_reader.RpcTransport diff --git a/server/src/plugin/plugin-api.ts b/server/src/plugin/plugin-api.ts index 998eb2fd1..b95a0e453 100644 --- a/server/src/plugin/plugin-api.ts +++ b/server/src/plugin/plugin-api.ts @@ -1,6 +1,5 @@ import type { Device, DeviceManifest, EventDetails, EventListenerOptions, EventListenerRegister, MediaManager, MediaObject, ScryptedDevice, ScryptedInterfaceDescriptor, ScryptedInterfaceProperty, ScryptedNativeId, SystemDeviceState } from '@scrypted/types'; import type { AccessControls } from './acl'; -import type { PluginStats } from './plugin-remote-stats'; export interface PluginLogger { log(level: string, message: string): Promise; @@ -170,8 +169,8 @@ export interface PluginRemoteLoadZipOptions { export class PluginZipAPI { constructor( - public getZip: () => Promise, - public updateStats: (stats: PluginStats) => Promise) { + public getZip: () => Promise + ) { } } diff --git a/server/src/plugin/plugin-host.ts b/server/src/plugin/plugin-host.ts index f87952448..5d843d0cb 100644 --- a/server/src/plugin/plugin-host.ts +++ b/server/src/plugin/plugin-host.ts @@ -4,13 +4,13 @@ import * as io from 'engine.io'; import fs from 'fs'; import os from 'os'; import WebSocket from 'ws'; +import { setupCluster } from '../cluster/cluster-setup'; import { Plugin } from '../db-types'; import { IOServer, IOServerSocket } from '../io'; import { Logger } from '../logger'; import { RpcPeer, RPCResultError } from '../rpc'; import { createRpcSerializer } from '../rpc-serializer'; import { ScryptedRuntime } from '../runtime'; -import { setupCluster } from '../cluster/cluster-setup'; import { sleep } from '../sleep'; import { AccessControls } from './acl'; import { MediaManagerHostImpl } from './media'; @@ -20,7 +20,6 @@ import { PluginDebug } from './plugin-debug'; import { PluginHostAPI } from './plugin-host-api'; import { LazyRemote } from './plugin-lazy-remote'; import { setupPluginRemote } from './plugin-remote'; -import { PluginStats } from './plugin-remote-stats'; import { WebSocketConnection } from './plugin-remote-websocket'; import { ensurePluginVolume, getScryptedVolume } from './plugin-volume'; import { createClusterForkWorker, needsClusterForkWorker } from './runtime/cluster-fork.worker'; @@ -60,8 +59,6 @@ export class PluginHost { api: PluginHostAPI; pluginName: string; packageJson: any; - lastStats: number; - stats: PluginStats; killed = false; consoleServer: Promise; zipHash: string; @@ -259,12 +256,7 @@ export class PluginHost { // original implementation sent the zipBuffer, sending the zipFile name now. // can switch back for non-local plugins. const modulePromise = remote.loadZip(this.packageJson, - // the plugin is expected to send process stats every 10 seconds. - // this can be used as a check for liveness. - new PluginZipAPI(async () => fs.promises.readFile(this.zipFile), async (stats: PluginStats) => { - this.lastStats = Date.now(); - this.stats = stats; - }), + new PluginZipAPI(async () => fs.promises.readFile(this.zipFile)), loadZipOptions); // allow garbage collection of the zip buffer const module = await modulePromise; @@ -414,7 +406,7 @@ export class PluginHost { const now = Date.now(); // plugin may take a while to install, so wait 10 minutes. // after that, require 1 minute checkins. - if (!this.lastStats || !lastPong) { + if (!lastPong) { if (now - startupTime > 10 * 60 * 1000) { const logger = await this.api.getLogger(undefined); logger.log('e', 'plugin failed to start in a timely manner. restarting.'); @@ -422,11 +414,6 @@ export class PluginHost { } return; } - if (!pluginDebug && (this.lastStats + 60000 < now)) { - const logger = await this.api.getLogger(undefined); - logger.log('e', 'plugin is not reporting stats. restarting.'); - this.api.requestRestart(); - } if (!pluginDebug && (lastPong + 60000 < now)) { const logger = await this.api.getLogger(undefined); logger.log('e', 'plugin is not responding to ping. restarting.'); diff --git a/server/src/plugin/plugin-remote-stats.ts b/server/src/plugin/plugin-remote-stats.ts deleted file mode 100644 index fa7269771..000000000 --- a/server/src/plugin/plugin-remote-stats.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { RuntimeWorker } from "./runtime/runtime-worker"; - -export interface PluginStats { - type: 'stats', - cpuUsage: NodeJS.CpuUsage; - memoryUsage: NodeJS.MemoryUsage; -} - -export function startStatsUpdater(allMemoryStats: Map, updateStats: (stats: PluginStats) => Promise) { - if (!updateStats) - console.warn('wtf') - setInterval(() => { - let cpuUsage: NodeJS.CpuUsage; - let memoryUsage: NodeJS.MemoryUsage; - if (process.cpuUsage) - cpuUsage = process.cpuUsage(); - - allMemoryStats.set(undefined, process.memoryUsage()); - - memoryUsage = { - rss: 0, - heapTotal: 0, - heapUsed: 0, - external: 0, - arrayBuffers: 0, - } - - for (const mu of allMemoryStats.values()) { - if (!mu) - continue; - memoryUsage.rss += mu.rss; - memoryUsage.heapTotal += mu.heapTotal; - memoryUsage.heapUsed += mu.heapUsed; - memoryUsage.external += mu.external; - memoryUsage.arrayBuffers += mu.arrayBuffers; - } - - updateStats({ - type: 'stats', - cpuUsage, - memoryUsage, - }).catch(() => {}); - }, 10000); -} diff --git a/server/src/plugin/plugin-remote-worker.ts b/server/src/plugin/plugin-remote-worker.ts index c259eabfe..1b78297d5 100644 --- a/server/src/plugin/plugin-remote-worker.ts +++ b/server/src/plugin/plugin-remote-worker.ts @@ -12,7 +12,6 @@ import { PluginAPI, PluginAPIProxy, PluginRemote, PluginRemoteLoadZipOptions, Pl import { pipeWorkerConsole, prepareConsoles } from './plugin-console'; import { getPluginNodePath, installOptionalDependencies } from './plugin-npm-dependencies'; import { attachPluginRemote, DeviceManagerImpl, setupPluginRemote } from './plugin-remote'; -import { PluginStats, startStatsUpdater } from './plugin-remote-stats'; import { createREPLServer } from './plugin-repl'; import { getPluginVolume } from './plugin-volume'; import { ChildProcessWorker } from './runtime/child-process-worker'; @@ -196,12 +195,6 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe await installOptionalDependencies(getPluginConsole(), packageJson); - // process.cpuUsage is for the entire process. - // process.memoryUsage is per thread. - const allMemoryStats = new Map(); - // start the stats updater/watchdog after installation has finished, as that may take some time. - startStatsUpdater(allMemoryStats, zipAPI.updateStats); - peer.params.ping = async (time: number, pong: (time: number) => Promise) => { await pong(time); }; @@ -315,13 +308,11 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe threadPeer.kill('worker exited'); forkApi.removeListeners(); forks.delete(remote); - allMemoryStats.delete(runtimeWorker); }); runtimeWorker.on('error', e => { threadPeer.kill('worker error ' + e); forkApi.removeListeners(); forks.delete(remote); - allMemoryStats.delete(runtimeWorker); }); for (const [nativeId, dmd] of deviceManager.nativeIds.entries()) { @@ -331,9 +322,7 @@ export function startPluginRemote(mainFilename: string, pluginId: string, peerSe const forkOptions = Object.assign({}, zipOptions); forkOptions.fork = true; forkOptions.main = options?.filename; - const forkZipAPI = new PluginZipAPI(() => zipAPI.getZip(), async (stats: PluginStats) => { - allMemoryStats.set(runtimeWorker, stats.memoryUsage); - }); + const forkZipAPI = new PluginZipAPI(() => zipAPI.getZip()); return remote.loadZip(packageJson, forkZipAPI, forkOptions) })(); diff --git a/server/src/services/plugin.ts b/server/src/services/plugin.ts index 6fe5b2851..db3e3236f 100644 --- a/server/src/services/plugin.ts +++ b/server/src/services/plugin.ts @@ -115,7 +115,6 @@ export class PluginComponent { return { pid: host?.worker?.pid, clientsCount: host?.io?.clientsCount, - stats: host?.stats, rpcObjects, packageJson, pendingResults,