Skip to main content

ri/java/classes/
observability.rs

1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//!     http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18//! # Observability Module JNI Bindings
19//!
20//! JNI bindings for Ri observability classes.
21
22use jni::JNIEnv;
23use jni::objects::{JClass, JObject, JString, JDoubleArray};
24use jni::sys::{jdouble, jint, jlong, jstring, jobjectArray, jobject};
25use crate::observability::{
26    RiObservabilityModule, RiTracer, RiSpanKind, RiSpanStatus,
27    RiMetric, RiMetricConfig, RiMetricType, RiMetricsRegistry,
28};
29#[cfg(feature = "system_info")]
30use crate::observability::{
31    RiSystemMetricsCollector, RiSystemMetrics, RiCPUMetrics, RiMemoryMetrics, RiDiskMetrics, RiNetworkMetrics,
32};
33use crate::java::exception::check_not_null;
34
35#[no_mangle]
36pub extern "system" fn Java_com_dunimd_ri_observability_RiObservabilityModule_new0(
37    mut env: JNIEnv,
38    _class: JClass,
39    config_ptr: jlong,
40) -> jlong {
41    if !check_not_null(&mut env, config_ptr, "RiObservabilityConfig") {
42        return 0;
43    }
44    let module = Box::new(RiObservabilityModule::new());
45    Box::into_raw(module) as jlong
46}
47
48#[no_mangle]
49pub extern "system" fn Java_com_dunimd_ri_observability_RiObservabilityModule_free0(
50    _env: JNIEnv,
51    _class: JClass,
52    ptr: jlong,
53) {
54    if ptr != 0 {
55        unsafe {
56            let _ = Box::from_raw(ptr as *mut RiObservabilityModule);
57        }
58    }
59}
60
61// RiTracer JNI bindings
62#[no_mangle]
63pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_new0(
64    _env: JNIEnv,
65    _class: JClass,
66    sampling_rate: jdouble,
67) -> jlong {
68    let tracer = Box::new(RiTracer::new(sampling_rate));
69    Box::into_raw(tracer) as jlong
70}
71
72#[no_mangle]
73pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_startTrace0(
74    mut env: JNIEnv,
75    _class: JClass,
76    ptr: jlong,
77    name: JString,
78) -> jstring {
79    if ptr == 0 {
80        return std::ptr::null_mut();
81    }
82    
83    let tracer = unsafe { &*(ptr as *const RiTracer) };
84    let name_str: String = match env.get_string(&name) {
85        Ok(s) => s.into(),
86        Err(_) => return std::ptr::null_mut(),
87    };
88    
89    match tracer.start_trace(name_str) {
90        Some(trace_id) => {
91            match env.new_string(trace_id.as_str()) {
92                Ok(s) => s.into_raw(),
93                Err(_) => std::ptr::null_mut(),
94            }
95        }
96        None => std::ptr::null_mut(),
97    }
98}
99
100#[no_mangle]
101pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_span0(
102    mut env: JNIEnv,
103    _class: JClass,
104    ptr: jlong,
105    name: JString,
106    kind: JString,
107) -> jstring {
108    if ptr == 0 {
109        return std::ptr::null_mut();
110    }
111    
112    let tracer = unsafe { &*(ptr as *const RiTracer) };
113    let name_str: String = match env.get_string(&name) {
114        Ok(s) => s.into(),
115        Err(_) => return std::ptr::null_mut(),
116    };
117    let kind_str: String = match env.get_string(&kind) {
118        Ok(s) => s.into(),
119        Err(_) => return std::ptr::null_mut(),
120    };
121    
122    let span_kind = match kind_str.as_str() {
123        "Server" => RiSpanKind::Server,
124        "Client" => RiSpanKind::Client,
125        "Producer" => RiSpanKind::Producer,
126        "Consumer" => RiSpanKind::Consumer,
127        _ => RiSpanKind::Internal,
128    };
129    
130    match tracer.start_span_from_context(name_str, span_kind) {
131        Some(span_id) => {
132            match env.new_string(span_id.as_str()) {
133                Ok(s) => s.into_raw(),
134                Err(_) => std::ptr::null_mut(),
135            }
136        }
137        None => std::ptr::null_mut(),
138    }
139}
140
141#[no_mangle]
142pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_finishSpan0(
143    mut env: JNIEnv,
144    _class: JClass,
145    ptr: jlong,
146    span_id: JString,
147    status: JString,
148) {
149    if ptr == 0 {
150        return;
151    }
152    
153    let tracer = unsafe { &*(ptr as *const RiTracer) };
154    let span_id_str: String = match env.get_string(&span_id) {
155        Ok(s) => s.into(),
156        Err(_) => return,
157    };
158    let status_str: String = match env.get_string(&status) {
159        Ok(s) => s.into(),
160        Err(_) => return,
161    };
162    
163    let span_status = match status_str.as_str() {
164        "Ok" => RiSpanStatus::Ok,
165        "Error" => RiSpanStatus::Error("Java error".to_string()),
166        _ => RiSpanStatus::Unset,
167    };
168    
169    use crate::observability::tracing::RiSpanId;
170    let span_id_obj = RiSpanId::from_string(span_id_str);
171    let _ = tracer.end_span(&span_id_obj, span_status);
172}
173
174#[no_mangle]
175pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_setAttribute0(
176    mut env: JNIEnv,
177    _class: JClass,
178    ptr: jlong,
179    span_id: JString,
180    key: JString,
181    value: JString,
182) {
183    if ptr == 0 {
184        return;
185    }
186    
187    let tracer = unsafe { &*(ptr as *const RiTracer) };
188    let span_id_str: String = match env.get_string(&span_id) {
189        Ok(s) => s.into(),
190        Err(_) => return,
191    };
192    let key_str: String = match env.get_string(&key) {
193        Ok(s) => s.into(),
194        Err(_) => return,
195    };
196    let value_str: String = match env.get_string(&value) {
197        Ok(s) => s.into(),
198        Err(_) => return,
199    };
200    
201    use crate::observability::tracing::RiSpanId;
202    let span_id_obj = RiSpanId::from_string(span_id_str);
203    let _ = tracer.span_mut(&span_id_obj, |span| {
204        span.set_attribute(key_str, value_str);
205    });
206}
207
208#[no_mangle]
209pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_addEvent0(
210    mut env: JNIEnv,
211    _class: JClass,
212    ptr: jlong,
213    span_id: JString,
214    name: JString,
215) {
216    if ptr == 0 {
217        return;
218    }
219    
220    let tracer = unsafe { &*(ptr as *const RiTracer) };
221    let span_id_str: String = match env.get_string(&span_id) {
222        Ok(s) => s.into(),
223        Err(_) => return,
224    };
225    let name_str: String = match env.get_string(&name) {
226        Ok(s) => s.into(),
227        Err(_) => return,
228    };
229    
230    use crate::observability::tracing::RiSpanId;
231    let span_id_obj = RiSpanId::from_string(span_id_str);
232    let _ = tracer.span_mut(&span_id_obj, |span| {
233        span.add_event(name_str, std::collections::HashMap::default());
234    });
235}
236
237#[no_mangle]
238pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_getActiveTraceCount0(
239    _env: JNIEnv,
240    _class: JClass,
241    ptr: jlong,
242) -> jint {
243    if ptr == 0 {
244        return 0;
245    }
246    
247    let tracer = unsafe { &*(ptr as *const RiTracer) };
248    tracer.active_trace_count() as jint
249}
250
251#[no_mangle]
252pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_getActiveSpanCount0(
253    _env: JNIEnv,
254    _class: JClass,
255    ptr: jlong,
256) -> jint {
257    if ptr == 0 {
258        return 0;
259    }
260    
261    let tracer = unsafe { &*(ptr as *const RiTracer) };
262    tracer.active_span_count() as jint
263}
264
265#[no_mangle]
266pub extern "system" fn Java_com_dunimd_ri_observability_RiTracer_free0(
267    _env: JNIEnv,
268    _class: JClass,
269    ptr: jlong,
270) {
271    if ptr != 0 {
272        unsafe {
273            let _ = Box::from_raw(ptr as *mut RiTracer);
274        }
275    }
276}
277
278// RiMetricConfig JNI bindings
279#[no_mangle]
280pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricConfig_new0(
281    mut env: JNIEnv,
282    _class: JClass,
283    name: JString,
284    metric_type: jint,
285) -> jlong {
286    let name_str: String = match env.get_string(&name) {
287        Ok(s) => s.into(),
288        Err(_) => return 0,
289    };
290    
291    let metric_type_enum = match metric_type {
292        0 => RiMetricType::Counter,
293        1 => RiMetricType::Gauge,
294        2 => RiMetricType::Histogram,
295        3 => RiMetricType::Summary,
296        _ => RiMetricType::Counter,
297    };
298    
299    let config = Box::new(RiMetricConfig {
300        metric_type: metric_type_enum,
301        name: name_str,
302        help: String::new(),
303        buckets: vec![0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0],
304        quantiles: vec![0.5, 0.9, 0.95, 0.99],
305        max_age: std::time::Duration::from_secs(600),
306        age_buckets: 5,
307    });
308    
309    Box::into_raw(config) as jlong
310}
311
312#[no_mangle]
313pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricConfig_setHelp0(
314    mut env: JNIEnv,
315    _class: JClass,
316    ptr: jlong,
317    help: JString,
318) {
319    if ptr == 0 {
320        return;
321    }
322    
323    let help_str: String = match env.get_string(&help) {
324        Ok(s) => s.into(),
325        Err(_) => return,
326    };
327    
328    let config = unsafe { &mut *(ptr as *mut RiMetricConfig) };
329    config.help = help_str;
330}
331
332#[no_mangle]
333pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricConfig_setBuckets0(
334    _env: JNIEnv,
335    _class: JClass,
336    ptr: jlong,
337    buckets: JDoubleArray,
338) {
339    if ptr == 0 {
340        return;
341    }
342    
343    let buckets_vec: Vec<f64> = match _env.get_double_array_elements(&buckets, jni::objects::ReleaseMode::CopyBack) {
344        Ok(elems) => elems.iter().map(|&x| x).collect(),
345        Err(_) => return,
346    };
347    
348    let config = unsafe { &mut *(ptr as *mut RiMetricConfig) };
349    config.buckets = buckets_vec;
350}
351
352#[no_mangle]
353pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricConfig_setQuantiles0(
354    _env: JNIEnv,
355    _class: JClass,
356    ptr: jlong,
357    quantiles: JDoubleArray,
358) {
359    if ptr == 0 {
360        return;
361    }
362    
363    let quantiles_vec: Vec<f64> = match _env.get_double_array_elements(&quantiles, jni::objects::ReleaseMode::CopyBack) {
364        Ok(elems) => elems.iter().map(|&x| x).collect(),
365        Err(_) => return,
366    };
367    
368    let config = unsafe { &mut *(ptr as *mut RiMetricConfig) };
369    config.quantiles = quantiles_vec;
370}
371
372#[no_mangle]
373pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricConfig_free0(
374    _env: JNIEnv,
375    _class: JClass,
376    ptr: jlong,
377) {
378    if ptr != 0 {
379        unsafe {
380            let _ = Box::from_raw(ptr as *mut RiMetricConfig);
381        }
382    }
383}
384
385// RiMetric JNI bindings
386#[no_mangle]
387pub extern "system" fn Java_com_dunimd_ri_observability_RiMetric_new0(
388    _env: JNIEnv,
389    _class: JClass,
390    config_ptr: jlong,
391) -> jlong {
392    if config_ptr == 0 {
393        return 0;
394    }
395    
396    let config = unsafe { &*(config_ptr as *const RiMetricConfig) };
397    let metric = Box::new(RiMetric::new(config.clone()));
398    Box::into_raw(metric) as jlong
399}
400
401#[no_mangle]
402pub extern "system" fn Java_com_dunimd_ri_observability_RiMetric_record0(
403    _env: JNIEnv,
404    _class: JClass,
405    ptr: jlong,
406    value: jdouble,
407) {
408    if ptr == 0 {
409        return;
410    }
411    
412    let metric = unsafe { &*(ptr as *const RiMetric) };
413    let _ = metric.record(value, vec![]);
414}
415
416#[no_mangle]
417pub extern "system" fn Java_com_dunimd_ri_observability_RiMetric_getValue0(
418    _env: JNIEnv,
419    _class: JClass,
420    ptr: jlong,
421) -> jdouble {
422    if ptr == 0 {
423        return 0.0;
424    }
425    
426    let metric = unsafe { &*(ptr as *const RiMetric) };
427    metric.get_value()
428}
429
430#[no_mangle]
431pub extern "system" fn Java_com_dunimd_ri_observability_RiMetric_getTotalCount0(
432    _env: JNIEnv,
433    _class: JClass,
434    ptr: jlong,
435) -> jlong {
436    if ptr == 0 {
437        return 0;
438    }
439    
440    let metric = unsafe { &*(ptr as *const RiMetric) };
441    metric.get_total_count() as jlong
442}
443
444#[no_mangle]
445pub extern "system" fn Java_com_dunimd_ri_observability_RiMetric_free0(
446    _env: JNIEnv,
447    _class: JClass,
448    ptr: jlong,
449) {
450    if ptr != 0 {
451        unsafe {
452            let _ = Box::from_raw(ptr as *mut RiMetric);
453        }
454    }
455}
456
457// RiMetricsRegistry JNI bindings
458#[no_mangle]
459pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricsRegistry_new0(
460    _env: JNIEnv,
461    _class: JClass,
462) -> jlong {
463    let registry = Box::new(RiMetricsRegistry::new());
464    Box::into_raw(registry) as jlong
465}
466
467#[no_mangle]
468pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricsRegistry_register0(
469    _env: JNIEnv,
470    _class: JClass,
471    ptr: jlong,
472    metric_ptr: jlong,
473) {
474    if ptr == 0 || metric_ptr == 0 {
475        return;
476    }
477    
478    let registry = unsafe { &*(ptr as *const RiMetricsRegistry) };
479    let metric = unsafe { &*(metric_ptr as *const RiMetric) };
480    let _ = registry.register(std::sync::Arc::new(RiMetric::new(metric.get_config().clone())));
481}
482
483#[no_mangle]
484pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricsRegistry_get0(
485    mut env: JNIEnv,
486    _class: JClass,
487    ptr: jlong,
488    name: JString,
489) -> jlong {
490    if ptr == 0 {
491        return 0;
492    }
493    
494    let registry = unsafe { &*(ptr as *const RiMetricsRegistry) };
495    let name_str: String = match env.get_string(&name) {
496        Ok(s) => s.into(),
497        Err(_) => return 0,
498    };
499    
500    match registry.get_metric(&name_str) {
501        Some(metric) => {
502            let metric_box = Box::new(RiMetric::new(metric.get_config().clone()));
503            Box::into_raw(metric_box) as jlong
504        }
505        None => 0,
506    }
507}
508
509#[no_mangle]
510pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricsRegistry_getMetricValue0(
511    mut env: JNIEnv,
512    _class: JClass,
513    ptr: jlong,
514    name: JString,
515) -> jdouble {
516    if ptr == 0 {
517        return 0.0;
518    }
519    
520    let registry = unsafe { &*(ptr as *const RiMetricsRegistry) };
521    let name_str: String = match env.get_string(&name) {
522        Ok(s) => s.into(),
523        Err(_) => return 0.0,
524    };
525    
526    match registry.get_metric(&name_str) {
527        Some(metric) => metric.get_value(),
528        None => 0.0,
529    }
530}
531
532#[no_mangle]
533pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricsRegistry_getAllMetricNames0(
534    mut env: JNIEnv,
535    _class: JClass,
536    ptr: jlong,
537) -> jobjectArray {
538    if ptr == 0 {
539        return std::ptr::null_mut();
540    }
541    
542    let registry = unsafe { &*(ptr as *const RiMetricsRegistry) };
543    let names: Vec<String> = registry.get_all_metrics().keys().cloned().collect();
544    
545    let array = match env.new_object_array(names.len() as jint, "java/lang/String", JObject::null()) {
546        Ok(arr) => arr,
547        Err(_) => return std::ptr::null_mut(),
548    };
549    
550    for (i, name) in names.iter().enumerate() {
551        if let Ok(jstr) = env.new_string(name) {
552            let _ = env.set_object_array_element(&array, i as jint, jstr);
553        }
554    }
555    
556    array.into_raw()
557}
558
559#[no_mangle]
560pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricsRegistry_exportPrometheus0(
561    _env: JNIEnv,
562    _class: JClass,
563    ptr: jlong,
564) -> jstring {
565    if ptr == 0 {
566        return std::ptr::null_mut();
567    }
568    
569    let registry = unsafe { &*(ptr as *const RiMetricsRegistry) };
570    let output = registry.export_prometheus();
571    
572    match _env.new_string(&output) {
573        Ok(s) => s.into_raw(),
574        Err(_) => std::ptr::null_mut(),
575    }
576}
577
578#[no_mangle]
579pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricsRegistry_getMetricCount0(
580    _env: JNIEnv,
581    _class: JClass,
582    ptr: jlong,
583) -> jint {
584    if ptr == 0 {
585        return 0;
586    }
587    
588    let registry = unsafe { &*(ptr as *const RiMetricsRegistry) };
589    registry.get_all_metrics().len() as jint
590}
591
592#[no_mangle]
593pub extern "system" fn Java_com_dunimd_ri_observability_RiMetricsRegistry_free0(
594    _env: JNIEnv,
595    _class: JClass,
596    ptr: jlong,
597) {
598    if ptr != 0 {
599        unsafe {
600            let _ = Box::from_raw(ptr as *mut RiMetricsRegistry);
601        }
602    }
603}
604
605// RiSystemMetricsCollector JNI bindings (only available with system_info feature)
606#[cfg(feature = "system_info")]
607#[no_mangle]
608pub extern "system" fn Java_com_dunimd_ri_observability_RiSystemMetricsCollector_new0(
609    _env: JNIEnv,
610    _class: JClass,
611) -> jlong {
612    let collector = Box::new(RiSystemMetricsCollector::new());
613    Box::into_raw(collector) as jlong
614}
615
616#[cfg(feature = "system_info")]
617#[no_mangle]
618pub extern "system" fn Java_com_dunimd_ri_observability_RiSystemMetricsCollector_collect0(
619    mut env: JNIEnv,
620    _class: JClass,
621    ptr: jlong,
622) -> jobject {
623    if ptr == 0 {
624        return JObject::null().into_raw();
625    }
626    
627    let collector = unsafe { &mut *(ptr as *mut RiSystemMetricsCollector) };
628    let metrics = collector.collect();
629    
630    create_system_metrics_object(&mut env, &metrics)
631}
632
633#[cfg(feature = "system_info")]
634fn create_system_metrics_object(env: &mut JNIEnv, metrics: &RiSystemMetrics) -> jobject {
635    let cpu_obj = create_cpu_metrics_object(env, &metrics.cpu);
636    let memory_obj = create_memory_metrics_object(env, &metrics.memory);
637    let disk_obj = create_disk_metrics_object(env, &metrics.disk);
638    let network_obj = create_network_metrics_object(env, &metrics.network);
639    
640    let cpu_jobj = match cpu_obj {
641        Ok(obj) => obj,
642        Err(_) => return JObject::null().into_raw(),
643    };
644    let memory_jobj = match memory_obj {
645        Ok(obj) => obj,
646        Err(_) => return JObject::null().into_raw(),
647    };
648    let disk_jobj = match disk_obj {
649        Ok(obj) => obj,
650        Err(_) => return JObject::null().into_raw(),
651    };
652    let network_jobj = match network_obj {
653        Ok(obj) => obj,
654        Err(_) => return JObject::null().into_raw(),
655    };
656    
657    match env.new_object(
658        "com/dunimd/ri/observability/RiSystemMetrics",
659        "(Lcom/dunimd/ri/observability/RiCPUMetrics;Lcom/dunimd/ri/observability/RiMemoryMetrics;Lcom/dunimd/ri/observability/RiDiskMetrics;Lcom/dunimd/ri/observability/RiNetworkMetrics;J)V",
660        &[cpu_jobj.into(), memory_jobj.into(), disk_jobj.into(), network_jobj.into(), metrics.timestamp.into()],
661    ) {
662        Ok(obj) => obj.into_raw(),
663        Err(_) => JObject::null().into_raw(),
664    }
665}
666
667#[cfg(feature = "system_info")]
668fn create_cpu_metrics_object<'a>(env: &'a mut JNIEnv<'a>, cpu: &RiCPUMetrics) -> jni::errors::Result<JObject<'a>> {
669    let per_core_array = env.new_double_array(cpu.per_core_usage.len() as jint)?;
670    env.set_double_array_region(&per_core_array, 0, &cpu.per_core_usage)?;
671    
672    env.new_object(
673        "com/dunimd/ri/observability/RiCPUMetrics",
674        "(D[DJJ)V",
675        &[cpu.total_usage_percent.into(), per_core_array.into(), cpu.context_switches.into(), cpu.interrupts.into()],
676    )
677}
678
679#[cfg(feature = "system_info")]
680fn create_memory_metrics_object<'a>(env: &'a mut JNIEnv<'a>, memory: &RiMemoryMetrics) -> jni::errors::Result<JObject<'a>> {
681    env.new_object(
682        "com/dunimd/ri/observability/RiMemoryMetrics",
683        "(JJJDJJDD)V",
684        &[
685            memory.total_bytes.into(),
686            memory.used_bytes.into(),
687            memory.free_bytes.into(),
688            memory.usage_percent.into(),
689            memory.swap_total_bytes.into(),
690            memory.swap_used_bytes.into(),
691            memory.swap_free_bytes.into(),
692            memory.swap_usage_percent.into(),
693        ],
694    )
695}
696
697#[cfg(feature = "system_info")]
698fn create_disk_metrics_object<'a>(env: &'a mut JNIEnv<'a>, disk: &RiDiskMetrics) -> jni::errors::Result<JObject<'a>> {
699    env.new_object(
700        "com/dunimd/ri/observability/RiDiskMetrics",
701        "(JJJDJJJJ)V",
702        &[
703            disk.total_bytes.into(),
704            disk.used_bytes.into(),
705            disk.free_bytes.into(),
706            disk.usage_percent.into(),
707            disk.read_bytes.into(),
708            disk.write_bytes.into(),
709            disk.read_count.into(),
710            disk.write_count.into(),
711        ],
712    )
713}
714
715#[cfg(feature = "system_info")]
716fn create_network_metrics_object<'a>(env: &'a mut JNIEnv<'a>, network: &RiNetworkMetrics) -> jni::errors::Result<JObject<'a>> {
717    env.new_object(
718        "com/dunimd/ri/observability/RiNetworkMetrics",
719        "(JJJJJJJJ)V",
720        &[
721            network.total_received_bytes.into(),
722            network.total_transmitted_bytes.into(),
723            network.received_bytes_per_sec.into(),
724            network.transmitted_bytes_per_sec.into(),
725            network.total_received_packets.into(),
726            network.total_transmitted_packets.into(),
727            network.received_packets_per_sec.into(),
728            network.transmitted_packets_per_sec.into(),
729        ],
730    )
731}
732
733#[cfg(feature = "system_info")]
734#[no_mangle]
735pub extern "system" fn Java_com_dunimd_ri_observability_RiSystemMetricsCollector_refresh0(
736    _env: JNIEnv,
737    _class: JClass,
738    ptr: jlong,
739) {
740    if ptr == 0 {
741        return;
742    }
743    
744    let collector = unsafe { &mut *(ptr as *mut RiSystemMetricsCollector) };
745    collector.system.refresh_all();
746}
747
748#[cfg(feature = "system_info")]
749#[no_mangle]
750pub extern "system" fn Java_com_dunimd_ri_observability_RiSystemMetricsCollector_free0(
751    _env: JNIEnv,
752    _class: JClass,
753    ptr: jlong,
754) {
755    if ptr != 0 {
756        unsafe {
757            let _ = Box::from_raw(ptr as *mut RiSystemMetricsCollector);
758        }
759    }
760}
761
762// Stub implementations when system_info feature is not enabled
763#[cfg(not(feature = "system_info"))]
764#[no_mangle]
765pub extern "system" fn Java_com_dunimd_ri_observability_RiSystemMetricsCollector_new0(
766    _env: JNIEnv,
767    _class: JClass,
768) -> jlong {
769    0
770}
771
772#[cfg(not(feature = "system_info"))]
773#[no_mangle]
774pub extern "system" fn Java_com_dunimd_ri_observability_RiSystemMetricsCollector_collect0(
775    _env: JNIEnv,
776    _class: JClass,
777    _ptr: jlong,
778) -> jobject {
779    JObject::null().into_raw()
780}
781
782#[cfg(not(feature = "system_info"))]
783#[no_mangle]
784pub extern "system" fn Java_com_dunimd_ri_observability_RiSystemMetricsCollector_refresh0(
785    _env: JNIEnv,
786    _class: JClass,
787    _ptr: jlong,
788) {
789}
790
791#[cfg(not(feature = "system_info"))]
792#[no_mangle]
793pub extern "system" fn Java_com_dunimd_ri_observability_RiSystemMetricsCollector_free0(
794    _env: JNIEnv,
795    _class: JClass,
796    _ptr: jlong,
797) {
798}