Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions rust/cymbal/src/frames/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::{
fingerprinting::{FingerprintBuilder, FingerprintComponent, FingerprintRecordPart},
langs::{
custom::CustomFrame, dart::RawDartFrame, go::RawGoFrame, hermes::RawHermesFrame,
java::RawJavaFrame, js::RawJSFrame, node::RawNodeFrame, python::RawPythonFrame,
ruby::RawRubyFrame,
java::RawJavaFrame, ios::RawIOSFrame, js::RawJSFrame, node::RawNodeFrame,
python::RawPythonFrame, ruby::RawRubyFrame,
},
metric_consts::{LEGACY_JS_FRAME_RESOLVED, PER_FRAME_TIME},
sanitize_string,
Expand Down Expand Up @@ -43,6 +43,8 @@ pub enum RawFrame {
Java(RawJavaFrame),
#[serde(rename = "dart")]
Dart(RawDartFrame),
#[serde(rename = "ios")]
Ios(RawIOSFrame),
#[serde(rename = "custom")]
Custom(CustomFrame),
// TODO - remove once we're happy no clients are using this anymore
Expand Down Expand Up @@ -71,6 +73,7 @@ impl RawFrame {
}

RawFrame::Dart(frame) => (to_vec(Ok(frame.into())), "dart"),
RawFrame::Ios(frame) => (to_vec(Ok(frame.into())), "ios"),
RawFrame::Python(frame) => (to_vec(Ok(frame.into())), "python"),
RawFrame::Ruby(frame) => (to_vec(Ok(frame.into())), "ruby"),
RawFrame::Custom(frame) => (to_vec(Ok(frame.into())), "custom"),
Expand Down Expand Up @@ -109,6 +112,7 @@ impl RawFrame {
| RawFrame::Ruby(_)
| RawFrame::Go(_)
| RawFrame::Dart(_)
| RawFrame::Ios(_)
| RawFrame::Custom(_) => None,
}
}
Expand All @@ -124,6 +128,7 @@ impl RawFrame {
RawFrame::Hermes(raw) => raw.frame_id(),
RawFrame::Java(raw) => raw.frame_id(),
RawFrame::Dart(raw) => raw.frame_id(),
RawFrame::Ios(raw) => raw.frame_id(),
};

RawFrameId::new(hash_id, team_id)
Expand Down
78 changes: 78 additions & 0 deletions rust/cymbal/src/langs/ios.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use common_types::error_tracking::FrameId;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha512};

use crate::{
frames::Frame,
langs::{utils::add_raw_to_junk, CommonFrameMetadata},
};

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RawIOSFrame {
pub instruction_addr: Option<String>,
pub symbol_addr: Option<String>,
pub image_addr: Option<String>,
pub image_uuid: Option<String>,
pub module: Option<String>,
pub function: Option<String>,
pub filename: Option<String>,
pub lineno: Option<u32>,
pub colno: Option<u32>,
#[serde(flatten)]
pub meta: CommonFrameMetadata,
}

impl RawIOSFrame {
pub fn frame_id(&self) -> String {
let mut hasher = Sha512::new();

if let Some(instruction_addr) = &self.instruction_addr {
hasher.update(instruction_addr.as_bytes());
}

if let Some(module) = &self.module {
hasher.update(module.as_bytes());
}

if let Some(function) = &self.function {
hasher.update(function.as_bytes());
}

if let Some(image_uuid) = &self.image_uuid {
hasher.update(image_uuid.as_bytes());
}

format!("{:x}", hasher.finalize())
}

}

impl From<&RawIOSFrame> for Frame {
fn from(raw: &RawIOSFrame) -> Self {
let mut f = Frame {
frame_id: FrameId::placeholder(),
mangled_name: raw.function.clone().unwrap_or_default(),
line: raw.lineno,
column: raw.colno,
source: raw.filename.clone(),
in_app: raw.meta.in_app,
resolved_name: raw.function.clone(),
lang: "ios".to_string(),
resolved: raw.function.is_some(),
resolve_failure: None,
junk_drawer: None,
release: None,
synthetic: raw.meta.synthetic,
context: None,
suspicious: false,
module: raw.module.clone(),
exception_type: None,
code_variables: None,
};

// Store raw frame data in junk drawer for debugging/analysis
add_raw_to_junk(&mut f, raw);
f
}
}

1 change: 1 addition & 0 deletions rust/cymbal/src/langs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod custom;
pub mod dart;
pub mod go;
pub mod hermes;
pub mod ios;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be using the language here not the platform? Are these Swift or Objective C frames or something else? I can see a world where it's confusing for "iOS frames" to process MacOS exceptions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah expressed the same concern in PR body. To my best understanding frames will be identical (and handled similarly) regardless of swift/objc and platform. Not sure I can distinguish runtime in a deterministic way if a specific frame is objc/swift
Some other alternatives can be apple, apple-native?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have java which also handles Kotlin and other jvm languages if I'm not mistaken? @marandaneto thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kotlin compiles to java bytecode so its the same thing.

Copy link
Member

@marandaneto marandaneto Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd rather call it apple.

i think lang here is a confusing name since you only think about the language and its properties.

it should have been something more connected to the symbolication type.

eg
for code highlighting:
lang=kotlin | java | etc
for symbolication:
symbol_type (or platform)=elf (linux) | proguard | r8 (android/java/kotlin) | sourcemaps (web) | Mach-O (apple) | etc

right now we are using lang as a way to trigger a certain symbolication process, in my example, symbol_type.

on the SDK side we use platform which can be hermes and then it symbolicates to javascript, see the confusion.

pub mod java;
pub mod js;
pub mod node;
Expand Down
Loading