diff --git a/Cargo.lock b/Cargo.lock index 529a917..38746ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -215,7 +215,7 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memonitor" -version = "0.2.3" +version = "0.2.4" dependencies = [ "cfg_aliases", "memonitor-sys", @@ -227,7 +227,7 @@ dependencies = [ [[package]] name = "memonitor-sys" -version = "0.2.3" +version = "0.2.4" dependencies = [ "bindgen", "cfg_aliases", @@ -432,9 +432,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.7" +version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c385888ef380a852a16209afc8cfad22795dd8873d69c9a14d2e2088f118d18" +checksum = "26d7c217777061d5a2d652aea771fb9ba98b6dade657204b08c4b9604d11555b" dependencies = [ "cfg-if", "core-foundation-sys", diff --git a/crates/memonitor-sys/Cargo.toml b/crates/memonitor-sys/Cargo.toml index 027bbf2..5fc6be9 100644 --- a/crates/memonitor-sys/Cargo.toml +++ b/crates/memonitor-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memonitor-sys" description = "Automatically generated bindings for some of memonitor's backends." -version = "0.2.3" +version = "0.2.4" authors = ["Pedro Valente "] license = "Apache-2.0" repository = "https://github.com/edgenai/memonitor" diff --git a/crates/memonitor-sys/build.rs b/crates/memonitor-sys/build.rs index 5c5e8e4..4be0808 100644 --- a/crates/memonitor-sys/build.rs +++ b/crates/memonitor-sys/build.rs @@ -13,6 +13,35 @@ fn main() { let cur_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + { + let log_dir = cur_dir.join("log"); + let mut build = Config::new(log_dir.as_path()); + let lib_out = build.build(); + println!( + "cargo:rustc-link-search=native={}", + lib_out.join("lib").display() + ); + println!("cargo:rustc-link-lib=static=memonitor-log"); + + let vk_bindings = Builder::default() + .header(log_dir.join("include").join("log.h").to_string_lossy()) + .allowlist_function("log_.*") + .allowlist_type("log_.*") + .parse_callbacks(Box::new(PrefixRemover::new("log_"))) + .default_enum_style(EnumVariation::Rust { + non_exhaustive: false, + }) + .use_core() + .generate() + .expect("Failed to generate Log bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + + vk_bindings + .write_to_file(out_path.join("log_bindings.rs")) + .expect("Couldn't write bindings"); + } + #[cfg(feature = "vulkan")] { let vk_dir = cur_dir.join("vulkan"); diff --git a/crates/memonitor-sys/cuda/CMakeLists.txt b/crates/memonitor-sys/cuda/CMakeLists.txt index b6ec344..1f1218b 100644 --- a/crates/memonitor-sys/cuda/CMakeLists.txt +++ b/crates/memonitor-sys/cuda/CMakeLists.txt @@ -1,9 +1,12 @@ cmake_minimum_required(VERSION 3.5) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED true) + project(memonitor-cuda LANGUAGES C) add_library(memonitor-cuda STATIC "include/memonitor.h" "src/memonitor.c") -target_include_directories(memonitor-cuda PUBLIC "include") +target_include_directories(memonitor-cuda PUBLIC "include" PRIVATE "../log/include") install(TARGETS memonitor-cuda LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index 5fe67d3..007f17f 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -1,6 +1,7 @@ #include #include +#include #ifdef _WIN32 @@ -45,11 +46,6 @@ typedef CUresult (*cuDeviceTotalMem_type)(size_t *, CUdevice); typedef CUresult (*cuMemGetInfo_type)(size_t *, size_t *); -struct Device { - CUdevice handle; - CUdevice_opaque inner; -}; - static mod_type module = NULL; static cuInit_type cuInit = NULL; @@ -69,6 +65,7 @@ int cu_init() { #ifdef _WIN32 module = LoadLibraryA("nvcuda.dll"); if (!module) { + LOG_WARN("Could not load CUDA driver"); return -1; } @@ -87,7 +84,13 @@ int cu_init() { return -1; #else module = dlopen("libcuda.so", RTLD_NOW | RTLD_LOCAL); + + if (!module) { + module = dlopen("libcuda.so.1", RTLD_NOW | RTLD_LOCAL); + } + if (!module) { + LOG_WARN("Could not load CUDA driver."); return -1; } @@ -104,8 +107,11 @@ int cu_init() { cuMemGetInfo = (cuMemGetInfo_type) dlsym(module, "cuMemGetInfo_v2"); #endif + LOG_DEBUG("Found CUDA driver"); + CUresult res = cuInit(0); if (res != 0) { + LOG_WARN("Failed to initialise CUDA"); #ifdef _WIN32 FreeLibrary(module); #else @@ -115,6 +121,8 @@ int cu_init() { return -2; } + LOG_DEBUG("Initialised CUDA context"); + return 0; } @@ -147,24 +155,32 @@ struct cu_Devices cu_list_devices() { int count = 0; CUresult res = cuDeviceGetCount(&count); if (count <= 0 || res != 0) { + if (res) { + LOG_WARN("Failed to retrieve CUDA device count (error %d)", res); + } else { + LOG_WARN("No CUDA devices found"); + } + return invalid_devices; } + LOG_DEBUG("Found %d CUDA device(s)", count); - struct Device *device_handles = calloc(count, sizeof(struct Device)); + CUdevice *device_handles = calloc(count, sizeof(CUdevice)); CUcontext *ctx_handles = calloc(count, sizeof(CUcontext)); for (int d = 0; d < count; d++) { - // This is very wrong and should never be done, but cuDeviceGet seems to be very badly documented in what it - // does, sometimes it changes the value, others it changes the pointer - device_handles[d].handle = &device_handles[d].inner; - res = cuDeviceGet(&device_handles[d].handle, d); + // cuDeviceGet only sets the first few bytes of the CUdevice pointer, and ignores the rest. + // A nul pointer output is valid. + res = cuDeviceGet(&device_handles[d], d); if (res != 0) { + LOG_WARN("Failed to retrieve CUDA device %d (error %d)", d, res); free(device_handles); free(ctx_handles); return invalid_devices; } - res = cuCtxCreate(&ctx_handles[d], NULL, 0, 0, device_handles[d].handle); + res = cuCtxCreate(&ctx_handles[d], NULL, 0, 0, device_handles[d]); if (res != 0) { + LOG_WARN("Failed to create CUDA device %d (error %d)", d, res); free(device_handles); free(ctx_handles); return invalid_devices; @@ -172,6 +188,7 @@ struct cu_Devices cu_list_devices() { res = cuCtxPopCurrent(&ctx_handles[d]); if (res != 0) { + LOG_WARN("Failed to pop device context %d (error %d)", d, res); free(device_handles); free(ctx_handles); return invalid_devices; @@ -203,6 +220,7 @@ void cu_destroy_devices(struct cu_Devices *devices) { struct cu_DeviceRef cu_get_device(struct cu_Devices *devices, uint32_t index) { const struct cu_DeviceRef invalid_ref = {NULL}; if (!devices || !devices->devices_handle || !devices->ctx_handle || !devices->count || devices->count <= index) { + LOG_WARN("Invalid CUDA device (index %u)", index); return invalid_ref; } @@ -214,7 +232,8 @@ struct cu_DeviceRef cu_get_device(struct cu_Devices *devices, uint32_t index) { struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device) { const struct cu_DeviceProperties invalid_properties = {{0}, Other, 0}; - if (!device.handle) { + if (!device.ctx_handle) { + LOG_WARN("Invalid CUDA device handle"); return invalid_properties; } @@ -224,11 +243,13 @@ struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device) { CUresult res = cuDeviceGetName(props.name, sizeof(props.name), cast_device); if (res != 0) { + LOG_WARN("Failed to get CUDA device name (error %d)", res); return invalid_properties; } res = cuDeviceTotalMem(&props.total_memory, cast_device); if (res != 0) { + LOG_WARN("Failed to get CUDA device total memory (error %d)", res); return invalid_properties; } @@ -237,13 +258,15 @@ struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device) { struct cu_DeviceMemoryProperties cu_device_memory_properties(struct cu_DeviceRef device) { const struct cu_DeviceMemoryProperties invalid_properties = {0}; - if (!device.handle) { + if (!device.ctx_handle) { + LOG_WARN("Invalid CUDA device handle"); return invalid_properties; } CUcontext *cast_ctx = device.ctx_handle; CUresult res = cuCtxPushCurrent(*cast_ctx); if (res != 0) { + LOG_WARN("Failed to push CUDA device context (error %d)", res); return invalid_properties; } @@ -252,11 +275,13 @@ struct cu_DeviceMemoryProperties cu_device_memory_properties(struct cu_DeviceRef res = cuMemGetInfo(&free_memory, &total_memory); if (res != 0) { + LOG_WARN("Failed to get CUDA device memory properties (error %d)", res); return invalid_properties; } res = cuCtxPopCurrent(cast_ctx); if (res != 0) { + LOG_WARN("Failed to pop CUDA device context (error %d)", res); return invalid_properties; } diff --git a/crates/memonitor-sys/log/CMakeLists.txt b/crates/memonitor-sys/log/CMakeLists.txt new file mode 100644 index 0000000..02fb1cc --- /dev/null +++ b/crates/memonitor-sys/log/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.5) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED true) + +project(memonitor-log LANGUAGES C) + +add_library(memonitor-log STATIC "include/log.h" "src/log.c") +target_include_directories(memonitor-log PUBLIC "include") + +install(TARGETS memonitor-log + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) \ No newline at end of file diff --git a/crates/memonitor-sys/log/include/log.h b/crates/memonitor-sys/log/include/log.h new file mode 100644 index 0000000..a57b7c6 --- /dev/null +++ b/crates/memonitor-sys/log/include/log.h @@ -0,0 +1,55 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#include + +/** + * The verbosity level of a log event. + */ +enum log_Level { + Trace, //!< Designates very low priority, often extremely verbose, information. + Debug, //!< Designates lower priority information. + Info, //!< Designates useful information. + Warn, //!< Designates hazardous situations. + Error, //!< Designates very serious errors. +}; + +/** + * The type of a log event function. + * + * @param level The verbosity level of the event. + * @param msg The string message to be logged. + */ +typedef void (*log_LogFn)(enum log_Level level, const char *msg); + +/** + * Set the global event logging function. + * + * @param fn_ptr A pointer to the event logging function. If `NULL`, the global logger is unset. + */ +void log_set(log_LogFn fn_ptr); + +/** + * The inner logging function, this should not be called directly, instead the macros defined in the same header + * should be used.. + * + * @param level The verbosity level of the event. + * @param msg The string message to be logged. + */ +void inner_log(enum log_Level level, const char *msg); + +#define LOG_MSG_SIZE(message, ...) sizeof(message) +#define INNER_LOG(level, ...) { char tmp[LOG_MSG_SIZE(__VA_ARGS__) + 256]; snprintf(tmp, sizeof(tmp), __VA_ARGS__); inner_log(level, tmp); }(0) + +#define LOG_TRACE(...) INNER_LOG(Trace, __VA_ARGS__) +#define LOG_DEBUG(...) INNER_LOG(Debug, __VA_ARGS__) +#define LOG_INFO(...) INNER_LOG(Info, __VA_ARGS__) +#define LOG_WARN(...) INNER_LOG(Warn, __VA_ARGS__) +#define LOG_ERROR(...) INNER_LOG(Error, __VA_ARGS__) + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/crates/memonitor-sys/log/src/log.c b/crates/memonitor-sys/log/src/log.c new file mode 100644 index 0000000..c8747bb --- /dev/null +++ b/crates/memonitor-sys/log/src/log.c @@ -0,0 +1,15 @@ +#include + +#include + +static log_LogFn logger = NULL; + +void log_set(log_LogFn fn_ptr) { + logger = fn_ptr; +} + +void inner_log(enum log_Level level, const char *msg) { + if (logger) { + logger(level, msg); + } +} diff --git a/crates/memonitor-sys/src/lib.rs b/crates/memonitor-sys/src/lib.rs index 8092760..ed221a0 100644 --- a/crates/memonitor-sys/src/lib.rs +++ b/crates/memonitor-sys/src/lib.rs @@ -8,6 +8,8 @@ #![warn(missing_docs)] +pub mod log; + #[cfg(all(feature = "cuda", not(apple)))] pub mod cuda; #[cfg(feature = "vulkan")] diff --git a/crates/memonitor-sys/src/log.rs b/crates/memonitor-sys/src/log.rs new file mode 100644 index 0000000..d7f1926 --- /dev/null +++ b/crates/memonitor-sys/src/log.rs @@ -0,0 +1,7 @@ +//! Automatically generated bindings for the native logger. + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!(concat!(env!("OUT_DIR"), "/log_bindings.rs")); diff --git a/crates/memonitor-sys/vulkan/CMakeLists.txt b/crates/memonitor-sys/vulkan/CMakeLists.txt index 211d50a..f9006f4 100644 --- a/crates/memonitor-sys/vulkan/CMakeLists.txt +++ b/crates/memonitor-sys/vulkan/CMakeLists.txt @@ -11,7 +11,7 @@ add_subdirectory(thirdparty/volk) option(MEMONITOR_VALIDATE "Use Vulkan validation layers" OFF) add_library(memonitor-vk STATIC "include/memonitor.h" "src/memonitor.c") -target_include_directories(memonitor-vk PUBLIC "include") +target_include_directories(memonitor-vk PUBLIC "include" PRIVATE "../log/include") target_link_libraries(memonitor-vk PRIVATE volk) if (MEMONITOR_VALIDATE) diff --git a/crates/memonitor-sys/vulkan/src/memonitor.c b/crates/memonitor-sys/vulkan/src/memonitor.c index 14202db..5f653a8 100644 --- a/crates/memonitor-sys/vulkan/src/memonitor.c +++ b/crates/memonitor-sys/vulkan/src/memonitor.c @@ -4,6 +4,7 @@ #include #include +#include #define ARRAY_LEN(array) sizeof(array) / sizeof(array[0]) @@ -26,11 +27,13 @@ int layer_support() { uint32_t count = 0; VkResult res = vkEnumerateInstanceLayerProperties(&count, NULL); if (res != VK_SUCCESS) { + LOG_WARN("Failed to enumerate Vulkan layers (error %d)", res); return res; } VkLayerProperties *properties = malloc(sizeof(VkLayerProperties) * count); res = vkEnumerateInstanceLayerProperties(&count, properties); if (res != VK_SUCCESS) { + LOG_WARN("Failed to enumerate Vulkan layers (error %d)", res); free(properties); return res; } @@ -46,6 +49,7 @@ int layer_support() { } if (!layer_found) { + LOG_WARN("Could not find Vulkan layer %s", layer_names[l]); free(properties); return VK_RESULT_MAX_ENUM; } @@ -66,11 +70,13 @@ int extension_support() { uint32_t count = 0; VkResult res = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL); if (res != VK_SUCCESS) { + LOG_WARN("Failed to enumerate Vulkan extensions (error %d)", res); return res; } VkExtensionProperties *properties = malloc(sizeof(VkExtensionProperties) * count); res = vkEnumerateInstanceExtensionProperties(NULL, &count, properties); if (res != VK_SUCCESS) { + LOG_WARN("Failed to enumerate Vulkan extensions (error %d)", res); free(properties); return res; } @@ -86,6 +92,7 @@ int extension_support() { } if (!extension_found) { + LOG_WARN("Could not find Vulkan extension %s", extension_names[e]); free(properties); return VK_RESULT_MAX_ENUM; } @@ -98,6 +105,7 @@ int extension_support() { int vk_init() { VkResult res = volkInitialize(); if (res != VK_SUCCESS) { + LOG_WARN("Failed to initialise Volk (error %d)", res); return res; } @@ -141,11 +149,12 @@ int vk_init() { VkInstance instance; res = vkCreateInstance(&instance_info, NULL, &instance); if (res != VK_SUCCESS) { + LOG_WARN("Failed to initialise Vulkan instance (error %d)", res); volkFinalize(); return res; } - volkLoadInstanceOnly(instance); + volkLoadInstance(instance); return VK_SUCCESS; } @@ -158,20 +167,24 @@ struct vk_Devices vk_list_devices() { VkInstance instance = volkGetLoadedInstance(); if (instance == VK_NULL_HANDLE) { + LOG_WARN("No Vulkan instance has been initialised"); return invalid_devices; } uint32_t count = 0; VkResult res = vkEnumeratePhysicalDevices(instance, &count, NULL); if (res != VK_SUCCESS) { + LOG_WARN("Failed to enumerate Vulkan devices (error %d)", res); return invalid_devices; } VkPhysicalDevice *device_handles = malloc(sizeof(VkPhysicalDevice) * count); res = vkEnumeratePhysicalDevices(instance, &count, device_handles); if (res != VK_SUCCESS) { + LOG_WARN("Failed to enumerate Vulkan devices (error %d)", res); free(device_handles); return invalid_devices; } + LOG_DEBUG("Found %d Vulkan device(s)", count); uint32_t *heap_indexes = calloc(count, sizeof(uint32_t)); for (uint32_t d = 0; d < count; d++) { @@ -204,6 +217,7 @@ void vk_destroy_devices(struct vk_Devices *devices) { struct vk_DeviceRef vk_get_device(struct vk_Devices *devices, uint32_t index) { const struct vk_DeviceRef invalid_ref = {NULL}; if (!devices || !devices->handle || !devices->count || devices->count <= index) { + LOG_WARN("Invalid Vulkan device (index %u)", index); return invalid_ref; } @@ -215,6 +229,7 @@ struct vk_DeviceRef vk_get_device(struct vk_Devices *devices, uint32_t index) { struct vk_DeviceProperties vk_device_properties(struct vk_DeviceRef device) { const struct vk_DeviceProperties invalid_properties = {{0}, Other, 0}; if (!device.handle) { + LOG_WARN("Invalid Vulkan device handle"); return invalid_properties; } @@ -267,6 +282,7 @@ struct vk_DeviceProperties vk_device_properties(struct vk_DeviceRef device) { struct vk_DeviceMemoryProperties vk_device_memory_properties(struct vk_DeviceRef device) { const struct vk_DeviceMemoryProperties invalid_properties = {0}; if (!device.handle) { + LOG_WARN("Invalid Vulkan device handle"); return invalid_properties; } @@ -279,6 +295,7 @@ struct vk_DeviceMemoryProperties vk_device_memory_properties(struct vk_DeviceRef vkGetPhysicalDeviceMemoryProperties2(cast_device, &properties); if (!properties.pNext) { + LOG_WARN("Failed to retrieve current Vulkan device memory values"); return invalid_properties; } struct vk_DeviceMemoryProperties mem_props = {memory_stats.heapBudget[device.local_heap], diff --git a/crates/memonitor/Cargo.toml b/crates/memonitor/Cargo.toml index 7eb9b87..54cf23b 100644 --- a/crates/memonitor/Cargo.toml +++ b/crates/memonitor/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memonitor" description = "Query CPU and GPU memory information in a portable way." -version = "0.2.3" +version = "0.2.4" authors = ["Pedro Valente "] license = "Apache-2.0" repository = "https://github.com/edgenai/memonitor" @@ -10,9 +10,9 @@ edition = "2021" publish = true [dependencies] -memonitor-sys = { path = "../memonitor-sys", version = "0.2.3", default-features = false } +memonitor-sys = { path = "../memonitor-sys", version = "0.2.4", default-features = false } once_cell = "1.19.0" -sysinfo = "0.30.7" +sysinfo = "0.30.10" tracing = "0.1.40" [build-dependencies] diff --git a/crates/memonitor/src/cuda.rs b/crates/memonitor/src/cuda.rs index d4628d6..217d01d 100644 --- a/crates/memonitor/src/cuda.rs +++ b/crates/memonitor/src/cuda.rs @@ -1,7 +1,7 @@ use std::ffi::CStr; use std::ptr::addr_of_mut; -use tracing::debug; +use tracing::{debug, info, warn}; use memonitor_sys::cuda; @@ -25,7 +25,7 @@ impl Cuda { let mut c_devices = unsafe { cuda::list_devices() }; if c_devices.count == 0 { - debug!("No Cuda devices found. Aborting CUDA initialisation."); + warn!("No Cuda devices found. Aborting CUDA initialisation."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -37,7 +37,7 @@ impl Cuda { for i in 0..c_devices.count { let c_device = unsafe { cuda::get_device(addr_of_mut!(c_devices), i) }; if c_device.ctx_handle.is_null() { - debug!("Invalid device handle. Aborting CUDA initialisation."); + warn!("Invalid device handle. Aborting CUDA initialisation."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -47,7 +47,7 @@ impl Cuda { let properties = unsafe { cuda::device_properties(c_device) }; if properties.name[0] == 0 { - debug!("Invalid device name. Aborting CUDA initialisation."); + warn!("Invalid device name. Aborting CUDA initialisation."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -64,7 +64,7 @@ impl Cuda { }; if properties.total_memory == 0 { - debug!("Invalid amount of memory."); + warn!("Invalid amount of memory. Skipping device."); continue; } @@ -79,14 +79,10 @@ impl Cuda { let backend = Cuda { handle: c_devices }; + info!("Successfully initialised CUDA backend."); Some((backend, devices)) } else { - match res { - -1 => debug!("Could not find Cuda driver module."), - -2 => debug!("Failed to initialise Cuda context."), - _ => unreachable!("Unhandled error."), - } - + warn!("Failed to initialise the CUDA backend."); None } } diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index f42fb25..224b627 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -35,11 +35,12 @@ #![warn(missing_docs)] -use once_cell::sync::Lazy; use std::fmt::{Display, Formatter}; use std::ops::{Deref, RangeBounds, RangeFull}; use std::sync::{RwLock, RwLockReadGuard}; +use once_cell::sync::Lazy; + mod cpu; #[cfg(feature = "vulkan")] @@ -47,6 +48,7 @@ mod vulkan; #[cfg(all(feature = "cuda", not(apple)))] mod cuda; +mod log; /// A backend identifier. #[non_exhaustive] @@ -99,6 +101,10 @@ impl Context { return; } + unsafe { + memonitor_sys::log::set(Some(log::log)); + } + let (system, cpus) = cpu::Host::init(); self.register_backend(system, cpus); diff --git a/crates/memonitor/src/log.rs b/crates/memonitor/src/log.rs new file mode 100644 index 0000000..bb321cf --- /dev/null +++ b/crates/memonitor/src/log.rs @@ -0,0 +1,21 @@ +use memonitor_sys::log::Level; +use std::ffi::{c_char, CStr}; +use tracing::{debug, error, info, trace, warn}; + +const TARGET: &str = "memonitor-sys"; + +pub(super) unsafe extern "C" fn log(level: Level, text: *const c_char) { + let text = unsafe { + // SAFETY: `text` is a NUL-terminated C String + CStr::from_ptr(text) + }; + let text = text.to_string_lossy(); + + match level { + Level::Trace => trace!(target: TARGET, "{text}"), + Level::Debug => debug!(target: TARGET, "{text}"), + Level::Info => info!(target: TARGET, "{text}"), + Level::Warn => warn!(target: TARGET, "{text}"), + Level::Error => error!(target: TARGET, "{text}"), + } +} diff --git a/crates/memonitor/src/vulkan.rs b/crates/memonitor/src/vulkan.rs index 379a69a..1b8338c 100644 --- a/crates/memonitor/src/vulkan.rs +++ b/crates/memonitor/src/vulkan.rs @@ -1,6 +1,6 @@ use std::ffi::CStr; use std::ptr::addr_of_mut; -use tracing::{debug, info}; +use tracing::{debug, info, warn}; use memonitor_sys::vulkan; @@ -25,7 +25,7 @@ impl Vulkan { let mut c_devices = unsafe { vulkan::list_devices() }; if c_devices.handle.is_null() { - debug!("No Vulkan devices found. Aborting Vulkan initialisation."); + warn!("No Vulkan devices found. Aborting Vulkan initialisation."); unsafe { vulkan::term() }; return None; } @@ -34,7 +34,7 @@ impl Vulkan { for i in 0..c_devices.count { let c_device = unsafe { vulkan::get_device(addr_of_mut!(c_devices), i) }; if c_device.handle.is_null() { - debug!("Invalid device handle. Aborting Vulkan initialisation."); + warn!("Invalid device handle. Aborting Vulkan initialisation."); unsafe { vulkan::destroy_devices(addr_of_mut!(c_devices)); vulkan::term(); @@ -44,7 +44,7 @@ impl Vulkan { let properties = unsafe { vulkan::device_properties(c_device) }; if properties.name[0] == 0 { - debug!("Invalid device name. Aborting Vulkan initialisation."); + warn!("Invalid device name. Aborting Vulkan initialisation."); unsafe { vulkan::destroy_devices(addr_of_mut!(c_devices)); vulkan::term(); @@ -53,7 +53,7 @@ impl Vulkan { } if properties.total_memory == 0 { - debug!("Invalid amount of memory. Skipping this device."); + warn!("Invalid amount of memory. Skipping this device."); continue; } @@ -78,9 +78,10 @@ impl Vulkan { let backend = Vulkan { handle: c_devices }; + info!("Successfully initialised Vulkan backend."); Some((backend, devices)) } else { - info!("Vulkan runtime not found."); + warn!("Vulkan runtime not found."); None } } diff --git a/crates/memonitor/tests/common/mod.rs b/crates/memonitor/tests/common/mod.rs index 26377f2..54b2624 100644 --- a/crates/memonitor/tests/common/mod.rs +++ b/crates/memonitor/tests/common/mod.rs @@ -1,11 +1,13 @@ use tracing_subscriber::filter::LevelFilter; -use tracing_subscriber::layer::SubscriberExt; -use tracing_subscriber::util::SubscriberInitExt; -use tracing_subscriber::{EnvFilter, fmt, registry}; +use tracing_subscriber::{fmt, EnvFilter}; pub fn init_tracing() { - let format = fmt::layer().pretty(); + let format = fmt::format() + .with_target(true) + .with_source_location(false) + .with_thread_names(true) + .compact(); let filter = EnvFilter::try_from_default_env() .unwrap_or(EnvFilter::default().add_directive(LevelFilter::TRACE.into())); - registry().with(format).with(filter).init(); + fmt().event_format(format).with_env_filter(filter).init(); }