Merge branch 'Zar-Branch' of https://git.racooncity.org/brotoskyj/Airlocktools into Zar-Branch

git commit -m "feat: Multiple UI improvements and new server log functionality

- Add Server Log tab with DataTable display of server activity logs

- Fix keyboard navigation bug in agents tab

- Add execution history viewer for selected agents

- Improve policy tree widget functionality by adding single device operations

- Integrate logging notifications into TUI
  - Add TextualNotificationHandler to setup.py
  - Display ERROR/WARNING/CRITICAL logs as toast notifications
  - Remove terminal output to prevent interference with TUI
  - Logs still written to Loxide.log file

closes #45"
This commit is contained in:
2025-12-16 16:17:25 -05:00
8 changed files with 346 additions and 67 deletions
+308 -28
View File
@@ -24,6 +24,34 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "airlock_libs"
version = "6.1.0"
dependencies = [
"chrono",
"crossbeam",
"flexi_logger",
"indicatif",
"log",
"mongodb",
"opentelemetry 0.27.1",
"opentelemetry-appender-log",
"opentelemetry-otlp",
"opentelemetry-proto",
"opentelemetry-semantic-conventions",
"opentelemetry_sdk 0.27.1",
"pyo3",
"reqwest",
"serde",
"serde-pyobject",
"serde_json",
"tokio",
"tonic",
"tracing",
"tracing-opentelemetry",
"tracing-subscriber",
]
[[package]] [[package]]
name = "android_system_properties" name = "android_system_properties"
version = "0.1.5" version = "0.1.5"
@@ -39,6 +67,150 @@ version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
[[package]]
name = "async-channel"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
dependencies = [
"concurrent-queue",
"event-listener 2.5.3",
"futures-core",
]
[[package]]
name = "async-channel"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
dependencies = [
"concurrent-queue",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-executor"
version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8"
dependencies = [
"async-task",
"concurrent-queue",
"fastrand",
"futures-lite",
"pin-project-lite",
"slab",
]
[[package]]
name = "async-global-executor"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c"
dependencies = [
"async-channel 2.5.0",
"async-executor",
"async-io",
"async-lock",
"blocking",
"futures-lite",
"once_cell",
]
[[package]]
name = "async-io"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc"
dependencies = [
"autocfg",
"cfg-if",
"concurrent-queue",
"futures-io",
"futures-lite",
"parking",
"polling",
"rustix",
"slab",
"windows-sys 0.61.2",
]
[[package]]
name = "async-lock"
version = "3.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc"
dependencies = [
"event-listener 5.4.1",
"event-listener-strategy",
"pin-project-lite",
]
[[package]]
name = "async-process"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
dependencies = [
"async-channel 2.5.0",
"async-io",
"async-lock",
"async-signal",
"async-task",
"blocking",
"cfg-if",
"event-listener 5.4.1",
"futures-lite",
"rustix",
]
[[package]]
name = "async-signal"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c"
dependencies = [
"async-io",
"async-lock",
"atomic-waker",
"cfg-if",
"futures-core",
"futures-io",
"rustix",
"signal-hook-registry",
"slab",
"windows-sys 0.61.2",
]
[[package]]
name = "async-std"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b"
dependencies = [
"async-channel 1.9.0",
"async-global-executor",
"async-io",
"async-lock",
"async-process",
"crossbeam-utils",
"futures-channel",
"futures-core",
"futures-io",
"futures-lite",
"gloo-timers",
"kv-log-macro",
"log",
"memchr",
"once_cell",
"pin-project-lite",
"pin-utils",
"slab",
"wasm-bindgen-futures",
]
[[package]] [[package]]
name = "async-stream" name = "async-stream"
version = "0.3.6" version = "0.3.6"
@@ -61,6 +233,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "async-task"
version = "4.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.89" version = "0.1.89"
@@ -164,6 +342,19 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "blocking"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21"
dependencies = [
"async-channel 2.5.0",
"async-task",
"futures-io",
"futures-lite",
"piper",
]
[[package]] [[package]]
name = "bson" name = "bson"
version = "2.15.0" version = "2.15.0"
@@ -234,6 +425,15 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]] [[package]]
name = "console" name = "console"
version = "0.16.1" version = "0.16.1"
@@ -555,6 +755,33 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "event-listener"
version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "event-listener"
version = "5.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
"event-listener 5.4.1",
"pin-project-lite",
]
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.3.0" version = "2.3.0"
@@ -649,6 +876,19 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-lite"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"parking",
"pin-project-lite",
]
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.31" version = "0.3.31"
@@ -732,6 +972,18 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
name = "gloo-timers"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
dependencies = [
"futures-channel",
"futures-core",
"js-sys",
"wasm-bindgen",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.4.12" version = "0.4.12"
@@ -769,6 +1021,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]] [[package]]
name = "hex" name = "hex"
version = "0.4.3" version = "0.4.3"
@@ -1198,6 +1456,15 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "kv-log-macro"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
dependencies = [
"log",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@@ -1236,6 +1503,9 @@ name = "log"
version = "0.4.29" version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
dependencies = [
"value-bag",
]
[[package]] [[package]]
name = "lru-slab" name = "lru-slab"
@@ -1625,6 +1895,7 @@ version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8" checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8"
dependencies = [ dependencies = [
"async-std",
"async-trait", "async-trait",
"futures-channel", "futures-channel",
"futures-executor", "futures-executor",
@@ -1655,6 +1926,12 @@ dependencies = [
"thiserror 2.0.17", "thiserror 2.0.17",
] ]
[[package]]
name = "parking"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.5" version = "0.12.5"
@@ -1725,12 +2002,37 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "piper"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
dependencies = [
"atomic-waker",
"fastrand",
"futures-io",
]
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.32" version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "polling"
version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"pin-project-lite",
"rustix",
"windows-sys 0.61.2",
]
[[package]] [[package]]
name = "portable-atomic" name = "portable-atomic"
version = "1.11.1" version = "1.11.1"
@@ -2413,34 +2715,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "signoz_test"
version = "6.0.0"
dependencies = [
"chrono",
"crossbeam",
"flexi_logger",
"indicatif",
"log",
"mongodb",
"opentelemetry 0.27.1",
"opentelemetry-appender-log",
"opentelemetry-otlp",
"opentelemetry-proto",
"opentelemetry-semantic-conventions",
"opentelemetry_sdk 0.27.1",
"pyo3",
"reqwest",
"serde",
"serde-pyobject",
"serde_json",
"tokio",
"tonic",
"tracing",
"tracing-opentelemetry",
"tracing-subscriber",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.11" version = "0.4.11"
@@ -3083,6 +3357,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "value-bag"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"
+3 -3
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "signoz_test" name = "airlock_libs"
version = "6.0.0" version = "6.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
@@ -25,7 +25,7 @@ crossbeam = "0.8.4"
log = "0.4.29" log = "0.4.29"
flexi_logger = "0.31.7" flexi_logger = "0.31.7"
opentelemetry-appender-log = "0.27.0" opentelemetry-appender-log = "0.27.0"
opentelemetry_sdk = { version = "0.27.0", features = ["rt-tokio", "trace"] } opentelemetry_sdk = { version = "0.27.0", features = ["rt-tokio", "testing", "trace"] }
[package.metadata.maturin] [package.metadata.maturin]
generate-abi-stubs = true generate-abi-stubs = true
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "maturin"
[project] [project]
name = "airlock_libs" name = "airlock_libs"
version = "6.0.0" version = "6.1.0"
description = "Airlock Digital API Wrapper" description = "Airlock Digital API Wrapper"
readme = "README.md" readme = "README.md"
license = { text = "AGPL-3.0-only" } license = { text = "AGPL-3.0-only" }
+26 -1
View File
@@ -8,7 +8,32 @@ pub struct TelemetryConfig {
} }
impl TelemetryConfig { impl TelemetryConfig {
pub fn load() -> Self { pub fn init_tracer() -> opentelemetry_sdk::trace::TracerProvider {
let cfg: TelemetryConfig = TelemetryConfig::load();
if !cfg.TELEMETRY {
return TracerProvider::builder().build();
}
let endpoint = cfg.TELEM_URL.unwrap_or_default();
let channel = Channel::from_shared(endpoint.clone())
.unwrap()
.tls_config(ClientTlsConfig::new().with_native_roots())
.unwrap()
.connect_lazy();
let exporter = opentelemetry_otlp::SpanExporter::builder()
.with_tonic()
.with_endpoint(endpoint.clone())
.with_channel(channel)
.build()
.expect("Failed to build exporter");
opentelemetry_sdk::trace::TracerProvider::builder()
.with_simple_exporter(exporter)
.with_resource(Resource::new(vec![KeyValue::new(
"service.name",
"LoxideLibs",
)]))
.build()
}
fn load() -> Self {
let cfg_path = get_base_directory().join("config\\user_config.json"); let cfg_path = get_base_directory().join("config\\user_config.json");
if !cfg_path.exists() { if !cfg_path.exists() {
return Self { return Self {
View File
+5
View File
@@ -1,4 +1,5 @@
pub use chrono::{Duration, Local, NaiveDate}; pub use chrono::{Duration, Local, NaiveDate};
pub use crossbeam::channel::unbounded;
pub use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle}; pub use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle};
pub use mongodb::bson::oid::ObjectId; pub use mongodb::bson::oid::ObjectId;
pub use opentelemetry::global::GlobalTracerProvider; pub use opentelemetry::global::GlobalTracerProvider;
@@ -7,6 +8,7 @@ pub use opentelemetry::trace::{Status, TraceContextExt, Tracer};
pub use opentelemetry::*; pub use opentelemetry::*;
pub use opentelemetry_otlp::ExportConfig; pub use opentelemetry_otlp::ExportConfig;
pub use opentelemetry_otlp::WithExportConfig; pub use opentelemetry_otlp::WithExportConfig;
pub use opentelemetry_otlp::WithTonicConfig;
pub use opentelemetry_sdk::Resource; pub use opentelemetry_sdk::Resource;
pub use opentelemetry_sdk::trace::{Config, TracerProvider}; pub use opentelemetry_sdk::trace::{Config, TracerProvider};
pub use pyo3::{prelude::*, types::PyString}; pub use pyo3::{prelude::*, types::PyString};
@@ -16,6 +18,8 @@ pub use reqwest::{
}; };
pub use serde::{Deserialize, Serialize}; pub use serde::{Deserialize, Serialize};
pub use serde_json::Value; pub use serde_json::Value;
pub use std::sync::{Arc, Mutex};
pub use std::thread;
pub use std::{ pub use std::{
collections::HashMap, collections::HashMap,
env, env,
@@ -25,3 +29,4 @@ pub use std::{
path::PathBuf, path::PathBuf,
str::FromStr, str::FromStr,
}; };
pub use tonic::transport::{Channel, ClientTlsConfig};
+2 -33
View File
@@ -1,10 +1,6 @@
use crate::modules::datatypes::*; use crate::modules::datatypes::*;
use crate::prelude::*; use crate::prelude::*;
use crossbeam::channel::unbounded;
use opentelemetry_otlp::WithTonicConfig;
use std::sync::{Arc, Mutex};
use std::thread;
use tonic::transport::{Channel, ClientTlsConfig};
#[pyfunction] #[pyfunction]
pub fn pull_policy_exec_histories( pub fn pull_policy_exec_histories(
py: Python<'_>, py: Python<'_>,
@@ -25,7 +21,7 @@ pub fn pull_policy_exec_histories(
std::process::abort(); std::process::abort();
} }
}; };
let tracer_provider = rt.block_on(async { init_tracer() }); let tracer_provider = rt.block_on(async { TelemetryConfig::init_tracer() });
global::set_tracer_provider(tracer_provider.clone()); global::set_tracer_provider(tracer_provider.clone());
let tracer: global::BoxedTracer = global::tracer("tracer"); let tracer: global::BoxedTracer = global::tracer("tracer");
let _cx: Context = Context::new(); let _cx: Context = Context::new();
@@ -184,9 +180,6 @@ pub fn pull_policy_exec_histories(
.unwrap() .unwrap()
.enable_steady_tick(std::time::Duration::from_millis(100)); .enable_steady_tick(std::time::Duration::from_millis(100));
let span: opentelemetry::trace::SpanRef<'_> = cx.span(); let span: opentelemetry::trace::SpanRef<'_> = cx.span();
//span.set_attribute(Key::new("Days").string(days.to_string()));
//span.set_attribute(Key::new("Days"));
//span.set_attribute(KeyValue::new("Policy Name", policy_names.clone()));
span.set_attribute(KeyValue::new("Days", days)); span.set_attribute(KeyValue::new("Days", days));
span.set_attribute(KeyValue::new("Policy Name", policy_names.clone())); span.set_attribute(KeyValue::new("Policy Name", policy_names.clone()));
loop { loop {
@@ -320,27 +313,3 @@ pub fn get_base_directory() -> PathBuf {
} }
} }
} }
fn init_tracer() -> opentelemetry_sdk::trace::TracerProvider {
let cfg: TelemetryConfig = TelemetryConfig::load();
let endpoint = cfg.TELEM_URL.unwrap_or_default().clone();
let channel_endpoint = endpoint.clone();
let channel = Channel::from_shared(channel_endpoint.clone())
.unwrap()
.tls_config(ClientTlsConfig::new().with_native_roots())
.unwrap()
.connect_lazy();
let exporter = opentelemetry_otlp::SpanExporter::builder()
.with_tonic()
.with_endpoint(endpoint.clone())
.with_channel(channel)
.build()
.expect("Failed to build exporter");
opentelemetry_sdk::trace::TracerProvider::builder()
.with_simple_exporter(exporter)
.with_resource(Resource::new(vec![KeyValue::new(
"service.name",
"LoxideLibs",
)]))
.build()
}
+1 -1
View File
@@ -23,4 +23,4 @@ pyperclip==1.11.0
# Custom/Private packages # Custom/Private packages
--extra-index-url https://git.racooncity.org/api/packages/brotoskyj/pypi/simple/ --extra-index-url https://git.racooncity.org/api/packages/brotoskyj/pypi/simple/
airlock_libs==6.0.0 airlock_libs==6.1.0