An Observable that wraps/decorates Electron's ipc
facilitating modules and emits meta data "marks" whenever a message is sent or received.
In some ways, this is just a glorified wrapper around Observable.create()
for IPC.
// import will detect which process you're on and wrap the appropriate ipc module
import ipcMonitor from "ipc-monitor";
// on subscribe, the ipc will get wrapped and this will emit meta data (this is a global side effect)
const subscription = ipcMonitor.subscribe((mark) => {
if (mark.type === "outgoing") {
console.log(`Message Sent @ ${mark.time}`);
} else if (mark.type === "incoming") {
console.log(`Message Received @ ${mark.time}`);
}
});
// later on... unsubscribing from the monitor will restore the ipc module to its original form
subscription.unsubscribe();
Note: this module performs a side-effect by decorating the
send
andemit
methods on ipc. Original methods are restored onunsubscribe()
.
IpcMark
is the type definition for emissions from an ipcMonitor
. It is necessarily serializable JSON payload. The below tables detail which IpcMark.Module
and IpcMark.Method
are used for a given ipc message event. Messages that incur an ipc message event are either incoming or outgoing from a given process (denoted by the IpcMark.Direction
property). Incoming and Outoing messages are correlated via the IpcMark.CorrelationId
property.
Sender Process | Receiver Process | IpcMark.Module |
IpcMark.Method |
---|---|---|---|
Main | Renderer | webContents |
send |
Renderer | Main | ipcRenderer |
send , sendSync |
Renderer | Renderer | ipcRenderer |
sendTo |
Host Renderer | Embedded Renderer | webviewTag |
send |
Embedded Renderer | Host Renderer | ipcRenderer |
sendToHost |
Note: Embedded specifically refer to
<webview/>
tags here, therefore, Embedded and Host Renderer`s are a subset of more general Renderer processes.
Sender Process | Receiver Process | IpcMark.Module |
IpcMark.Method |
---|---|---|---|
Main | Renderer | ipcRenderer |
emit |
Renderer | Main | ipcMain |
emit |
Renderer | Renderer | ipcRenderer |
emit |
Host Renderer | Embedded Renderer | ipcRenderer |
emit |
Embedded Renderer | Host Renderer | ipcRenderer |
addEventListener |
This is the term used to refer to operations one can perform on an ipcMonitor
to post-process data about ipc traffic. It's just an alias for the standard RxJS operator type definition:
type IpcMetric<T> = (source: Observable<IpcMark>) => Observable<T>
There's an unpublished "sample-metrics" folder with, well, sample metrics that one can apply to their ipcMonitors. Using other libraries like rx-ipc
to merge all ipcMonitor data into a single process, you can calculate info like average message latency across all processes. E.G.
// in renderer process
import ipcRendererMonitor from "ipc-monitor";
import { proxify } from "rx-ipc";
ipcRendererMonitor.pipe(
proxify({ channel: "ipc-monitor" })
).subscribe();
// in main process
import ipcMainMonitor from "ipc-monitor";
import { averageLatency } from "ipc-monitor/sample-metrics/latency";
import { createProxy } from "rx-ipc";
import { merge } from "rxjs";
const ipcRendererMonitorProxy = createProxy({ channel: "ipc-monitor" });
const ipcMonitorGlobal = merge(ipcMainMonitor, ipcRendererMonitorProxy);
ipcMonitorGlobal.pipe(
averageLatency()
).subscribe(({ averageLatency }) => console.log(`Current Average IPC Latency: ${averageLatency}`))
- Upgrade to RxJS v6. While the above examples use RxJS v6 syntax, this library currently utilizes RxJS v5. (this is because I consume this in an app with an RxJS v5 dependency :/ )