Skip to content

Commit

Permalink
feat: Introduce platform enums (#1557)
Browse files Browse the repository at this point in the history
These don't do a whole lot yet, but will allow us to
distinguish frames down the line.

This also includes a drive-by refactor of
`symbolicli` to take advantage of this enum
instead of awkwardly rolling its own.
  • Loading branch information
loewenheim authored Nov 27, 2024
1 parent 2d4a77f commit e3793f1
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 74 deletions.
110 changes: 110 additions & 0 deletions crates/symbolicator-service/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,113 @@ impl ObjectFileStatus {
}
}
}

/// Possible values for the platform of a native event.
///
/// This corresponds to `NATIVE_PLATFORMS` in Sentry.
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "lowercase")]
pub enum NativePlatform {
ObjC,
Cocoa,
Swift,
Native,
C,
CSharp,
}

impl fmt::Display for NativePlatform {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
NativePlatform::ObjC => write!(f, "objc"),
NativePlatform::Cocoa => write!(f, "cocoa"),
NativePlatform::Swift => write!(f, "swift"),
NativePlatform::Native => write!(f, "native"),
NativePlatform::C => write!(f, "c"),
NativePlatform::CSharp => write!(f, "csharp"),
}
}
}

/// Possible values for the platform of a JavaScript event.
///
/// This corresponds to the platforms listed in `is_js_event` in Sentry.
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "lowercase")]
pub enum JsPlatform {
Node,
JavaScript,
}

impl fmt::Display for JsPlatform {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
JsPlatform::Node => write!(f, "node"),
JsPlatform::JavaScript => write!(f, "javascript"),
}
}
}

/// Possible values for the platform of a JVM event.
///
/// This corresponds to the platforms listed in `java.processing._handles_frame` in Sentry.
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "lowercase")]
pub enum JvmPlatform {
Java,
}

impl fmt::Display for JvmPlatform {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
JvmPlatform::Java => write!(f, "java"),
}
}
}

/// Possible values for the platform of an event.
///
/// In addition to the native, JS, and JVM cases this also has a catch-all variant for
/// otherwise unrecognized platforms.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
#[serde(untagged)]
pub enum Platform {
Native(NativePlatform),
Js(JsPlatform),
Jvm(JvmPlatform),
Other(String),
}

impl Platform {
/// Returns `true` if this is a native platform.
pub fn is_native(&self) -> bool {
matches!(self, Self::Native(_))
}

/// Returns `true` if this is a JS platform.
pub fn is_js(&self) -> bool {
matches!(self, Self::Js(_))
}

/// Returns `true` if this is a JVM platform.
pub fn is_jvm(&self) -> bool {
matches!(self, Self::Jvm(_))
}
}

impl Default for Platform {
fn default() -> Self {
Self::Other("unknown".to_owned())
}
}

impl fmt::Display for Platform {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Platform::Native(p) => p.fmt(f),
Platform::Js(p) => p.fmt(f),
Platform::Jvm(p) => p.fmt(f),
Platform::Other(p) => p.fmt(f),
}
}
}
142 changes: 68 additions & 74 deletions crates/symbolicli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::io::{Read, Seek};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{fmt, io};

Expand All @@ -10,6 +10,7 @@ use remote::EventKey;
use settings::Mode;
use symbolicator_js::SourceMapService;
use symbolicator_native::SymbolicationActor;
use symbolicator_service::config::Config;
use symbolicator_service::services::SharedServices;
use symbolicator_service::types::Scope;
use symbolicator_sources::{
Expand Down Expand Up @@ -100,7 +101,7 @@ async fn main() -> Result<()> {
};

let res = match payload {
Payload::Event(event) if event.is_js() => {
Payload::Event(event) if event.platform.is_js() => {
let Mode::Online {
ref org,
ref project,
Expand Down Expand Up @@ -128,62 +129,28 @@ async fn main() -> Result<()> {
CompletedResponse::JsSymbolication(js.symbolicate_js(request).await)
}

_ => {
let mut dsym_sources = vec![];
if let Mode::Online {
ref org,
ref project,
ref base_url,
ref auth_token,
..
} = mode
{
let project_source = SourceConfig::Sentry(Arc::new(SentrySourceConfig {
id: SourceId::new("sentry:project"),
token: auth_token.clone(),
url: base_url
.join(&format!("projects/{org}/{project}/files/dsyms/"))
.unwrap(),
}));

dsym_sources.push(project_source);
}

dsym_sources.extend(symbolicator_config.sources.iter().cloned());
if let Some(path) = symbols {
let local_source = FilesystemSourceConfig {
id: SourceId::new("local:cli"),
path,
files: CommonSourceConfig {
filters: Default::default(),
layout: DirectoryLayout {
ty: DirectoryLayoutType::Unified,
casing: Default::default(),
},
is_public: false,
},
};
dsym_sources.push(SourceConfig::Filesystem(local_source.into()));
}
let dsym_sources = Arc::from(dsym_sources.into_boxed_slice());

CompletedResponse::NativeSymbolication(match payload {
Payload::Event(event) => {
let request = create_native_symbolication_request(scope, dsym_sources, event)
.context("Event cannot be symbolicated")?;
Payload::Event(event) if event.platform.is_native() => {
let dsym_sources = prepare_dsym_sources(mode, &symbolicator_config, symbols);
let request = create_native_symbolication_request(scope, dsym_sources, event)
.context("Event cannot be symbolicated")?;

tracing::info!("symbolicating event");
tracing::info!("symbolicating event");

native.symbolicate(request).await?
}
Payload::Minidump(minidump_path) => {
tracing::info!("symbolicating minidump");
native
.process_minidump(scope, minidump_path, dsym_sources, Default::default())
.await?
}
})
let res = native.symbolicate(request).await?;
CompletedResponse::NativeSymbolication(res)
}
Payload::Minidump(minidump_path) => {
let dsym_sources = prepare_dsym_sources(mode, &symbolicator_config, symbols);
tracing::info!("symbolicating minidump");
let res = native
.process_minidump(scope, minidump_path, dsym_sources, Default::default())
.await?;
CompletedResponse::NativeSymbolication(res)
}
Payload::Event(event) => anyhow::bail!(
"Cannot symbolicate event: invalid platform {}",
event.platform
),
};

match output_format {
Expand All @@ -202,6 +169,50 @@ async fn main() -> Result<()> {
Ok(())
}

fn prepare_dsym_sources(
mode: Mode,
symbolicator_config: &Config,
local_symbols: Option<PathBuf>,
) -> Arc<[SourceConfig]> {
let mut dsym_sources = vec![];
if let Mode::Online {
ref org,
ref project,
ref base_url,
ref auth_token,
..
} = mode
{
let project_source = SourceConfig::Sentry(Arc::new(SentrySourceConfig {
id: SourceId::new("sentry:project"),
token: auth_token.clone(),
url: base_url
.join(&format!("projects/{org}/{project}/files/dsyms/"))
.unwrap(),
}));

dsym_sources.push(project_source);
}

dsym_sources.extend(symbolicator_config.sources.iter().cloned());
if let Some(path) = local_symbols {
let local_source = FilesystemSourceConfig {
id: SourceId::new("local:cli"),
path,
files: CommonSourceConfig {
filters: Default::default(),
layout: DirectoryLayout {
ty: DirectoryLayoutType::Unified,
casing: Default::default(),
},
is_public: false,
},
};
dsym_sources.push(SourceConfig::Filesystem(local_source.into()));
}
Arc::from(dsym_sources.into_boxed_slice())
}

#[derive(Debug)]
enum Payload {
Event(event::Event),
Expand Down Expand Up @@ -414,7 +425,7 @@ mod event {
AddrMode, CompleteObjectInfo, FrameTrust, RawFrame, RawStacktrace, Signal,
StacktraceOrigin, SymbolicateStacktraces,
};
use symbolicator_service::types::{RawObjectInfo, Scope, ScrapingConfig};
use symbolicator_service::types::{Platform, RawObjectInfo, Scope, ScrapingConfig};
use symbolicator_service::utils::hex::HexValue;
use symbolicator_sources::{SentrySourceConfig, SourceConfig};

Expand Down Expand Up @@ -548,21 +559,10 @@ mod event {
})
}

#[derive(Debug, Clone, Copy, Deserialize, Default, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
enum Platform {
#[default]
Native,
Javascript,
Node,
Csharp,
Cocoa,
}

#[derive(Debug, Deserialize)]
pub struct Event {
#[serde(default)]
platform: Platform,
pub platform: Platform,
#[serde(default)]
debug_meta: DebugMeta,
exception: Option<Exceptions>,
Expand All @@ -572,12 +572,6 @@ mod event {
dist: Option<String>,
}

impl Event {
pub fn is_js(&self) -> bool {
matches!(self.platform, Platform::Javascript | Platform::Node)
}
}

#[derive(Debug, Deserialize, Default)]
struct DebugMeta {
images: Vec<Module>,
Expand Down

0 comments on commit e3793f1

Please sign in to comment.