diff --git a/docs/RFCs/0005-crashtracker-structured-log-format.md b/docs/RFCs/0005-crashtracker-structured-log-format.md new file mode 100644 index 000000000..721ffac42 --- /dev/null +++ b/docs/RFCs/0005-crashtracker-structured-log-format.md @@ -0,0 +1,217 @@ +# RFC 0005: Crashtracker Structured Log Format (Version 1.0) + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [IETF RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119). + +## Summary + +This document describes version 1.0 of the crashinfo data format. + +## Motivation + +The `libdatadog` crashtracker detects program crashes. +It automatically collects information relevant to the characterizing and debugging the crash, including stack-traces, the crash-type (e.g. SIGSIGV, SIGBUS, etc) crash, the library version, etc. +This RFC establishes a standardized logging format for reporting this information. + +### Why structured json + +As a text-based format, json can be written to standard logging endpoints. +It is (somewhat) human readable, so users can directly interpret the crash info off their log if necessary. +As a structured format, it avoids the ambiguity of standard semi-structured stacktrace formats (as used by e.g. Java, .Net, etc). +Due to the use of native extensions, it is possible for a single stack-trace to include frames from multiple languages (e.g. python may call C code, which calls Rust code, etc). +Having a single structured format allows us to work across languages. + +## Proposed format + +A natural language description of the proposed json format is given here. +An example is given in Appendix A, and the schema is given in Appendix B. +Any field not listed as "Required" is optional. +Consumers MUST accept json with elided optional fields. + +### Extensibility + +The data-format has a REQUIRED `data_schema_version` field, which represents the semver version ID of the data. +Following semver, collectors may add additional fields without affecting the major version number. +Parsers SHOULD therefore accept unexpected fields, either by ignoring them, or by displaying them as additional data. + +### Fields + +- `counters`: **[optional]** + A map of names to integer values. + At present, this is used by the profiler to track which operations were active at the time of the crash. +- `data_schema_version`: **[required]** + A string containing the semver ID of the crashtracker data schema ("1.0" for the current version). +- `error`: **[required]** + - `threads`: **[optional]** + An array of `Thread` objects. + In a multi-threaded program, the collector SHOULD collect the stacktraces of all active threads, and report them here. + A `Thread` object has the following fields: + - `crashed`: **[required]** + A boolean which tells if the thread crashed. + - `name`: **[required]** + Name of the thread (e.g. 'Thread 0'). + - `stack`: **[required]** + The `StackTrace` of the thread. + See below for more details on how stacktraces are formatted. + - `state`: **[optional]** + Platform-specific state of the thread when its state was captured (CPU registers dump for iOS, thread state enum for Android, etc.). + Currently, this is a platform-dependent string. + - `is_crash`: **[required]** + Boolean true if the error was a crash, false otherwise. + - `kind`: **[required]** + The kind of error that occurred. + For example, "Panic", "UnhandledException", "UnixSignal". + - `message`: **[optional]** + A human readable string containing an error message associated with the stack trace. + - `source_type`: **[required]** + The string "Crashtracking". + - `stack`: **[required]** + This represents the stack of the crashing thread. + See below for more details on how stacktraces are formatted. +- `files`: **[optional]** + A `Map` where `contents` is an array of plain text strings, one per line. + Useful files for triage and debugging, such as `/proc/self/maps` or `/proc/meminfo`. +- `fingerprint`: **[optional]** + A string containing a summary or hash of crash information which can be used for deduplication. +- `incomplete`: **[required]** + Boolean `false` if the crashreport is complete (i.e. contains all intended data), `true` if there is expected missing data. + This can happen becasue the crashtracker is architected to stream data to an out of process receiver, allowing a partial crash report to be emitted even in the case where the crashtracker itself crashed during stack trace collection. + This MUST be set to `true` if any required field is missing. +- `log_messages`: **[optional]** + An array of strings containing log messages generated by the crashtracker. +- `metadata`: **[required]** + Metadata about the system in which the crash occurred: + - `library_name`: **[required]** + e.g. "dd-trace-python". + - `library_version`: **[required]** + e.g. "2.16.0". + - `family`: **[required]** + e.g. "python". + - `tags`: **[optional]** + A set of key:value pairs, representing any tags the crashtracking system wishes to associate with the crash. + Examples would include "hostname", "service", and any configuration information the system wishes to track. +- `os_info`: **[required]** + The OS + processor architecture on which the crash occurred. + Follows the display format of the [os_info crate](https://crates.io/crates/os_info). + - `architecture`: **[required]** + e.g. "arm64" + - `bitness`: **[required]** + e.g. "64-bit". + - `os_type`: **[required]** + e.g. "Mac OS". + - `version`: **[required]** + e.g. "14.7.0". +- `proc_info`: **[optional]** + A place to store information about the crashing process. + In the future, this may have additional optional fields as more data is collected. + - `pid`: **[required]** + The PID of the crashing process. +- `sig_info`: **[optional]** + UNIX signal based collectors only: Useful information from the [siginfo_t](https://man7.org/linux/man-pages/man2/sigaction.2.html) structure. + - `sid_addr`: **[optional]** + A hexidecimal string with the memory address at which the fault occurred, e.g. "0xDEADBEEF". + - `si_code`: **[required]** + An integer storing the [UNIX signal code](https://man7.org/linux/man-pages/man7/signal.7.html), e.g. `1` for a `SEGV_MAPERR`. + - `si_code_human_readable`: **[required]** + The signal code expressed as a human readable string, e.g. "SEGV_MAPERR" for `SEGV_MAPERR`. + Follows the naming convention in [the manpage](https://man7.org/linux/man-pages/man7/signal.7.html). + - `si_signo`: **[required]** + An integer storing the [UNIX signal number](https://man7.org/linux/man-pages/man7/signal.7.html), e.g. `11` for a segmentation violation. + - `si_signo_human_readable`: **[required]** + The signal name, e.g. "SIGSEGV". + Follows the naming convention in [the manpage](https://man7.org/linux/man-pages/man7/signal.7.html). +- `span_ids`: **[optional]** + A vector representing active span ids at the time of program crash. + The collector MAY cap the number of spans that it tracks. + - `id`: **[required]** + A string containing the span id. + - `thread_name`: **[optional]** + A string containing the thread name for the given span. +- `timestamp`: **[required]** + The time at which the crash occurred, in ISO 8601 format. +- `trace_ids:`: **[optional]** + A vector representing active span ids at the time of program crash. + The collector MAY cap the number of spans that it tracks. + - `id`: **[required]** + A string containing the trace id. + - `thread name`: **[optional]** + A string containing the thread name for the given trace. +- `uuid`: **[required]** + A UUID v4 which uniquely identifies the crash. + This will typically be generated at crash-time, and then associated with the uploaded crash. + +### Stacktraces + +Different languages and language runtimes have different representations of a stacktrace. +The representation below attempts to collect as much information as possible. +In addition, not all information may be available at crash-time on a given machine. +For example, some libraries may have been shipped with debug symbols stripped, meaning that the only information available about a given frame may be the instruction pointer (`ip`) address, stored as a hex number "0xDEADBEEF". +This address may be given as an absolute address, or a `NormalizedAddress`, which can be used by backend symbolication. + +A stacktrace consists of + +- `format`: **[required]** + An identifier describing the format of the stack trace. + Allows for extensibility to support different stack trace formats. + The format described below is identified using the string "Datadog Crashtracker 1.0" +- `frames`: **[required]** + An array of `StackFrame`, described below. + Note that each inlined function gets its own stack frame in this schema. + +#### StackFrames + +- **Absolute Addresses** + The actual in-memory addresses used in the crashing process. + Combined with mapping information, such as from `/proc/self/maps`, and the relevant binaries, this can be used to reconstruct relevant symbols. + These fields follow the scheme used by the [backtrace crate](https://docs.rs/backtrace/latest/backtrace/struct.Frame.html) + - `ip`: **[optional]** + The current instruction pointer of this frame. + This is normally the next instruction to execute in the frame, but not all implementations list this with 100% accuracy (but it’s generally pretty close). + - `sp`: **[optional]** + The current stack pointer of this frame. + - `symbol_address`: **[optional]** + The starting symbol address of the frame of this function. + This will attempt to rewind the instruction pointer returned by ip to the start of the function, returning that value. + In some cases, however, backends will just return ip from this function. + - `module_base_address`: **[optional]** + The base address of the module to which the frame belongs +- **Relative Addresses** + Addresses expressed as an offset into a given library or executable. + Can be used by backend symbolication to generate debug names etc. + Note that tracking this per stack frame can entail significant duplication of information. + Adding a "modules" section and referencing it by index, as in the pprof specification, is future work. + - `build_id`: **[optional]** + A string identifying the build id of the module the address belongs to. + For example, GNU build ids are hex strings "9944168df12b0b9b152113c4ad663bc27797fb15". + Pdb build ids can be stored as a concatenation of the guid and the age (using a well-known separator). + - `build_id_type`: **[required if `build_id` is set, optional otherwise]** + The type of the `build_id`. E.g. "SHA1/GNU/GO/PDB/PE". + - `file_type`: **[required if `relative_address` is set, optional otherwise]** + The file type of the module containing the symbol, e.g. "ELF", "PDB", etc. + - `relative_address`: **[optional]** + The relative offset of the symbol in the base file (e.g. an ELF virtual address), given as a hexidecimal string. + - `path`: **[required if `relative_address` is set, optional otherwise]** + The path to the module containing the symbol. +- **Debug information (e.g. "names")** + Human readable debug information representing the location of the stack frame in the high-level code. + Note that this is a best effort collection: for optimized code, it may be difficult to associate a given instruction back to file, line and column. + - `column`: **[optional]** + The column number in the given file where the symbol was defined. + - `file`: **[optional]** + The file name where this function was defined. + Note that this may be either an absolute or relative path. + - `line`: **[optional]** + The line number in the given file where the symbol was defined. + - `function`: **[optional]** + The name of the function. + This may or may not include module information. + It may or may not be demangled (e.g. "\_ZNSt28**atomic_futex_unsigned_base26_M_futex_wait_until_steadyEPjjbNSt6chrono8durationIlSt5ratioILl1ELl1EEEENS2_IlS3_ILl1ELl1000000000EEEE" vs "std::**atomic_futex_unsigned_base::\_M_futex_wait_until_steady") + +### Other data + +## Appendix A: Example output + +[Available here](artifacts/0002-crashtracker-example.json) + +## Appendix B: Json Schema + +[Available here](artifacts/0002-crashtracker-schema.json) diff --git a/docs/RFCs/artifacts/0005-crashtracker-example.json b/docs/RFCs/artifacts/0005-crashtracker-example.json new file mode 100644 index 000000000..c66204b03 --- /dev/null +++ b/docs/RFCs/artifacts/0005-crashtracker-example.json @@ -0,0 +1,344 @@ +{ + "counters": { + "profiler_collecting_sample": 1, + "profiler_inactive": 0, + "profiler_unwinding": 0, + "profiler_serializing": 0 + }, + "data_schema_version": "1.0", + "error": { + "is_crash": true, + "kind": "UnixSignal", + "source_type": "Crashtracking", + "stack": { + "format": "Datadog Crashtracker 1.0", + "frames": [ + { + "ip": "0x100cc8270", + "sp": "0x1023370e0", + "symbol_address": "0x100cc8270", + "column": 5, + "file": "/Users/daniel.schwartznarbonne/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/libunwind.rs", + "function": "backtrace::backtrace::libunwind::trace::h44cd4fb81cab179c", + "line": 116 + }, + { + "ip": "0x100cc8270", + "sp": "0x1023370e0", + "symbol_address": "0x100cc8270", + "column": 5, + "file": "/Users/daniel.schwartznarbonne/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/mod.rs", + "function": "backtrace::backtrace::trace_unsynchronized::h9864180bb5bf11b8", + "line": 66 + }, + { + "ip": "0x100c52a24", + "sp": "0x102337130", + "symbol_address": "0x100c52a24", + "column": 5, + "file": "/Users/daniel.schwartznarbonne/go/src/github.com/DataDog/libdatadog/crashtracker/src/collector/emitters.rs", + "function": "datadog_crashtracker::collector::emitters::emit_backtrace_by_frames::hffe0893f890cf311", + "line": 34 + }, + { + "ip": "0x100c53f50", + "sp": "0x102337290", + "symbol_address": "0x100c53f50", + "column": 18, + "file": "/Users/daniel.schwartznarbonne/go/src/github.com/DataDog/libdatadog/crashtracker/src/collector/emitters.rs", + "function": "datadog_crashtracker::collector::emitters::emit_crashreport::h072d9dec8eb6d587", + "line": 128 + }, + { + "ip": "0x100d00120", + "sp": "0x1023374a0", + "symbol_address": "0x100d00120", + "column": 15, + "file": "/Users/daniel.schwartznarbonne/go/src/github.com/DataDog/libdatadog/crashtracker/src/collector/crash_handler.rs", + "function": "datadog_crashtracker::collector::crash_handler::handle_posix_signal_impl::ha45884607fab00ab", + "line": 507 + }, + { + "ip": "0x100cff9d0", + "sp": "0x102337a20", + "symbol_address": "0x100cff9d0", + "column": 13, + "file": "/Users/daniel.schwartznarbonne/go/src/github.com/DataDog/libdatadog/crashtracker/src/collector/crash_handler.rs", + "function": "datadog_crashtracker::collector::crash_handler::handle_posix_sigaction::hfda5a5ec0bcfec82", + "line": 388 + }, + { + "ip": "0x181022584", + "sp": "0x102337b80", + "symbol_address": "0x181022584", + "function": "__simple_esappend" + }, + { + "ip": "0x100cdfa4c", + "sp": "0x102337bb0", + "symbol_address": "0x100cdfa4c", + "column": 5, + "file": "/Users/daniel.schwartznarbonne/go/src/github.com/DataDog/libdatadog/crashtracker/src/collector/api.rs", + "function": "datadog_crashtracker::collector::api::test_crash::h0310ac857cf5687f", + "line": 157 + }, + { + "ip": "0x100c81484", + "sp": "0x16f3da7a0", + "symbol_address": "0x100c81484", + "column": 20, + "file": "/Users/daniel.schwartznarbonne/go/src/github.com/DataDog/libdatadog/crashtracker/src/collector/api.rs", + "function": "datadog_crashtracker::collector::api::test_crash::{{closure}}::h0b9b36ed20d8a85a", + "line": 99 + }, + { + "ip": "0x100ca9e80", + "sp": "0x16f3da7c0", + "symbol_address": "0x100ca9e80", + "column": 5, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/ops/function.rs", + "function": "core::ops::function::FnOnce::call_once::h77ea56fa2b6e43e3", + "line": 250 + }, + { + "ip": "0x100dca6a0", + "sp": "0x16f3da7f0", + "symbol_address": "0x100dca6a0", + "column": 5, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/ops/function.rs", + "function": "core::ops::function::FnOnce::call_once::hdc78704e3375b6cc", + "line": 250 + }, + { + "ip": "0x100dca6a0", + "sp": "0x16f3da7f0", + "symbol_address": "0x100dca6a0", + "column": 18, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/test/src/lib.rs", + "function": "test::__rust_begin_short_backtrace::ha00c83e9361a315d", + "line": 621 + }, + { + "ip": "0x100dc9e18", + "sp": "0x16f3da830", + "symbol_address": "0x100dc9e18", + "column": 60, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/test/src/lib.rs", + "function": "test::run_test_in_process::{{closure}}::h049a3922169151a8", + "line": 644 + }, + { + "ip": "0x100dc9e18", + "sp": "0x16f3da830", + "symbol_address": "0x100dc9e18", + "column": 9, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/panic/unwind_safe.rs", + "function": " as core::ops::function::FnOnce<()>>::call_once::h59b471ae83578d9f", + "line": 272 + }, + { + "ip": "0x100dc9e18", + "sp": "0x16f3da830", + "symbol_address": "0x100dc9e18", + "column": 40, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/panicking.rs", + "function": "std::panicking::try::do_call::hdcae0245e55fa0c0", + "line": 552 + }, + { + "ip": "0x100dc9e18", + "sp": "0x16f3da830", + "symbol_address": "0x100dc9e18", + "column": 19, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/panicking.rs", + "function": "std::panicking::try::h9dc0119b564ac9cf", + "line": 516 + }, + { + "ip": "0x100dc9e18", + "sp": "0x16f3da830", + "symbol_address": "0x100dc9e18", + "column": 14, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/panic.rs", + "function": "std::panic::catch_unwind::hab329ede8b56df3b", + "line": 146 + }, + { + "ip": "0x100dc9e18", + "sp": "0x16f3da830", + "symbol_address": "0x100dc9e18", + "column": 27, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/test/src/lib.rs", + "function": "test::run_test_in_process::h42ddc94bb4665859", + "line": 644 + }, + { + "ip": "0x100dc9e18", + "sp": "0x16f3da830", + "symbol_address": "0x100dc9e18", + "column": 43, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/test/src/lib.rs", + "function": "test::run_test::{{closure}}::h5bc06caf086790ae", + "line": 567 + }, + { + "ip": "0x100d9c7d4", + "sp": "0x16f3dadb0", + "symbol_address": "0x100d9c7d4", + "column": 41, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/test/src/lib.rs", + "function": "test::run_test::{{closure}}::hf12704d7fb5fe7af", + "line": 595 + }, + { + "ip": "0x100d9c7d4", + "sp": "0x16f3dadb0", + "symbol_address": "0x100d9c7d4", + "column": 18, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/sys_common/backtrace.rs", + "function": "std::sys_common::backtrace::__rust_begin_short_backtrace::hf83ba910f7522d55", + "line": 155 + }, + { + "ip": "0x100da0d08", + "sp": "0x16f3daf20", + "symbol_address": "0x100da0d08", + "column": 17, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/thread/mod.rs", + "function": "std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}::he9daeef7c6950e9b", + "line": 528 + }, + { + "ip": "0x100da0d08", + "sp": "0x16f3daf20", + "symbol_address": "0x100da0d08", + "column": 9, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/panic/unwind_safe.rs", + "function": " as core::ops::function::FnOnce<()>>::call_once::h0202fb4f2537b363", + "line": 272 + }, + { + "ip": "0x100da0d08", + "sp": "0x16f3daf20", + "symbol_address": "0x100da0d08", + "column": 40, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/panicking.rs", + "function": "std::panicking::try::do_call::hbfefa096cde588e7", + "line": 552 + }, + { + "ip": "0x100da0d08", + "sp": "0x16f3daf20", + "symbol_address": "0x100da0d08", + "column": 19, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/panicking.rs", + "function": "std::panicking::try::hebf8b6694f3819d7", + "line": 516 + }, + { + "ip": "0x100da0d08", + "sp": "0x16f3daf20", + "symbol_address": "0x100da0d08", + "column": 14, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/panic.rs", + "function": "std::panic::catch_unwind::h62e366e1b226d45f", + "line": 146 + }, + { + "ip": "0x100da0d08", + "sp": "0x16f3daf20", + "symbol_address": "0x100da0d08", + "column": 30, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/thread/mod.rs", + "function": "std::thread::Builder::spawn_unchecked_::{{closure}}::h2dcb575929bd939b", + "line": 527 + }, + { + "ip": "0x100da0d08", + "sp": "0x16f3daf20", + "symbol_address": "0x100da0d08", + "column": 5, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/ops/function.rs", + "function": "core::ops::function::FnOnce::call_once{{vtable.shim}}::h28247bdc23f84175", + "line": 250 + }, + { + "ip": "0x10147da90", + "sp": "0x16f3daf80", + "symbol_address": "0x10147da90", + "column": 9, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/alloc/src/boxed.rs", + "function": " as core::ops::function::FnOnce>::call_once::heeda316fdad4f743", + "line": 2020 + }, + { + "ip": "0x10147da90", + "sp": "0x16f3daf80", + "symbol_address": "0x10147da90", + "column": 9, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/alloc/src/boxed.rs", + "function": " as core::ops::function::FnOnce>::call_once::h0d3160611f7295b1", + "line": 2020 + }, + { + "ip": "0x10147da90", + "sp": "0x16f3daf80", + "symbol_address": "0x10147da90", + "column": 17, + "file": "/rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/sys/pal/unix/thread.rs", + "function": "std::sys::pal::unix::thread::Thread::new::thread_start::h9266fbbdd0c3d8be", + "line": 108 + }, + { + "ip": "0x180ff1f94", + "sp": "0x16f3dafd0", + "symbol_address": "0x180ff1f94", + "function": "__pthread_joiner_wake" + } + ] + } + }, + "incomplete": false, + "metadata": { + "library_name": "libname", + "library_version": "version", + "family": "family", + "tags": [ + "apple:banana" + ] + }, + "os_info": { + "architecture": "arm64", + "bitness": "64-bit", + "os_type": "Mac OS", + "version": "14.7.0" + }, + "proc_info": { + "pid": 5056 + }, + "sig_info": { + "si_addr": "0x0000000000000000", + "si_code": -1, + "si_code_human_readable": "SI_USER", + "si_signo": 11, + "si_signo_human_readable": "SIGSEGV" + }, + "span_ids": [ + { + "id": "12" + }, + { + "id": "42" + } + ], + "timestamp": "2024-11-13 19:28:37.429897 UTC", + "trace_ids": [ + { + "id": "99399939399939393993" + }, + { + "id": "340282366920938463463374607431768211455" + } + ], + "uuid": "36e6ca52-9aab-46ae-9ba4-caadda7f9fb6" +} \ No newline at end of file diff --git a/docs/RFCs/artifacts/0005-crashtracker-schema.json b/docs/RFCs/artifacts/0005-crashtracker-schema.json new file mode 100644 index 000000000..d561dda86 --- /dev/null +++ b/docs/RFCs/artifacts/0005-crashtracker-schema.json @@ -0,0 +1,436 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CrashInfo", + "type": "object", + "required": [ + "data_schema_version", + "error", + "incomplete", + "metadata", + "os_info", + "proc_info", + "sig_info", + "timestamp", + "uuid" + ], + "properties": { + "counters": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int64" + } + }, + "data_schema_version": { + "type": "string" + }, + "error": { + "$ref": "#/definitions/ErrorData" + }, + "files": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "fingerprint": { + "type": [ + "string", + "null" + ] + }, + "incomplete": { + "type": "boolean" + }, + "log_messages": { + "type": "array", + "items": { + "type": "string" + } + }, + "metadata": { + "$ref": "#/definitions/Metadata" + }, + "os_info": { + "$ref": "#/definitions/OsInfo" + }, + "proc_info": { + "$ref": "#/definitions/ProcInfo" + }, + "sig_info": { + "$ref": "#/definitions/SigInfo" + }, + "span_ids": { + "type": "array", + "items": { + "$ref": "#/definitions/Span" + } + }, + "timestamp": { + "type": "string" + }, + "trace_ids": { + "type": "array", + "items": { + "$ref": "#/definitions/Span" + } + }, + "uuid": { + "type": "string" + } + }, + "definitions": { + "BuildIdType": { + "type": "string", + "enum": [ + "GNU", + "GO", + "PDB", + "PE", + "SHA1" + ] + }, + "ErrorData": { + "type": "object", + "required": [ + "is_crash", + "kind", + "source_type", + "stack" + ], + "properties": { + "is_crash": { + "type": "boolean" + }, + "kind": { + "$ref": "#/definitions/ErrorKind" + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "source_type": { + "$ref": "#/definitions/SourceType" + }, + "stack": { + "$ref": "#/definitions/StackTrace" + }, + "threads": { + "type": "array", + "items": { + "$ref": "#/definitions/ThreadData" + } + } + } + }, + "ErrorKind": { + "type": "string", + "enum": [ + "Panic", + "UnhandledException", + "UnixSignal" + ] + }, + "FileType": { + "type": "string", + "enum": [ + "APK", + "ELF", + "PDB" + ] + }, + "Metadata": { + "type": "object", + "required": [ + "family", + "library_name", + "library_version" + ], + "properties": { + "family": { + "type": "string" + }, + "library_name": { + "type": "string" + }, + "library_version": { + "type": "string" + }, + "tags": { + "description": "A list of \"key:value\" tuples.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "OsInfo": { + "type": "object", + "required": [ + "architecture", + "bitness", + "os_type", + "version" + ], + "properties": { + "architecture": { + "type": "string" + }, + "bitness": { + "type": "string" + }, + "os_type": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "ProcInfo": { + "type": "object", + "required": [ + "pid" + ], + "properties": { + "pid": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + }, + "SiCodes": { + "description": "See https://man7.org/linux/man-pages/man2/sigaction.2.html", + "type": "string", + "enum": [ + "BUS_ADRALN", + "BUS_ADRERR", + "BUS_MCEERR_AO", + "BUS_MCEERR_AR", + "BUS_OBJERR", + "SEGV_ACCERR", + "SEGV_BNDERR", + "SEGV_MAPERR", + "SEGV_PKUERR", + "SI_ASYNCIO", + "SI_KERNEL", + "SI_MESGQ", + "SI_QUEUE", + "SI_SIGIO", + "SI_TIMER", + "SI_TKILL", + "SI_USER", + "SYS_SECCOMP" + ] + }, + "SigInfo": { + "type": "object", + "required": [ + "si_code", + "si_code_human_readable", + "si_signo", + "si_signo_human_readable" + ], + "properties": { + "si_addr": { + "type": [ + "string", + "null" + ] + }, + "si_code": { + "type": "integer", + "format": "int32" + }, + "si_code_human_readable": { + "$ref": "#/definitions/SiCodes" + }, + "si_signo": { + "type": "integer", + "format": "int32" + }, + "si_signo_human_readable": { + "$ref": "#/definitions/SignalNames" + } + } + }, + "SignalNames": { + "description": "See https://man7.org/linux/man-pages/man7/signal.7.html", + "type": "string", + "enum": [ + "SIGABRT", + "SIGBUS", + "SIGSEGV", + "SIGSYS" + ] + }, + "SourceType": { + "type": "string", + "enum": [ + "Crashtracking" + ] + }, + "Span": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "thread_name": { + "type": [ + "string", + "null" + ] + } + } + }, + "StackFrame": { + "type": "object", + "properties": { + "build_id": { + "type": [ + "string", + "null" + ] + }, + "build_id_type": { + "anyOf": [ + { + "$ref": "#/definitions/BuildIdType" + }, + { + "type": "null" + } + ] + }, + "column": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "file": { + "type": [ + "string", + "null" + ] + }, + "file_type": { + "anyOf": [ + { + "$ref": "#/definitions/FileType" + }, + { + "type": "null" + } + ] + }, + "function": { + "type": [ + "string", + "null" + ] + }, + "ip": { + "type": [ + "string", + "null" + ] + }, + "line": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "module_base_address": { + "type": [ + "string", + "null" + ] + }, + "path": { + "type": [ + "string", + "null" + ] + }, + "relative_address": { + "type": [ + "string", + "null" + ] + }, + "sp": { + "type": [ + "string", + "null" + ] + }, + "symbol_address": { + "type": [ + "string", + "null" + ] + } + } + }, + "StackTrace": { + "type": "object", + "required": [ + "format", + "frames" + ], + "properties": { + "format": { + "type": "string" + }, + "frames": { + "type": "array", + "items": { + "$ref": "#/definitions/StackFrame" + } + } + } + }, + "ThreadData": { + "type": "object", + "required": [ + "crashed", + "name", + "stack" + ], + "properties": { + "crashed": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "stack": { + "$ref": "#/definitions/StackTrace" + }, + "state": { + "type": [ + "string", + "null" + ] + } + } + } + } +} \ No newline at end of file