mirror of
https://github.com/denoland/deno.git
synced 2024-12-23 15:49:44 -05:00
feat(unstable): Add "Deno.osUptime()" API (#17179)
This PR adds support for `Deno.osUptime` which reports number of seconds since os was booted. It will allow us to be compatible with Node's `os.uptime` - https://nodejs.org/api/os.html#osuptime Partially based on https://docs.rs/uptime_lib/latest/src/uptime_lib/lib.rs.html
This commit is contained in:
parent
1e857bc03c
commit
3baf1a4bd3
10 changed files with 110 additions and 1 deletions
|
@ -239,6 +239,18 @@ Deno.test({ permissions: { sys: false } }, function releasePerm() {
|
|||
}, Deno.errors.PermissionDenied);
|
||||
});
|
||||
|
||||
Deno.test({ permissions: { sys: ["osUptime"] } }, function osUptime() {
|
||||
const uptime = Deno.osUptime();
|
||||
assert(typeof uptime === "number");
|
||||
assert(uptime > 0);
|
||||
});
|
||||
|
||||
Deno.test({ permissions: { sys: false } }, function osUptimePerm() {
|
||||
assertThrows(() => {
|
||||
Deno.osUptime();
|
||||
}, Deno.errors.PermissionDenied);
|
||||
});
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { sys: ["systemMemoryInfo"] } },
|
||||
function systemMemoryInfo() {
|
||||
|
|
|
@ -22,6 +22,7 @@ Deno.test(async function permissionNetInvalidHost() {
|
|||
Deno.test(async function permissionSysValidKind() {
|
||||
await Deno.permissions.query({ name: "sys", kind: "loadavg" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "osRelease" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "osUptime" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "networkInterfaces" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "systemMemoryInfo" });
|
||||
await Deno.permissions.query({ name: "sys", kind: "hostname" });
|
||||
|
|
|
@ -46,6 +46,7 @@ const UNSTABLE_DENO_PROPS: &[&str] = &[
|
|||
"ServeInit",
|
||||
"ServeTlsInit",
|
||||
"Handler",
|
||||
"osUptime",
|
||||
];
|
||||
|
||||
static MSG_MISSING_PROPERTY_DENO: Lazy<Regex> = Lazy::new(|| {
|
||||
|
|
1
cli/tsc/dts/lib.deno.ns.d.ts
vendored
1
cli/tsc/dts/lib.deno.ns.d.ts
vendored
|
@ -4120,6 +4120,7 @@ declare namespace Deno {
|
|||
| "systemMemoryInfo"
|
||||
| "networkInterfaces"
|
||||
| "osRelease"
|
||||
| "osUptime"
|
||||
| "uid"
|
||||
| "gid";
|
||||
}
|
||||
|
|
15
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
15
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
|
@ -1691,6 +1691,21 @@ declare namespace Deno {
|
|||
/** The buffered output from the child process' `stderr`. */
|
||||
readonly stderr: Uint8Array;
|
||||
}
|
||||
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* Returns the Operating System uptime in number of seconds.
|
||||
*
|
||||
* ```ts
|
||||
* console.log(Deno.osUptime());
|
||||
* ```
|
||||
*
|
||||
* Requires `allow-sys` permission.
|
||||
*
|
||||
* @tags allow-sys
|
||||
* @category Runtime Environment
|
||||
*/
|
||||
export function osUptime(): number;
|
||||
}
|
||||
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
return ops.op_os_release();
|
||||
}
|
||||
|
||||
function osUptime() {
|
||||
return ops.op_os_uptime();
|
||||
}
|
||||
|
||||
function systemMemoryInfo() {
|
||||
return ops.op_system_memory_info();
|
||||
}
|
||||
|
@ -106,6 +110,7 @@
|
|||
loadavg,
|
||||
networkInterfaces,
|
||||
osRelease,
|
||||
osUptime,
|
||||
setExitHandler,
|
||||
systemMemoryInfo,
|
||||
uid,
|
||||
|
|
|
@ -119,6 +119,7 @@
|
|||
refTimer: __bootstrap.timers.refTimer,
|
||||
unrefTimer: __bootstrap.timers.unrefTimer,
|
||||
osRelease: __bootstrap.os.osRelease,
|
||||
osUptime: __bootstrap.os.osUptime,
|
||||
hostname: __bootstrap.os.hostname,
|
||||
systemMemoryInfo: __bootstrap.os.systemMemoryInfo,
|
||||
networkInterfaces: __bootstrap.os.networkInterfaces,
|
||||
|
|
|
@ -29,6 +29,7 @@ fn init_ops(builder: &mut ExtensionBuilder) -> &mut ExtensionBuilder {
|
|||
op_loadavg::decl(),
|
||||
op_network_interfaces::decl(),
|
||||
op_os_release::decl(),
|
||||
op_os_uptime::decl(),
|
||||
op_set_env::decl(),
|
||||
op_set_exit_code::decl(),
|
||||
op_system_memory_info::decl(),
|
||||
|
@ -423,3 +424,13 @@ fn rss() -> usize {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[op]
|
||||
fn op_os_uptime(state: &mut OpState) -> Result<u64, AnyError> {
|
||||
super::check_unstable(state, "Deno.osUptime");
|
||||
state
|
||||
.borrow_mut::<Permissions>()
|
||||
.sys
|
||||
.check("osUptime", Some("Deno.osUptime()"))?;
|
||||
Ok(sys_info::os_uptime())
|
||||
}
|
||||
|
|
|
@ -300,3 +300,65 @@ pub fn mem_info() -> Option<MemInfo> {
|
|||
|
||||
Some(mem_info)
|
||||
}
|
||||
|
||||
pub fn os_uptime() -> u64 {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let mut info = std::mem::MaybeUninit::uninit();
|
||||
// SAFETY: `info` is a valid pointer to a `libc::sysinfo` struct.
|
||||
let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
|
||||
if res == 0 {
|
||||
// SAFETY: `sysinfo` initializes the struct.
|
||||
let info = unsafe { info.assume_init() };
|
||||
return info.uptime as u64;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_vendor = "apple",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
{
|
||||
use std::mem;
|
||||
use std::time::Duration;
|
||||
use std::time::SystemTime;
|
||||
let mut request = [libc::CTL_KERN, libc::KERN_BOOTTIME];
|
||||
// SAFETY: `boottime` is only accessed if sysctl() succeeds
|
||||
// and agrees with the `size` set by sysctl().
|
||||
let mut boottime: libc::timeval = unsafe { mem::zeroed() };
|
||||
let mut size: libc::size_t = mem::size_of_val(&boottime) as libc::size_t;
|
||||
// SAFETY: `sysctl` is thread-safe.
|
||||
let res = unsafe {
|
||||
libc::sysctl(
|
||||
&mut request[0],
|
||||
2,
|
||||
&mut boottime as *mut libc::timeval as *mut libc::c_void,
|
||||
&mut size,
|
||||
std::ptr::null_mut(),
|
||||
0,
|
||||
)
|
||||
};
|
||||
if res == 0 {
|
||||
return SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.map(|d| {
|
||||
(d - Duration::new(
|
||||
boottime.tv_sec as u64,
|
||||
boottime.tv_usec as u32 * 1000,
|
||||
))
|
||||
.as_secs()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
unsafe {
|
||||
// Windows is the only one that returns `uptime` in milisecond precision,
|
||||
// so we need to get the seconds out of it to be in sync with other envs.
|
||||
return unsafe { winapi::um::sysinfoapi::GetTickCount64() as u64 / 1000 };
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
|
|
@ -309,7 +309,7 @@ pub struct SysDescriptor(pub String);
|
|||
|
||||
pub fn parse_sys_kind(kind: &str) -> Result<&str, AnyError> {
|
||||
match kind {
|
||||
"hostname" | "osRelease" | "loadavg" | "networkInterfaces"
|
||||
"hostname" | "osRelease" | "osUptime" | "loadavg" | "networkInterfaces"
|
||||
| "systemMemoryInfo" | "uid" | "gid" => Ok(kind),
|
||||
_ => Err(type_error(format!("unknown system info kind \"{}\"", kind))),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue