sentry_types/protocol/
attachment.rs

1use std::fmt;
2
3use serde::Deserialize;
4
5/// The different types an attachment can have.
6#[derive(Debug, Copy, Clone, Eq, PartialEq, Deserialize)]
7pub enum AttachmentType {
8    #[serde(rename = "event.attachment")]
9    /// (default) A standard attachment without special meaning.
10    Attachment,
11    /// A minidump file that creates an error event and is symbolicated. The
12    /// file should start with the `MDMP` magic bytes.
13    #[serde(rename = "event.minidump")]
14    Minidump,
15    /// An Apple crash report file that creates an error event and is symbolicated.
16    #[serde(rename = "event.applecrashreport")]
17    AppleCrashReport,
18    /// An XML file containing UE4 crash meta data. During event ingestion,
19    /// event contexts and extra fields are extracted from this file.
20    #[serde(rename = "unreal.context")]
21    UnrealContext,
22    /// A plain-text log file obtained from UE4 crashes. During event ingestion,
23    /// the last logs are extracted into event breadcrumbs.
24    #[serde(rename = "unreal.logs")]
25    UnrealLogs,
26}
27
28impl Default for AttachmentType {
29    fn default() -> Self {
30        Self::Attachment
31    }
32}
33
34impl AttachmentType {
35    /// Gets the string value Sentry expects for the attachment type.
36    pub fn as_str(self) -> &'static str {
37        match self {
38            Self::Attachment => "event.attachment",
39            Self::Minidump => "event.minidump",
40            Self::AppleCrashReport => "event.applecrashreport",
41            Self::UnrealContext => "unreal.context",
42            Self::UnrealLogs => "unreal.logs",
43        }
44    }
45}
46
47#[derive(Clone, PartialEq, Default)]
48/// Represents an attachment item.
49pub struct Attachment {
50    /// The actual attachment data.
51    pub buffer: Vec<u8>,
52    /// The filename of the attachment.
53    pub filename: String,
54    /// The Content Type of the attachment
55    pub content_type: Option<String>,
56    /// The special type of this attachment.
57    pub ty: Option<AttachmentType>,
58}
59
60impl Attachment {
61    /// Writes the attachment and its headers to the provided `Writer`.
62    pub fn to_writer<W>(&self, writer: &mut W) -> std::io::Result<()>
63    where
64        W: std::io::Write,
65    {
66        writeln!(
67            writer,
68            r#"{{"type":"attachment","length":{length},"filename":"{filename}","attachment_type":"{at}","content_type":"{ct}"}}"#,
69            filename = self.filename,
70            length = self.buffer.len(),
71            at = self.ty.unwrap_or_default().as_str(),
72            ct = self
73                .content_type
74                .as_ref()
75                .unwrap_or(&"application/octet-stream".to_string())
76        )?;
77
78        writer.write_all(&self.buffer)?;
79        Ok(())
80    }
81}
82
83// Implement Debug manually, otherwise users will be sad when they get a dump
84// of decimal encoded bytes to their console
85impl fmt::Debug for Attachment {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        f.debug_struct("Attachment")
88            .field("buffer", &self.buffer.len())
89            .field("filename", &self.filename)
90            .field("content_type", &self.content_type)
91            .field("type", &self.ty)
92            .finish()
93    }
94}