Skip to content

Commit d6f822f

Browse files
committed
add more diagonstics and debug info
Signed-off-by: Andrei Gherghescu <[email protected]>
1 parent 240c8fe commit d6f822f

File tree

4 files changed

+444
-104
lines changed

4 files changed

+444
-104
lines changed

.github/workflows/ci.yml

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,19 @@ jobs:
3333
runs-on: ubuntu-latest
3434
steps:
3535
- uses: actions/checkout@v4
36+
- name: Setup Chrome
37+
uses: browser-actions/setup-chrome@v1
38+
with:
39+
chrome-version: 'latest'
40+
install-chromedriver: true
3641
- uses: dtolnay/rust-toolchain@stable
3742
with:
3843
components: clippy
3944
targets: wasm32-unknown-unknown
4045
# lint the main library workspace for non-wasm target
41-
- run: cargo clippy --all-features -- -D warnings
46+
- run: cargo clippy --features all -- -D warnings -A deprecated
4247
# lint the non-wasm examples
43-
- run: cd ${{ github.workspace }}/examples && cargo clippy --workspace --exclude "wasm*" -- -D warnings
48+
- run: cd ${{ github.workspace }}/examples && cargo clippy --workspace --exclude "wasm*" --exclude "kaleido" -- -D warnings
4449
# lint the plotly library for wasm target
4550
- run: cargo clippy --package plotly --target wasm32-unknown-unknown -- -D warnings
4651
# lint the wasm examples
@@ -68,9 +73,14 @@ jobs:
6873
os: [ubuntu-latest, windows-latest, macos-latest]
6974
runs-on: ${{ matrix.os }}
7075
steps:
76+
- name: Setup Chrome
77+
uses: browser-actions/setup-chrome@v1
78+
with:
79+
chrome-version: 'latest'
80+
install-chromedriver: true
7181
- uses: actions/checkout@v4
7282
- uses: dtolnay/rust-toolchain@stable
73-
- run: cargo test --features plotly_ndarray,plotly_image,kaleido
83+
- run: cargo test --workspace --features plotly_ndarray,plotly_image,static_export_default --exclude plotly_kaleido
7484
- if: ${{ matrix.os == 'windows-latest' }}
7585
run: gci -recurse -filter "*example*"
7686

@@ -103,12 +113,21 @@ jobs:
103113
ndarray,
104114
scientific_charts,
105115
shapes,
116+
static_export,
106117
subplots,
107118
themes,
108119
]
109120
runs-on: ubuntu-latest
110121
steps:
111122
- uses: actions/checkout@v4
123+
124+
- name: Setup Chrome (for static_export)
125+
if: matrix.example == 'static_export'
126+
uses: browser-actions/setup-chrome@v1
127+
with:
128+
chrome-version: 'latest'
129+
install-chromedriver: true
130+
112131
- uses: dtolnay/rust-toolchain@stable
113132
- run: cd ${{ github.workspace }}/examples/${{ matrix.example }} && cargo build
114133

@@ -131,6 +150,13 @@ jobs:
131150
runs-on: ubuntu-latest
132151
steps:
133152
- uses: actions/checkout@v4
153+
154+
- name: Setup Chrome (for static_export)
155+
uses: browser-actions/setup-chrome@v1
156+
with:
157+
chrome-version: 'latest'
158+
install-chromedriver: true
159+
134160
- uses: dtolnay/rust-toolchain@stable
135161
- run: cargo install mdbook --no-default-features --features search --vers "^0.4" --locked --quiet
136162
- name: Build examples to generate needed html files
@@ -143,5 +169,6 @@ jobs:
143169
cd ${{ github.workspace }}/examples/subplots && cargo run
144170
cd ${{ github.workspace }}/examples/shapes && cargo run
145171
cd ${{ github.workspace }}/examples/themes && cargo run
172+
cd ${{ github.workspace }}/examples/static_export && cargo run
146173
- name: Build book
147-
run: mdbook build docs/book
174+
run: mdbook build docs/book

plotly_static/src/lib.rs

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
//!
8383
//! ### Custom Configuration
8484
//!
85-
//! ```rust
85+
//! ```no_run
8686
//! use plotly_static::StaticExporterBuilder;
8787
//!
8888
//! let exporter = StaticExporterBuilder::default()
@@ -132,7 +132,7 @@
132132
//! The library supports logging via the `log` crate. Enable it with
133133
//! `env_logger`:
134134
//!
135-
//! ```rust
135+
//! ```no_run
136136
//! use plotly_static::StaticExporterBuilder;
137137
//!
138138
//! // Initialize logging (typically done once at the start of your application)
@@ -150,7 +150,7 @@
150150
//!
151151
//! The library is designed to work safely in parallel environments:
152152
//!
153-
//! ```rust
153+
//! ```no_run
154154
//! use plotly_static::{StaticExporterBuilder, ImageFormat};
155155
//! use std::sync::atomic::{AtomicU32, Ordering};
156156
//!
@@ -256,25 +256,44 @@ use fantoccini::{wd::Capabilities, ClientBuilder};
256256
use log::{debug, error, warn};
257257
use serde::Serialize;
258258
use serde_json::map::Map as JsonMap;
259-
use tokio::runtime::Runtime;
260259
use urlencoding::encode;
261260
use webdriver::WebDriver;
262261

263262
use crate::template::{IMAGE_EXPORT_JS_SCRIPT, PDF_EXPORT_JS_SCRIPT};
264263

265-
const DEFAULT_CAPS_ARRAY: [&str; 12] = [
264+
#[cfg(feature = "chromedriver")]
265+
const CHROME_DEFAULT_CAPS: [&str; 23] = [
266266
"--headless",
267267
"--no-sandbox",
268-
"--disable-gpu",
268+
"--disable-gpu-sandbox",
269269
"--disable-dev-shm-usage",
270270
"--disable-extensions",
271271
"--disable-background-networking",
272272
"--disable-sync",
273273
"--disable-translate",
274-
"--mute-audio",
275-
"--safebrowsing-disable-auto-update",
276-
"--ignore-certificate-errors",
277-
"--log-level=1",
274+
"--disable-background-timer-throttling",
275+
"--disable-renderer-backgrounding",
276+
"--disable-features=VizDisplayCompositor",
277+
"--memory-pressure-off",
278+
// macOS-specific flags from choreographer
279+
"--enable-unsafe-swiftshader",
280+
"--use-mock-keychain",
281+
"--password-store=basic",
282+
"--disable-web-security",
283+
"--disable-breakpad",
284+
"--no-first-run",
285+
"--no-default-browser-check",
286+
// Additional flags for better PDF generation support
287+
"--disable-backgrounding-occluded-windows",
288+
"--disable-ipc-flooding-protection",
289+
"--enable-logging",
290+
"--v=1",
291+
];
292+
293+
#[cfg(feature = "geckodriver")]
294+
const FIREFOX_DEFAULT_CAPS: [&str; 2] = [
295+
"-headless", // Essential for headless operation (single dash for Firefox)
296+
"--no-remote", // Prevents connecting to existing Firefox instances
278297
];
279298

280299
mod template;
@@ -383,7 +402,9 @@ struct PlotData<'a> {
383402
///
384403
/// # Examples
385404
///
386-
/// ```rust
405+
/// ```no_run
406+
/// // This example requires a running WebDriver (chromedriver/geckodriver) and a browser.
407+
/// // It cannot be run as a doc test.
387408
/// use plotly_static::StaticExporterBuilder;
388409
///
389410
/// let exporter = StaticExporterBuilder::default()
@@ -425,7 +446,20 @@ impl Default for StaticExporterBuilder {
425446
webdriver_url: webdriver::WEBDRIVER_URL.to_string(),
426447
spawn_webdriver: true,
427448
offline_mode: false,
428-
webdriver_browser_caps: DEFAULT_CAPS_ARRAY.iter().map(|s| s.to_string()).collect(),
449+
webdriver_browser_caps: {
450+
#[cfg(feature = "chromedriver")]
451+
{
452+
CHROME_DEFAULT_CAPS.iter().map(|s| s.to_string()).collect()
453+
}
454+
#[cfg(feature = "geckodriver")]
455+
{
456+
FIREFOX_DEFAULT_CAPS.iter().map(|s| s.to_string()).collect()
457+
}
458+
#[cfg(not(any(feature = "chromedriver", feature = "geckodriver")))]
459+
{
460+
Vec::new()
461+
}
462+
},
429463
}
430464
}
431465
}
@@ -576,12 +610,20 @@ impl StaticExporterBuilder {
576610
pub fn build(&self) -> Result<StaticExporter> {
577611
let wd = self.create_webdriver()?;
578612

613+
let runtime = std::sync::Arc::new(
614+
tokio::runtime::Builder::new_multi_thread()
615+
.enable_all()
616+
.build()
617+
.expect("Failed to create Tokio runtime"),
618+
);
619+
579620
Ok(StaticExporter {
580621
webdriver_port: self.webdriver_port,
581-
webdriver_url: self.webdriver_url.to_string(),
622+
webdriver_url: self.webdriver_url.clone(),
582623
webdriver: wd,
583624
offline_mode: self.offline_mode,
584625
webdriver_browser_caps: self.webdriver_browser_caps.clone(),
626+
runtime,
585627
})
586628
}
587629

@@ -649,6 +691,7 @@ pub struct StaticExporter {
649691
webdriver: WebDriver,
650692
offline_mode: bool,
651693
webdriver_browser_caps: Vec<String>,
694+
runtime: std::sync::Arc<tokio::runtime::Runtime>,
652695
}
653696

654697
impl Drop for StaticExporter {
@@ -663,8 +706,9 @@ impl Drop for StaticExporter {
663706
/// - Leaves externally managed WebDriver sessions running
664707
/// - Logs errors but doesn't panic if cleanup fails
665708
fn drop(&mut self) {
709+
// Stop the WebDriver process
666710
if let Err(e) = self.webdriver.stop() {
667-
error!("Failed to release WebDriver process: {e}");
711+
error!("Failed to stop WebDriver: {e}");
668712
}
669713
}
670714
}
@@ -835,7 +879,8 @@ impl StaticExporter {
835879

836880
fn static_export(&mut self, plot: &PlotData<'_>) -> Result<String> {
837881
let data_uri = template::html_body(self.offline_mode);
838-
Runtime::new()?
882+
let runtime = self.runtime.clone();
883+
runtime
839884
.block_on(self.extract(&data_uri, plot))
840885
.with_context(|| "Failed to extract static image from browser session")
841886
}
@@ -943,11 +988,9 @@ impl StaticExporter {
943988
// Define browser capabilities
944989
let mut caps = JsonMap::new();
945990
let mut browser_opts = JsonMap::new();
991+
let browser_args = self.webdriver_browser_caps.clone();
946992

947-
browser_opts.insert(
948-
"args".to_string(),
949-
serde_json::json!(self.webdriver_browser_caps.clone()),
950-
);
993+
browser_opts.insert("args".to_string(), serde_json::json!(browser_args));
951994

952995
caps.insert(
953996
"browserName".to_string(),
@@ -962,6 +1005,19 @@ impl StaticExporter {
9621005

9631006
Ok(caps)
9641007
}
1008+
1009+
/// Get diagnostic information about the underlying WebDriver process
1010+
///
1011+
/// This method provides detailed information about the WebDriver process
1012+
/// for debugging purposes, including process status, port information,
1013+
/// and connection details.
1014+
///
1015+
/// # Returns
1016+
///
1017+
/// Returns a string with diagnostic information
1018+
pub fn get_webdriver_diagnostics(&self) -> String {
1019+
self.webdriver.get_diagnostics()
1020+
}
9651021
}
9661022

9671023
#[cfg(test)]

0 commit comments

Comments
 (0)