Skip to content

Commit

Permalink
feat(js): Parse debug ids from scraped source files (#1534)
Browse files Browse the repository at this point in the history
  • Loading branch information
timfish authored Oct 21, 2024
1 parent 3cfaf3c commit 6f6cf85
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- Added `dry-run` mode to the `cleanup` command that simulates the cleanup
without deleting files. ([#1531](https://github.com/getsentry/symbolicator/pull/1531))
- Parse debug identifiers from scraped JavaScript source files
([#1534](https://github.com/getsentry/symbolicator/pull/1534))

### Dependencies

Expand Down
23 changes: 18 additions & 5 deletions crates/symbolicator-js/src/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use reqwest::Url;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use symbolic::common::{ByteView, DebugId, SelfCell};
use symbolic::debuginfo::js::discover_sourcemaps_location;
use symbolic::debuginfo::js::{discover_debug_id, discover_sourcemaps_location};
use symbolic::debuginfo::sourcebundle::{
SourceBundleDebugSession, SourceFileDescriptor, SourceFileType,
};
Expand Down Expand Up @@ -447,6 +447,7 @@ impl<T> CachedFileEntry<T> {
pub struct CachedFile {
pub contents: Option<ByteViewString>,
sourcemap_url: Option<Arc<SourceMapUrl>>,
debug_id: Option<DebugId>,
}

impl fmt::Debug for CachedFile {
Expand Down Expand Up @@ -493,6 +494,7 @@ impl CachedFile {
Ok(Self {
contents,
sourcemap_url: sourcemap_url.map(Arc::new),
debug_id: None,
})
}

Expand Down Expand Up @@ -580,12 +582,17 @@ impl ArtifactFetcher {
self.metrics.record_not_found(SourceFileType::Source);
}

// Then fetch the corresponding sourcemap if we have a sourcemap reference
let sourcemap_url = match &minified_source.entry {
Ok(minified_source) => minified_source.sourcemap_url.as_deref(),
Err(_) => None,
// Then fetch the corresponding sourcemap reference and debug_id
let (sourcemap_url, source_debug_id) = match &minified_source.entry {
Ok(minified_source) => (
minified_source.sourcemap_url.as_deref(),
minified_source.debug_id,
),
Err(_) => (None, None),
};

let debug_id = debug_id.or(source_debug_id);

// If we don't have sourcemap reference, nor a `DebugId`, we skip creating `SourceMapCache`.
if sourcemap_url.is_none() && debug_id.is_none() {
self.metrics.record_sourcemap_not_needed();
Expand All @@ -600,6 +607,7 @@ impl ArtifactFetcher {
entry: Ok(CachedFile {
contents: Some(data.clone()),
sourcemap_url: None,
debug_id,
}),
resolved_with: minified_source.resolved_with,
},
Expand Down Expand Up @@ -781,12 +789,15 @@ impl ArtifactFetcher {
.and_then(|sm_ref| SourceMapUrl::parse_with_prefix(abs_path, sm_ref).ok())
.map(Arc::new);

let debug_id = discover_debug_id(&contents);

self.scraping_attempts
.push(JsScrapingAttempt::success(abs_path.to_owned()));

Ok(CachedFile {
contents: Some(contents),
sourcemap_url,
debug_id,
})
}
Err(e) => {
Expand Down Expand Up @@ -931,9 +942,11 @@ impl ArtifactFetcher {

// Get the sourcemap reference from the artifact, either from metadata, or file contents
let sourcemap_url = resolve_sourcemap_url(abs_path, &artifact.headers, &contents);
let debug_id = discover_debug_id(&contents);
CachedFile {
contents: Some(contents),
sourcemap_url: sourcemap_url.map(Arc::new),
debug_id,
}
}),
resolved_with: artifact.resolved_with,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
source: crates/symbolicator-js/tests/integration/sourcemap.rs
assertion_line: 702
expression: response
---
stacktraces:
- frames:
- function: onFailure
filename: test.js
module: files/test
abs_path: "http://localhost:<port>/files/test.js"
lineno: 5
colno: 11
pre_context:
- "var makeAFailure = (function() {"
- " function onSuccess(data) {}"
- ""
- " function onFailure(data) {"
context_line: " throw new Error('failed!');"
post_context:
- " }"
- ""
- " function invoke(data) {"
- " var cb = null;"
- " if (data.failed) {"
data:
sourcemap: "http://localhost:<port>/files/app.js"
sourcemap_origin:
bundled:
- "sentry://project_debug_file/1"
- source_map:
debug_id: 2f259f80-58b7-44cb-d7cd-de1505e7e718
resolved_with: debug-id
symbolicated: true
raw_stacktraces:
- frames:
- abs_path: "http://localhost:<port>/files/app.js"
lineno: 1
colno: 64
context_line: "var makeAFailure=function(){function n(n){}function e(n){throw new Error(\"failed!\")}function r(r){var i=null;if(r.failed){i=e}else{i=n}i(r)} {snip}"
post_context:
- "//# debugId=2f259f80-58b7-44cb-d7cd-de1505e7e718"
data:
symbolicated: false
scraping_attempts:
- url: "http://localhost:<port>/files/app.js"
status: success
31 changes: 31 additions & 0 deletions crates/symbolicator-js/tests/integration/sourcemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,37 @@ async fn e2e_multiple_smref_scraped() {
assert_snapshot!(response);
}

#[tokio::test]
async fn e2e_scraped_debugid() {
let (symbolication, _cache_dir) = setup_service(|_| ());
let (srv, source) = sourcemap_server("e2e_scraped_debugid", |url, query| {
assert_eq!(query, "debug_id=2f259f80-58b7-44cb-d7cd-de1505e7e718");
json!([{
"type": "bundle",
"id": "1",
"url": format!("{url}/bundle.zip"),
"resolved_with": "debug-id",
}])
});

let url = srv.url("/files/");
let frames = format!(
r#"[{{
"abs_path": "{url}app.js",
"lineno": 1,
"colno": 64
}}]"#
);
let modules = r#"[]"#;

let mut request = make_js_request(source, &frames, modules, None, None);
request.scraping.enabled = true;

let response = symbolication.symbolicate_js(request).await;

assert_snapshot!(response);
}

#[tokio::test]
async fn sorted_bundles() {
let (symbolication, _cache_dir) = setup_service(|_| ());
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/sourcemaps/e2e_scraped_debugid/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var makeAFailure=function(){function n(n){}function e(n){throw new Error("failed!")}function r(r){var i=null;if(r.failed){i=e}else{i=n}i(r)}function i(){var n={failed:true,value:42};r(n)}return i}();
//# debugId=2f259f80-58b7-44cb-d7cd-de1505e7e718
Binary file not shown.

0 comments on commit 6f6cf85

Please sign in to comment.