Skip to content

Commit bdcbb8a

Browse files
committed
feat: Added debug meta and repos
1 parent 3df1500 commit bdcbb8a

File tree

3 files changed

+138
-1
lines changed

3 files changed

+138
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ serde_json = "1.0"
1313
serde_plain = "0.3.0"
1414
url_serde = "0.2.0"
1515
chrono = { version = "0.4.0", features = ["serde"] }
16+
uuid = { version = "0.6.2", features = ["serde"] }
1617

1718
[patch.crates-io]
1819
serde = { git = "https://github.com/mitsuhiko/serde", branch = "feature/flatten" }

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern crate serde_json;
1313
extern crate serde_plain;
1414
extern crate url;
1515
extern crate url_serde;
16+
extern crate uuid;
1617

1718
#[macro_use]
1819
mod macros;

src/protocol/v7.rs

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use chrono;
77
use chrono::{DateTime, Utc};
88
use url_serde;
99
use url::Url;
10+
use uuid::Uuid;
1011
use serde::de::{Deserialize, Deserializer, Error as DeError};
1112
use serde::ser::{Error as SerError, Serialize, SerializeMap, Serializer};
1213
use serde_json::{from_value, to_value, Value};
@@ -182,6 +183,7 @@ pub struct Exception {
182183
pub stacktrace: Option<Stacktrace>,
183184
}
184185

186+
/// Represents the level of severity of an event or breadcrumb
185187
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
186188
#[serde(rename_all = "lowercase")]
187189
pub enum Level {
@@ -281,6 +283,85 @@ pub struct Request {
281283
#[serde(flatten)] pub other: HashMap<String, Value>,
282284
}
283285

286+
/// Represents debug meta information.
287+
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
288+
#[serde(default)]
289+
pub struct SdkInfo {
290+
/// The internal name of the SDK
291+
sdk_name: String,
292+
/// the major version of the SDK as integer or 0
293+
version_major: u32,
294+
/// the minor version of the SDK as integer or 0
295+
version_minior: u32,
296+
/// the patch version of the SDK as integer or 0
297+
version_patchlevel: u32,
298+
}
299+
300+
/// Represents a debug image.
301+
#[derive(Debug, Clone, PartialEq)]
302+
pub enum DebugImage {
303+
Apple(AppleDebugImage),
304+
Proguard(ProguardDebugImage),
305+
Unknown(HashMap<String, Value>),
306+
}
307+
308+
impl DebugImage {
309+
/// Returns the name of the type on sentry.
310+
pub fn type_name(&self) -> &str {
311+
match *self {
312+
DebugImage::Apple(..) => "apple",
313+
DebugImage::Proguard(..) => "proguard",
314+
DebugImage::Unknown(ref map) => map.get("type")
315+
.and_then(|x| x.as_str())
316+
.unwrap_or("unknown"),
317+
}
318+
}
319+
}
320+
321+
/// Represents an apple debug image in the debug meta.
322+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
323+
pub struct AppleDebugImage {
324+
pub name: String,
325+
pub arch: Option<String>,
326+
pub cpu_type: u32,
327+
pub cpu_subtype: u32,
328+
pub image_addr: u64,
329+
pub image_size: u64,
330+
pub image_vmaddr: u64,
331+
pub uuid: Uuid,
332+
}
333+
334+
/// Represents a proguard mapping file reference.
335+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
336+
pub struct ProguardDebugImage {
337+
pub uuid: Uuid,
338+
}
339+
340+
/// Represents debug meta information.
341+
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
342+
#[serde(default)]
343+
pub struct DebugMeta {
344+
/// Optional system SDK information.
345+
#[serde(skip_serializing_if = "Option::is_none")]
346+
sdk_info: Option<SdkInfo>,
347+
/// A list of debug information files.
348+
#[serde(skip_serializing_if = "Option::is_none")]
349+
images: Option<DebugImage>,
350+
}
351+
352+
/// Represents a repository reference.
353+
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
354+
#[serde(default)]
355+
pub struct RepoReference {
356+
/// The name of the repository as it is registered in Sentry.
357+
pub name: String,
358+
/// The optional prefix path to apply to source code when pairing it
359+
/// up with files in the repository.
360+
pub prefix: Option<String>,
361+
/// The optional current revision of the local repository.
362+
pub revision: Option<String>,
363+
}
364+
284365
/// Represents a full event for Sentry.
285366
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
286367
#[serde(default)]
@@ -312,6 +393,9 @@ pub struct Event {
312393
/// A release identifier.
313394
#[serde(skip_serializing_if = "Option::is_none")]
314395
pub release: Option<String>,
396+
/// Repository references
397+
#[serde(skip_serializing_if = "HashMap::is_empty")]
398+
pub repos: HashMap<String, RepoReference>,
315399
/// An optional distribution identifer.
316400
#[serde(skip_serializing_if = "Option::is_none")]
317401
pub dist: Option<String>,
@@ -350,9 +434,13 @@ pub struct Event {
350434
/// Optional extra information to be sent with the event.
351435
#[serde(skip_serializing_if = "HashMap::is_empty")]
352436
pub extra: HashMap<String, Value>,
437+
/// Debug meta information.
438+
#[serde(skip_serializing_if = "Option::is_none")]
439+
pub debug_meta: Option<DebugMeta>,
353440
/// Additional arbitrary keys for forwards compatibility.
354441
#[serde(flatten)]
355442
pub other: HashMap<String, Value>,
443+
// TODO: repos, sdk, logger, culprit, modules
356444
}
357445

358446
fn is_other(value: &str) -> bool {
@@ -374,6 +462,7 @@ impl Default for Event {
374462
timestamp: None,
375463
server_name: None,
376464
release: None,
465+
repos: HashMap::new(),
377466
dist: None,
378467
environment: None,
379468
user: None,
@@ -386,6 +475,7 @@ impl Default for Event {
386475
threads: Vec::new(),
387476
tags: HashMap::new(),
388477
extra: HashMap::new(),
478+
debug_meta: None,
389479
other: HashMap::new(),
390480
}
391481
}
@@ -554,7 +644,7 @@ fn serialize_context<S>(value: &HashMap<String, Context>, serializer: S) -> Resu
554644
where
555645
S: Serializer,
556646
{
557-
let mut map = try!(serializer.serialize_map(Some(value.len())));
647+
let mut map = try!(serializer.serialize_map(None));
558648

559649
for (key, value) in value {
560650
let mut c = match to_value(&value.data).map_err(S::Error::custom)? {
@@ -629,3 +719,48 @@ where
629719
}
630720
Helper { values: &value }.serialize(serializer)
631721
}
722+
723+
impl<'de> Deserialize<'de> for DebugImage {
724+
fn deserialize<D>(deserializer: D) -> Result<DebugImage, D::Error>
725+
where
726+
D: Deserializer<'de>,
727+
{
728+
let mut map = match Value::deserialize(deserializer)? {
729+
Value::Object(map) => map,
730+
_ => return Err(D::Error::custom("expected debug image")),
731+
};
732+
733+
Ok(match map.remove("type").as_ref().and_then(|x| x.as_str()) {
734+
Some("apple") => {
735+
let img: AppleDebugImage =
736+
from_value(Value::Object(map)).map_err(D::Error::custom)?;
737+
DebugImage::Apple(img)
738+
}
739+
Some("proguard") => {
740+
let img: ProguardDebugImage =
741+
from_value(Value::Object(map)).map_err(D::Error::custom)?;
742+
DebugImage::Proguard(img)
743+
}
744+
Some(ty) => {
745+
let mut img: HashMap<String, Value> = map.into_iter().collect();
746+
img.insert("type".into(), ty.into());
747+
DebugImage::Unknown(img)
748+
}
749+
None => DebugImage::Unknown(Default::default()),
750+
})
751+
}
752+
}
753+
754+
impl Serialize for DebugImage {
755+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
756+
where
757+
S: Serializer,
758+
{
759+
let mut c = match to_value(self).map_err(S::Error::custom)? {
760+
Value::Object(map) => map,
761+
_ => unreachable!(),
762+
};
763+
c.insert("type".into(), self.type_name().into());
764+
c.serialize(serializer)
765+
}
766+
}

0 commit comments

Comments
 (0)