Skip to content

Commit 4e899d4

Browse files
authored
fix: otel resiliency (#26857)
Improving the breadth of collected data, and ensuring that the collected data is more likely to be successfully reported. - Use `log` crate in more places - Hook up `log` crate to otel - Switch to process-wide otel processors - Handle places that use `process::exit` Also adds a more robust testing framework, with a deterministic tracing setting. Refs: #26852
1 parent cb107a7 commit 4e899d4

37 files changed

+411
-175
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ jsonc-parser = { version = "=0.26.2", features = ["serde"] }
141141
lazy-regex = "3"
142142
libc = "0.2.126"
143143
libz-sys = { version = "1.1.20", default-features = false }
144-
log = "0.4.20"
144+
log = { version = "0.4.20", features = ["kv"] }
145145
lsp-types = "=0.97.0" # used by tower-lsp and "proposed" feature is unstable in patch releases
146146
memmem = "0.1.1"
147147
monch = "=0.5.0"

cli/args/flags.rs

+19
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use deno_path_util::normalize_path;
3636
use deno_path_util::url_to_file_path;
3737
use deno_runtime::deno_permissions::PermissionsOptions;
3838
use deno_runtime::deno_permissions::SysDescriptor;
39+
use deno_runtime::ops::otel::OtelConfig;
3940
use log::debug;
4041
use log::Level;
4142
use serde::Deserialize;
@@ -967,6 +968,24 @@ impl Flags {
967968
args
968969
}
969970

971+
pub fn otel_config(&self) -> Option<OtelConfig> {
972+
if self
973+
.unstable_config
974+
.features
975+
.contains(&String::from("otel"))
976+
{
977+
Some(OtelConfig {
978+
runtime_name: Cow::Borrowed("deno"),
979+
runtime_version: Cow::Borrowed(crate::version::DENO_VERSION_INFO.deno),
980+
deterministic: std::env::var("DENO_UNSTABLE_OTEL_DETERMINISTIC")
981+
.is_ok(),
982+
..Default::default()
983+
})
984+
} else {
985+
None
986+
}
987+
}
988+
970989
/// Extract the paths the config file should be discovered from.
971990
///
972991
/// Returns `None` if the config file should not be auto-discovered.

cli/args/mod.rs

+2-17
Original file line numberDiff line numberDiff line change
@@ -823,10 +823,8 @@ impl CliOptions {
823823
};
824824
let msg =
825825
format!("DANGER: TLS certificate validation is disabled {}", domains);
826-
#[allow(clippy::print_stderr)]
827826
{
828-
// use eprintln instead of log::warn so this always gets shown
829-
eprintln!("{}", colors::yellow(msg));
827+
log::error!("{}", colors::yellow(msg));
830828
}
831829
}
832830

@@ -1131,20 +1129,7 @@ impl CliOptions {
11311129
}
11321130

11331131
pub fn otel_config(&self) -> Option<OtelConfig> {
1134-
if self
1135-
.flags
1136-
.unstable_config
1137-
.features
1138-
.contains(&String::from("otel"))
1139-
{
1140-
Some(OtelConfig {
1141-
runtime_name: Cow::Borrowed("deno"),
1142-
runtime_version: Cow::Borrowed(crate::version::DENO_VERSION_INFO.deno),
1143-
..Default::default()
1144-
})
1145-
} else {
1146-
None
1147-
}
1132+
self.flags.otel_config()
11481133
}
11491134

11501135
pub fn env_file_name(&self) -> Option<&String> {

cli/clippy.toml

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
disallowed-methods = [
22
{ path = "reqwest::Client::new", reason = "create an HttpClient via an HttpClientProvider instead" },
3+
{ path = "std::process::exit", reason = "use deno_runtime::exit instead" },
34
]
45
disallowed-types = [
56
{ path = "reqwest::Client", reason = "use crate::http_util::HttpClient instead" },

cli/graph_util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ pub fn graph_exit_integrity_errors(graph: &ModuleGraph) {
188188
fn exit_for_integrity_error(err: &ModuleError) {
189189
if let Some(err_message) = enhanced_integrity_error_message(err) {
190190
log::error!("{} {}", colors::red("error:"), err_message);
191-
std::process::exit(10);
191+
deno_runtime::exit(10);
192192
}
193193
}
194194

cli/lsp/parent_process_checker.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub fn start(parent_process_id: u32) {
1111
std::thread::sleep(Duration::from_secs(10));
1212

1313
if !is_process_active(parent_process_id) {
14-
std::process::exit(1);
14+
deno_runtime::exit(1);
1515
}
1616
});
1717
}

cli/main.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -350,18 +350,17 @@ fn setup_panic_hook() {
350350
eprintln!("Args: {:?}", env::args().collect::<Vec<_>>());
351351
eprintln!();
352352
orig_hook(panic_info);
353-
std::process::exit(1);
353+
deno_runtime::exit(1);
354354
}));
355355
}
356356

357-
#[allow(clippy::print_stderr)]
358357
fn exit_with_message(message: &str, code: i32) -> ! {
359-
eprintln!(
358+
log::error!(
360359
"{}: {}",
361360
colors::red_bold("error"),
362361
message.trim_start_matches("error: ")
363362
);
364-
std::process::exit(code);
363+
deno_runtime::exit(code);
365364
}
366365

367366
fn exit_for_error(error: AnyError) -> ! {
@@ -380,13 +379,12 @@ fn exit_for_error(error: AnyError) -> ! {
380379
exit_with_message(&error_string, error_code);
381380
}
382381

383-
#[allow(clippy::print_stderr)]
384382
pub(crate) fn unstable_exit_cb(feature: &str, api_name: &str) {
385-
eprintln!(
383+
log::error!(
386384
"Unstable API '{api_name}'. The `--unstable-{}` flag must be provided.",
387385
feature
388386
);
389-
std::process::exit(70);
387+
deno_runtime::exit(70);
390388
}
391389

392390
pub fn main() {
@@ -419,7 +417,7 @@ pub fn main() {
419417
drop(profiler);
420418

421419
match result {
422-
Ok(exit_code) => std::process::exit(exit_code),
420+
Ok(exit_code) => deno_runtime::exit(exit_code),
423421
Err(err) => exit_for_error(err),
424422
}
425423
}
@@ -433,12 +431,21 @@ fn resolve_flags_and_init(
433431
if err.kind() == clap::error::ErrorKind::DisplayVersion =>
434432
{
435433
// Ignore results to avoid BrokenPipe errors.
434+
util::logger::init(None);
436435
let _ = err.print();
437-
std::process::exit(0);
436+
deno_runtime::exit(0);
437+
}
438+
Err(err) => {
439+
util::logger::init(None);
440+
exit_for_error(AnyError::from(err))
438441
}
439-
Err(err) => exit_for_error(AnyError::from(err)),
440442
};
441443

444+
if let Some(otel_config) = flags.otel_config() {
445+
deno_runtime::ops::otel::init(otel_config)?;
446+
}
447+
util::logger::init(flags.log_level);
448+
442449
// TODO(bartlomieju): remove in Deno v2.5 and hard error then.
443450
if flags.unstable_config.legacy_flag_enabled {
444451
log::warn!(
@@ -467,7 +474,6 @@ fn resolve_flags_and_init(
467474
deno_core::JsRuntime::init_platform(
468475
None, /* import assertions enabled */ false,
469476
);
470-
util::logger::init(flags.log_level);
471477

472478
Ok(flags)
473479
}

cli/mainrt.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,21 @@ use std::env::current_exe;
4040

4141
use crate::args::Flags;
4242

43-
#[allow(clippy::print_stderr)]
4443
pub(crate) fn unstable_exit_cb(feature: &str, api_name: &str) {
45-
eprintln!(
44+
log::error!(
4645
"Unstable API '{api_name}'. The `--unstable-{}` flag must be provided.",
4746
feature
4847
);
49-
std::process::exit(70);
48+
deno_runtime::exit(70);
5049
}
5150

52-
#[allow(clippy::print_stderr)]
5351
fn exit_with_message(message: &str, code: i32) -> ! {
54-
eprintln!(
52+
log::error!(
5553
"{}: {}",
5654
colors::red_bold("error"),
5755
message.trim_start_matches("error: ")
5856
);
59-
std::process::exit(code);
57+
deno_runtime::exit(code);
6058
}
6159

6260
fn unwrap_or_exit<T>(result: Result<T, AnyError>) -> T {
@@ -89,13 +87,19 @@ fn main() {
8987
let future = async move {
9088
match standalone {
9189
Ok(Some(data)) => {
90+
if let Some(otel_config) = data.metadata.otel_config.clone() {
91+
deno_runtime::ops::otel::init(otel_config)?;
92+
}
9293
util::logger::init(data.metadata.log_level);
9394
load_env_vars(&data.metadata.env_vars_from_env_file);
9495
let exit_code = standalone::run(data).await?;
95-
std::process::exit(exit_code);
96+
deno_runtime::exit(exit_code);
9697
}
9798
Ok(None) => Ok(()),
98-
Err(err) => Err(err),
99+
Err(err) => {
100+
util::logger::init(None);
101+
Err(err)
102+
}
99103
}
100104
};
101105

cli/standalone/binary.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
517517
Some(bytes) => bytes,
518518
None => {
519519
log::info!("Download could not be found, aborting");
520-
std::process::exit(1)
520+
deno_runtime::exit(1);
521521
}
522522
};
523523

cli/tools/lint/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ pub async fn lint(
191191
linter.finish()
192192
};
193193
if !success {
194-
std::process::exit(1);
194+
deno_runtime::exit(1);
195195
}
196196
}
197197

cli/tools/test/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,7 @@ pub async fn report_tests(
13571357
if let Err(err) = reporter.flush_report(&elapsed, &tests, &test_steps) {
13581358
eprint!("Test reporter failed to flush: {}", err)
13591359
}
1360+
#[allow(clippy::disallowed_methods)]
13601361
std::process::exit(130);
13611362
}
13621363
}
@@ -1642,6 +1643,7 @@ pub async fn run_tests_with_watch(
16421643
loop {
16431644
signal::ctrl_c().await.unwrap();
16441645
if !HAS_TEST_RUN_SIGINT_HANDLER.load(Ordering::Relaxed) {
1646+
#[allow(clippy::disallowed_methods)]
16451647
std::process::exit(130);
16461648
}
16471649
}

cli/tools/upgrade.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ pub async fn upgrade(
540540
let Some(archive_data) = download_package(&client, download_url).await?
541541
else {
542542
log::error!("Download could not be found, aborting");
543-
std::process::exit(1)
543+
deno_runtime::exit(1)
544544
};
545545

546546
log::info!(

cli/util/file_watcher.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ impl DebouncedReceiver {
7373
}
7474
}
7575

76-
#[allow(clippy::print_stderr)]
7776
async fn error_handler<F>(watch_future: F) -> bool
7877
where
7978
F: Future<Output = Result<(), AnyError>>,
@@ -84,7 +83,7 @@ where
8483
Some(e) => format_js_error(e),
8584
None => format!("{err:?}"),
8685
};
87-
eprintln!(
86+
log::error!(
8887
"{}: {}",
8988
colors::red_bold("error"),
9089
error_string.trim_start_matches("error: ")

cli/util/logger.rs

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ impl log::Log for CliLogger {
2929
// thread's state
3030
DrawThread::hide();
3131
self.0.log(record);
32+
deno_runtime::ops::otel::handle_log(record);
3233
DrawThread::show();
3334
}
3435
}

cli/util/v8.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,14 @@ pub fn init_v8_flags(
4646
.skip(1)
4747
.collect::<Vec<_>>();
4848

49-
#[allow(clippy::print_stderr)]
5049
if !unrecognized_v8_flags.is_empty() {
5150
for f in unrecognized_v8_flags {
52-
eprintln!("error: V8 did not recognize flag '{f}'");
51+
log::error!("error: V8 did not recognize flag '{f}'");
5352
}
54-
eprintln!("\nFor a list of V8 flags, use '--v8-flags=--help'");
55-
std::process::exit(1);
53+
log::error!("\nFor a list of V8 flags, use '--v8-flags=--help'");
54+
deno_runtime::exit(1);
5655
}
5756
if v8_flags_includes_help {
58-
std::process::exit(0);
57+
deno_runtime::exit(0);
5958
}
6059
}

ext/napi/node_api.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ fn napi_fatal_exception(env: &mut Env, err: napi_value) -> napi_status {
140140
}
141141

142142
#[napi_sym]
143-
#[allow(clippy::print_stderr)]
144143
fn napi_fatal_error(
145144
location: *const c_char,
146145
location_len: usize,
@@ -173,9 +172,9 @@ fn napi_fatal_error(
173172
};
174173

175174
if let Some(location) = location {
176-
eprintln!("NODE API FATAL ERROR: {} {}", location, message);
175+
log::error!("NODE API FATAL ERROR: {} {}", location, message);
177176
} else {
178-
eprintln!("NODE API FATAL ERROR: {}", message);
177+
log::error!("NODE API FATAL ERROR: {}", message);
179178
}
180179

181180
std::process::abort();

ext/napi/uv.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ use deno_core::parking_lot::Mutex;
55
use std::mem::MaybeUninit;
66
use std::ptr::addr_of_mut;
77

8-
#[allow(clippy::print_stderr)]
98
fn assert_ok(res: c_int) -> c_int {
109
if res != 0 {
11-
eprintln!("bad result in uv polyfill: {res}");
10+
log::error!("bad result in uv polyfill: {res}");
1211
// don't panic because that might unwind into
1312
// c/c++
1413
std::process::abort();

runtime/clippy.toml

+1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ disallowed-methods = [
4242
{ path = "std::fs::write", reason = "File system operations should be done using FileSystem trait" },
4343
{ path = "std::path::Path::canonicalize", reason = "File system operations should be done using FileSystem trait" },
4444
{ path = "std::path::Path::exists", reason = "File system operations should be done using FileSystem trait" },
45+
{ path = "std::process::exit", reason = "use deno_runtime::exit instead" },
4546
]

0 commit comments

Comments
 (0)