feat(ffi): API for enabling tracing logs (#452)

This commit is contained in:
irvingouj @ Devolutions
2024-05-03 02:44:00 -04:00
committed by GitHub
parent 7a1ff4a8e7
commit 0ec5be5dc4
10 changed files with 172 additions and 1 deletions
Generated
+2
View File
@@ -1136,6 +1136,8 @@ dependencies = [
"ironrdp",
"sspi",
"thiserror",
"tracing",
"tracing-subscriber",
]
[[package]]
+2
View File
@@ -22,6 +22,8 @@ diplomat-runtime = "0.7.0"
ironrdp = { workspace = true, features = ["connector", "dvc", "svc","rdpdr","rdpsnd","graphics","input"] }
sspi = { workspace = true, features = ["network_client"] }
thiserror.workspace = true
tracing.workspace = true
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
[target.'cfg(windows)'.build-dependencies]
embed-resource = "2.2.0"
@@ -30,6 +30,8 @@ public partial class MainWindow : Window
private void OnOpened(object? sender, EventArgs e)
{
Log.InitWithEnv();
WindowState = WindowState.Maximized;
var username = Environment.GetEnvironmentVariable("IRONRDP_USERNAME");
@@ -9,6 +9,8 @@ namespace Devolutions.IronRdp.ConnectExample
{
var arguments = ParseArguments(args);
Log.InitWithEnv();
if (arguments == null)
{
return;
@@ -0,0 +1,71 @@
// <auto-generated/> by Diplomat
#pragma warning disable 0105
using System;
using System.Runtime.InteropServices;
using Devolutions.IronRdp.Diplomat;
#pragma warning restore 0105
namespace Devolutions.IronRdp;
#nullable enable
public partial class Log: IDisposable
{
private unsafe Raw.Log* _inner;
/// <summary>
/// Creates a managed <c>Log</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// <br/>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe Log(Raw.Log* handle)
{
_inner = handle;
}
public static void InitWithEnv()
{
unsafe
{
Raw.Log.InitWithEnv();
}
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.Log* AsFFI()
{
return _inner;
}
/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}
Raw.Log.Destroy(_inner);
_inner = null;
GC.SuppressFinalize(this);
}
}
~Log()
{
Dispose();
}
}
@@ -0,0 +1,24 @@
// <auto-generated/> by Diplomat
#pragma warning disable 0105
using System;
using System.Runtime.InteropServices;
using Devolutions.IronRdp.Diplomat;
#pragma warning restore 0105
namespace Devolutions.IronRdp.Raw;
#nullable enable
[StructLayout(LayoutKind.Sequential)]
public partial struct Log
{
private const string NativeLib = "DevolutionsIronRdp";
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Log_init_with_env", ExactSpelling = true)]
public static unsafe extern void InitWithEnv();
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Log_destroy", ExactSpelling = true)]
public static unsafe extern void Destroy(Log* self);
}
+1 -1
View File
@@ -195,7 +195,7 @@ pub mod ffi {
performance_flags: self.performance_flags.ok_or("performance flag is missing")?,
desktop_scale_factor: 0,
};
tracing::debug!(config=?inner_config, "Built config");
Ok(Box::new(Config(inner_config)))
}
}
+1
View File
@@ -151,6 +151,7 @@ pub mod ffi {
let Some(connector) = self.0.as_ref() else {
return Err(ValueConsumedError::for_item("connector").into());
};
tracing::trace!(pduhint=?connector.next_pdu_hint(), "Reading next PDU hint");
Ok(connector.next_pdu_hint().map(PduHint).map(Box::new))
}
+1
View File
@@ -7,6 +7,7 @@ pub mod dvc;
pub mod error;
pub mod graphics;
pub mod input;
pub mod log;
pub mod pdu;
pub mod session;
pub mod svc;
+66
View File
@@ -0,0 +1,66 @@
use std::{error::Error, sync::Once};
static INIT_LOG: Once = Once::new();
const IRONRDP_LOG_PATH: &str = "IRONRDP_LOG_PATH";
const IRONRDP_LOG: &str = "IRONRDP_LOG";
#[diplomat::bridge]
pub mod ffi {
use super::{setup_logging, INIT_LOG, IRONRDP_LOG_PATH};
#[diplomat::opaque]
pub struct Log;
impl Log {
pub fn init_with_env() {
INIT_LOG.call_once(|| {
let log_file = std::env::var(IRONRDP_LOG_PATH).ok();
let log_file = log_file.as_deref();
setup_logging(log_file).expect("Failed to setup logging");
});
}
}
}
fn setup_logging(log_file_path: Option<&str>) -> Result<(), Box<dyn Error>> {
use std::{fs::create_dir_all, fs::OpenOptions, path::PathBuf};
use tracing::metadata::LevelFilter;
use tracing_subscriber::prelude::*;
use tracing_subscriber::EnvFilter;
let env_filter = EnvFilter::builder()
.with_default_directive(LevelFilter::WARN.into())
.with_env_var(IRONRDP_LOG)
.from_env_lossy();
if let Some(log_file_path) = log_file_path {
let path = PathBuf::from(log_file_path);
if let Some(parent) = path.parent() {
create_dir_all(parent)?;
}
let file = OpenOptions::new().create(true).append(true).open(log_file_path)?;
let fmt_layer = tracing_subscriber::fmt::layer()
.with_ansi(false)
.with_writer(file)
.compact();
tracing_subscriber::registry()
.with(env_filter)
.with(fmt_layer)
.try_init()?;
} else {
let fmt_layer = tracing_subscriber::fmt::layer()
.compact()
.with_file(true)
.with_line_number(true)
.with_thread_ids(true)
.with_target(false);
tracing_subscriber::registry()
.with(env_filter)
.with(fmt_layer)
.try_init()?;
};
Ok(())
}