From b852ebd99a6ed3f9a13d706ff8c91ed1587eef9c Mon Sep 17 00:00:00 2001
From: Markus Unterwaditzer <markus-honeypot@unterwaditzer.net>
Date: Fri, 31 Jul 2020 11:32:04 +0200
Subject: [PATCH 01/17] wip on jsonschema project for snuba

---
 event.schema.json                       |  1 +
 mypy.ini                                |  2 ++
 requirements.txt                        |  3 ++-
 snuba/datasets/events_processor.py      | 14 +++++------
 snuba/datasets/events_processor_base.py | 31 +++++++++++++++++--------
 5 files changed, 33 insertions(+), 18 deletions(-)
 create mode 100644 event.schema.json

diff --git a/event.schema.json b/event.schema.json
new file mode 100644
index 00000000000..ce365c72a7f
--- /dev/null
+++ b/event.schema.json
@@ -0,0 +1 @@
+{"$schema":"http://json-schema.org/draft-07/schema#","title":"Event","anyOf":[{"type":"object","properties":{"breadcrumbs":{"description":"List of breadcrumbs recorded before this event.","default":null,"type":["object","null"],"required":["values"],"properties":{"values":{"type":"array","items":{"anyOf":[{"$ref":"#/definitions/Breadcrumb"},{"type":"null"}]}}}},"contexts":{"description":"Contexts describing the environment (e.g. device, os or browser).","default":null,"anyOf":[{"$ref":"#/definitions/Contexts"},{"type":"null"}]},"culprit":{"description":"Custom culprit of the event.","default":null,"type":["string","null"]},"debug_meta":{"description":"Meta data for event processing and debugging.","default":null,"anyOf":[{"$ref":"#/definitions/DebugMeta"},{"type":"null"}]},"dist":{"description":"Program's distribution identifier.","default":null,"type":["string","null"]},"environment":{"description":"Environment the environment was generated in (\"production\" or \"development\").","default":null,"type":["string","null"]},"errors":{"description":"Errors encountered during processing. Intended to be phased out in favor of annotation/metadata system.","default":null,"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/EventProcessingError"},{"type":"null"}]}},"event_id":{"description":"Unique identifier of this event.","default":null,"anyOf":[{"$ref":"#/definitions/EventId"},{"type":"null"}]},"exception":{"description":"One or multiple chained (nested) exceptions.","default":null,"type":["object","null"],"required":["values"],"properties":{"values":{"type":"array","items":{"anyOf":[{"$ref":"#/definitions/Exception"},{"type":"null"}]}}}},"extra":{"description":"Arbitrary extra information set by the user.","default":null,"type":["object","null"],"additionalProperties":true},"fingerprint":{"description":"Manual fingerprint override.","default":null,"anyOf":[{"$ref":"#/definitions/Fingerprint"},{"type":"null"}]},"key_id":{"description":"Project key which sent this event.","default":null,"type":["string","null"]},"level":{"description":"Severity level of the event.","default":null,"anyOf":[{"$ref":"#/definitions/Level"},{"type":"null"}]},"logentry":{"description":"Custom parameterized message for this event.","default":null,"anyOf":[{"$ref":"#/definitions/LogEntry"},{"type":"null"}]},"logger":{"description":"Logger that created the event.","default":null,"type":["string","null"]},"modules":{"description":"Name and versions of installed modules.","default":null,"type":["object","null"],"additionalProperties":{"type":["string","null"]}},"platform":{"description":"Platform identifier of this event (defaults to \"other\").","default":null,"type":["string","null"]},"project":{"description":"Project which sent this event.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"received":{"description":"Timestamp when the event has been received by Sentry.","default":null,"anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"release":{"description":"Program's release identifier.","default":null,"type":["string","null"]},"request":{"description":"Information about a web request that occurred during the event.","default":null,"anyOf":[{"$ref":"#/definitions/Request"},{"type":"null"}]},"sdk":{"description":"Information about the Sentry SDK that generated this event.","default":null,"anyOf":[{"$ref":"#/definitions/ClientSdkInfo"},{"type":"null"}]},"server_name":{"description":"Server or device name the event was generated on.","default":null,"type":["string","null"]},"site":{"description":"Deprecated in favor of tags.","default":null,"type":["string","null"]},"spans":{"description":"Spans for tracing.","default":null,"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/Span"},{"type":"null"}]}},"stacktrace":{"description":"Event stacktrace.\n\nDEPRECATED: Prefer `threads` or `exception` depending on which is more appropriate.","default":null,"anyOf":[{"$ref":"#/definitions/Stacktrace"},{"type":"null"}]},"start_timestamp":{"description":"Timestamp when the event has started (relevant for event type = \"transaction\")","default":null,"anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"tags":{"description":"Custom tags for this event.","default":null,"anyOf":[{"$ref":"#/definitions/Tags"},{"type":"null"}]},"threads":{"description":"Threads that were active when the event occurred.","default":null,"type":["object","null"],"required":["values"],"properties":{"values":{"type":"array","items":{"anyOf":[{"$ref":"#/definitions/Thread"},{"type":"null"}]}}}},"time_spent":{"description":"Time since the start of the transaction until the error occurred.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"timestamp":{"description":"Timestamp when the event was created.","default":null,"anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"transaction":{"description":"Transaction name of the event.","default":null,"type":["string","null"]},"type":{"description":"Type of event: error, csp, default","default":null,"anyOf":[{"$ref":"#/definitions/EventType"},{"type":"null"}]},"user":{"description":"Information about the user who triggered this event.","default":null,"anyOf":[{"$ref":"#/definitions/User"},{"type":"null"}]},"version":{"description":"Version","default":null,"type":["string","null"]}}}],"definitions":{"Addr":{"type":"string"},"AppContext":{"anyOf":[{"type":"object","properties":{"app_build":{"description":"Internal build ID as it appears on the platform.","default":null,"type":["string","null"]},"app_identifier":{"description":"App identifier (dotted bundle id).","default":null,"type":["string","null"]},"app_name":{"description":"Application name as it appears on the platform.","default":null,"type":["string","null"]},"app_start_time":{"description":"Start time of the app.","default":null,"type":["string","null"]},"app_version":{"description":"Application version as it appears on the platform.","default":null,"type":["string","null"]},"build_type":{"description":"Build identicator.","default":null,"type":["string","null"]},"device_app_hash":{"description":"Device app hash (app specific device ID)","default":null,"type":["string","null"]}}}]},"AppleDebugImage":{"anyOf":[{"type":"object","required":["image_addr","image_size","name","uuid"],"properties":{"arch":{"description":"CPU architecture target.","default":null,"type":["string","null"]},"cpu_subtype":{"description":"MachO CPU subtype identifier.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"cpu_type":{"description":"MachO CPU type identifier.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"image_addr":{"description":"Starting memory address of the image (required).","anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"image_size":{"description":"Size of the image in bytes (required).","type":["integer","null"],"format":"uint64","minimum":0.0},"image_vmaddr":{"description":"Loading address in virtual memory.","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"name":{"description":"Path and name of the debug image (required).","type":["string","null"]},"uuid":{"description":"The unique UUID of the image.","type":["string","null"],"format":"uuid"}}}]},"Breadcrumb":{"anyOf":[{"type":"object","properties":{"category":{"description":"The optional category of the breadcrumb.","default":null,"type":["string","null"]},"data":{"description":"Custom user-defined data of this breadcrumb.","default":null,"type":["object","null"],"additionalProperties":true},"level":{"description":"Severity level of the breadcrumb.","default":null,"anyOf":[{"$ref":"#/definitions/Level"},{"type":"null"}]},"message":{"description":"Human readable message for the breadcrumb.","default":null,"type":["string","null"]},"timestamp":{"description":"The timestamp of the breadcrumb.","default":null,"anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"type":{"description":"The type of the breadcrumb.","default":null,"type":["string","null"]}}}]},"BrowserContext":{"anyOf":[{"type":"object","properties":{"name":{"description":"Runtime name.","default":null,"type":["string","null"]},"version":{"description":"Runtime version.","default":null,"type":["string","null"]}}}]},"CError":{"anyOf":[{"type":"object","properties":{"name":{"description":"Optional name of the errno constant.","default":null,"type":["string","null"]},"number":{"description":"The error code as specified by ISO C99, POSIX.1-2001 or POSIX.1-2008.","default":null,"type":["integer","null"],"format":"int64"}}}]},"ClientSdkInfo":{"anyOf":[{"type":"object","required":["name","version"],"properties":{"client_ip":{"description":"IP Address of sender??? Seems unused.","default":null,"anyOf":[{"$ref":"#/definitions/String"},{"type":"null"}]},"integrations":{"description":"List of integrations that are enabled in the SDK.","default":null,"type":["array","null"],"items":{"type":["string","null"]}},"name":{"description":"Unique SDK name.","type":["string","null"]},"packages":{"description":"List of installed and loaded SDK packages.","default":null,"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/ClientSdkPackage"},{"type":"null"}]}},"version":{"description":"SDK version.","type":["string","null"]}}}]},"ClientSdkPackage":{"anyOf":[{"type":"object","properties":{"name":{"description":"Name of the package.","default":null,"type":["string","null"]},"version":{"description":"Version of the package.","default":null,"type":["string","null"]}}}]},"CodeId":{"type":"string"},"Context":{"anyOf":[{"$ref":"#/definitions/DeviceContext"},{"$ref":"#/definitions/OsContext"},{"$ref":"#/definitions/RuntimeContext"},{"$ref":"#/definitions/AppContext"},{"$ref":"#/definitions/BrowserContext"},{"$ref":"#/definitions/GpuContext"},{"$ref":"#/definitions/TraceContext"},{"$ref":"#/definitions/MonitorContext"},{"type":"object","additionalProperties":true}]},"ContextInner":{"anyOf":[{"$ref":"#/definitions/Context"}]},"Contexts":{"anyOf":[{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#/definitions/ContextInner"},{"type":"null"}]}}]},"Cookies":{"anyOf":[{"anyOf":[{"type":"object","additionalProperties":{"type":["string","null"]}},{"type":"array","items":{"type":["array","null"],"items":[{"type":["string","null"]},{"type":["string","null"]}],"maxItems":2,"minItems":2}}]}]},"DebugId":{"type":"string"},"DebugImage":{"anyOf":[{"$ref":"#/definitions/AppleDebugImage"},{"$ref":"#/definitions/NativeDebugImage"},{"$ref":"#/definitions/NativeDebugImage"},{"$ref":"#/definitions/NativeDebugImage"},{"$ref":"#/definitions/NativeDebugImage"},{"$ref":"#/definitions/ProguardDebugImage"},{"type":"object","additionalProperties":true}]},"DebugMeta":{"anyOf":[{"type":"object","properties":{"images":{"description":"List of debug information files (debug images).","default":null,"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/DebugImage"},{"type":"null"}]}},"sdk_info":{"description":"Information about the system SDK (e.g. iOS SDK).","default":null,"anyOf":[{"$ref":"#/definitions/SystemSdkInfo"},{"type":"null"}]}}}]},"DeviceContext":{"anyOf":[{"type":"object","properties":{"arch":{"description":"Native cpu architecture of the device.","default":null,"type":["string","null"]},"battery_level":{"description":"Current battery level (0-100).","default":null,"type":["number","null"],"format":"double"},"boot_time":{"description":"Indicator when the device was booted.","default":null,"type":["string","null"]},"brand":{"description":"Brand of the device.","default":null,"type":["string","null"]},"charging":{"description":"Whether the device was charging or not.","default":null,"type":["boolean","null"]},"external_free_storage":{"description":"Free size of the attached external storage in bytes (eg: android SDK card).","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"external_storage_size":{"description":"Total size of the attached external storage in bytes (eg: android SDK card).","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"family":{"description":"Family of the device model.","default":null,"type":["string","null"]},"free_memory":{"description":"How much memory is still available in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"free_storage":{"description":"How much storage is free in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"low_memory":{"description":"Whether the device was low on memory.","default":null,"type":["boolean","null"]},"manufacturer":{"description":"Manufacturer of the device","default":null,"type":["string","null"]},"memory_size":{"description":"Total memory available in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"model":{"description":"Device model (human readable).","default":null,"type":["string","null"]},"model_id":{"description":"Device model (internal identifier).","default":null,"type":["string","null"]},"name":{"description":"Name of the device.","default":null,"type":["string","null"]},"online":{"description":"Whether the device was online or not.","default":null,"type":["boolean","null"]},"orientation":{"description":"Current screen orientation.","default":null,"type":["string","null"]},"screen_density":{"description":"Device screen density.","default":null,"type":["number","null"],"format":"double"},"screen_dpi":{"description":"Screen density as dots-per-inch.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"screen_resolution":{"description":"Device screen resolution.","default":null,"type":["string","null"]},"simulator":{"description":"Simulator/prod indicator.","default":null,"type":["boolean","null"]},"storage_size":{"description":"Total storage size of the device in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"timezone":{"description":"Timezone of the device.","default":null,"type":["string","null"]},"usable_memory":{"description":"How much memory is usable for the app in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0}}}]},"EventId":{"anyOf":[{"type":"string","format":"uuid"}]},"EventProcessingError":{"anyOf":[{"type":"object","required":["type"],"properties":{"name":{"description":"Affected key or deep path.","default":null,"type":["string","null"]},"type":{"description":"The error kind.","type":["string","null"]},"value":{"description":"The original value causing this error.","default":null}}}]},"EventType":{"description":"The type of an event.","type":"string","enum":["error","csp","hpkp","expectct","expectstaple","transaction","default"]},"Exception":{"anyOf":[{"type":"object","properties":{"mechanism":{"description":"Mechanism by which this exception was generated and handled.","default":null,"anyOf":[{"$ref":"#/definitions/Mechanism"},{"type":"null"}]},"module":{"description":"Module name of this exception.","default":null,"type":["string","null"]},"raw_stacktrace":{"description":"Optional unprocessed stack trace.","default":null,"anyOf":[{"$ref":"#/definitions/RawStacktrace"},{"type":"null"}]},"stacktrace":{"description":"Stack trace containing frames of this exception.","default":null,"anyOf":[{"$ref":"#/definitions/Stacktrace"},{"type":"null"}]},"thread_id":{"description":"Identifier of the thread this exception occurred in.","default":null,"anyOf":[{"$ref":"#/definitions/ThreadId"},{"type":"null"}]},"type":{"description":"Exception type. One of value or exception is required, checked in StoreNormalizeProcessor","default":null,"type":["string","null"]},"value":{"description":"Human readable display value.","default":null,"anyOf":[{"$ref":"#/definitions/JsonLenientString"},{"type":"null"}]}}}]},"Fingerprint":{"anyOf":[{"type":"array","items":{"type":"string"}}]},"Frame":{"anyOf":[{"type":"object","properties":{"abs_path":{"description":"Absolute path to the source file.","default":null,"anyOf":[{"$ref":"#/definitions/NativeImagePath"},{"type":"null"}]},"colno":{"description":"Column number within the source file.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"context_line":{"description":"Source code of the current line.","default":null,"type":["string","null"]},"data":{"description":"Auxiliary information about the frame that is platform specific.","default":null,"anyOf":[{"$ref":"#/definitions/FrameData"},{"type":"null"}]},"filename":{"description":"The source file name (basename only).","default":null,"anyOf":[{"$ref":"#/definitions/NativeImagePath"},{"type":"null"}]},"function":{"description":"Name of the frame's function. This might include the name of a class.","default":null,"type":["string","null"]},"image_addr":{"description":"Start address of the containing code module (image).","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"in_app":{"description":"Override whether this frame should be considered in-app.","default":null,"type":["boolean","null"]},"instruction_addr":{"description":"Absolute address of the frame's CPU instruction.","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"lang":{"description":"The language of the frame if it overrides the stacktrace language.","default":null,"type":["string","null"]},"lineno":{"description":"Line number within the source file.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"module":{"description":"Name of the module the frame is contained in.\n\nNote that this might also include a class name if that is something the language natively considers to be part of the stack (for instance in Java).","default":null,"type":["string","null"]},"package":{"description":"Name of the package that contains the frame.\n\nFor instance this can be a dylib for native languages, the name of the jar or .NET assembly.","default":null,"type":["string","null"]},"platform":{"description":"Which platform this frame is from.","default":null,"type":["string","null"]},"post_context":{"description":"Source code of the lines after the current line.","default":null,"type":["array","null"],"items":{"type":["string","null"]}},"pre_context":{"description":"Source code leading up to the current line.","default":null,"type":["array","null"],"items":{"type":["string","null"]}},"raw_function":{"description":"A raw (but potentially truncated) function value.\n\nIf this has the same value as `function` it's best to be omitted.  This exists because on many platforms the function itself contains additional information like overload specifies or a lot of generics which can make it exceed the maximum limit we provide for the field.  In those cases then we cannot reliably trim down the function any more at a later point because the more valuable information has been removed.\n\nThe logic to be applied is that an intelligently trimmed function name should be stored in `function` and the value before trimming is stored in this field instead.  However also this field will be capped at 256 characters at the moment which often means that not the entire original value can be stored.","default":null,"type":["string","null"]},"symbol":{"description":"Potentially mangled name of the symbol as it appears in an executable.\n\nThis is different from a function name by generally being the mangled name that appears natively in the binary.  This is relevant for languages like Swift, C++ or Rust.","default":null,"type":["string","null"]},"symbol_addr":{"description":"Start address of the frame's function.","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"trust":{"description":"Used for native crashes to indicate how much we can \"trust\" the instruction_addr","default":null,"type":["string","null"]},"vars":{"description":"Local variables in a convenient format.","default":null,"anyOf":[{"$ref":"#/definitions/FrameVars"},{"type":"null"}]}}}]},"FrameData":{"anyOf":[{"type":"object","properties":{"orig_colno":{"description":"The original column number.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"orig_filename":{"description":"The original minified filename.","default":null,"type":["string","null"]},"orig_function":{"description":"The original function name before it was resolved.","default":null,"type":["string","null"]},"orig_in_app":{"description":"The original value of the in_app flag before grouping enhancers ran.\n\nBecause we need to handle more cases the following values are used:\n\n- missing / `null`: information not available - `-1`: in_app was set to `null` - `0`: in_app was set to `false` - `1`: in_app was set to `true`","default":null,"type":["integer","null"],"format":"int64"},"orig_lineno":{"description":"The original line number.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"sourcemap":{"description":"A reference to the sourcemap used.","default":null,"type":["string","null"]}}}]},"FrameVars":{"anyOf":[{"type":"object","additionalProperties":true}]},"Geo":{"anyOf":[{"type":"object","properties":{"city":{"description":"Human readable city name.","default":null,"type":["string","null"]},"country_code":{"description":"Two-letter country code (ISO 3166-1 alpha-2).","default":null,"type":["string","null"]},"region":{"description":"Human readable region name or code.","default":null,"type":["string","null"]}}}]},"GpuContext":{"anyOf":[{"type":"object","additionalProperties":true}]},"HeaderName":{"anyOf":[{"type":"string"}]},"HeaderValue":{"anyOf":[{"type":"string"}]},"Headers":{"anyOf":[{"anyOf":[{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#/definitions/HeaderValue"},{"type":"null"}]}},{"type":"array","items":{"type":["array","null"],"items":[{"anyOf":[{"$ref":"#/definitions/HeaderName"},{"type":"null"}]},{"anyOf":[{"$ref":"#/definitions/HeaderValue"},{"type":"null"}]}],"maxItems":2,"minItems":2}}]}]},"JsonLenientString":{"anyOf":[{"type":"string"}]},"Level":{"description":"Severity level of an event or breadcrumb.","type":"string","enum":["debug","info","warning","error","fatal"]},"LogEntry":{"anyOf":[{"type":"object","properties":{"formatted":{"description":"The formatted message","default":null,"anyOf":[{"$ref":"#/definitions/Message"},{"type":"null"}]},"message":{"description":"The log message with parameter placeholders.","default":null,"anyOf":[{"$ref":"#/definitions/Message"},{"type":"null"}]},"params":{"description":"Positional parameters to be interpolated into the log message.","default":null}}}]},"MachException":{"anyOf":[{"type":"object","properties":{"code":{"description":"The mach exception code.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"exception":{"description":"The mach exception type.","default":null,"type":["integer","null"],"format":"int64"},"name":{"description":"Optional name of the mach exception.","default":null,"type":["string","null"]},"subcode":{"description":"The mach exception subcode.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0}}}]},"Mechanism":{"anyOf":[{"type":"object","required":["type"],"properties":{"data":{"description":"Additional attributes depending on the mechanism type.","default":null,"type":["object","null"],"additionalProperties":true},"description":{"description":"Human readable detail description.","default":null,"type":["string","null"]},"handled":{"description":"Flag indicating whether this exception was handled.","default":null,"type":["boolean","null"]},"help_link":{"description":"Link to online resources describing this error.","default":null,"type":["string","null"]},"meta":{"description":"Operating system or runtime meta information.","default":null,"anyOf":[{"$ref":"#/definitions/MechanismMeta"},{"type":"null"}]},"synthetic":{"description":"If this is set then the exception is not a real exception but some form of synthetic error for instance from a signal handler, a hard segfault or similar where type and value are not useful for grouping or display purposes.","default":null,"type":["boolean","null"]},"type":{"description":"Mechanism type (required).","type":["string","null"]}}}]},"MechanismMeta":{"anyOf":[{"type":"object","properties":{"errno":{"description":"Optional ISO C standard error code.","default":null,"anyOf":[{"$ref":"#/definitions/CError"},{"type":"null"}]},"mach_exception":{"description":"Optional mach exception information.","default":null,"anyOf":[{"$ref":"#/definitions/MachException"},{"type":"null"}]},"signal":{"description":"Optional POSIX signal number.","default":null,"anyOf":[{"$ref":"#/definitions/PosixSignal"},{"type":"null"}]}}}]},"Message":{"anyOf":[{"type":"string"}]},"MonitorContext":{"anyOf":[{"type":"object","additionalProperties":true}]},"NativeDebugImage":{"anyOf":[{"type":"object","required":["code_file","debug_id","image_addr","image_size"],"properties":{"arch":{"description":"CPU architecture target.","default":null,"type":["string","null"]},"code_file":{"description":"Path and name of the image file (required).","anyOf":[{"$ref":"#/definitions/NativeImagePath"},{"type":"null"}]},"code_id":{"description":"Optional identifier of the code file.\n\nIf not specified, it is assumed to be identical to the debug identifier.","default":null,"anyOf":[{"$ref":"#/definitions/CodeId"},{"type":"null"}]},"debug_file":{"description":"Path and name of the debug companion file (required).","default":null,"anyOf":[{"$ref":"#/definitions/NativeImagePath"},{"type":"null"}]},"debug_id":{"description":"Unique debug identifier of the image.","anyOf":[{"$ref":"#/definitions/DebugId"},{"type":"null"}]},"image_addr":{"description":"Starting memory address of the image (required).","anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"image_size":{"description":"Size of the image in bytes (required).","type":["integer","null"],"format":"uint64","minimum":0.0},"image_vmaddr":{"description":"Loading address in virtual memory.","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]}}}]},"NativeImagePath":{"anyOf":[{"type":"string"}]},"OsContext":{"anyOf":[{"type":"object","properties":{"build":{"description":"Internal build number of the operating system.","default":null,"type":["string","null"]},"kernel_version":{"description":"Current kernel version.","default":null,"type":["string","null"]},"name":{"description":"Name of the operating system.","default":null,"type":["string","null"]},"raw_description":{"description":"Unprocessed operating system info.","default":null,"type":["string","null"]},"rooted":{"description":"Indicator if the OS is rooted (mobile mostly).","default":null,"type":["boolean","null"]},"version":{"description":"Version of the operating system.","default":null,"type":["string","null"]}}}]},"PosixSignal":{"anyOf":[{"type":"object","properties":{"code":{"description":"An optional signal code present on Apple systems.","default":null,"type":["integer","null"],"format":"int64"},"code_name":{"description":"Optional name of the errno constant.","default":null,"type":["string","null"]},"name":{"description":"Optional name of the errno constant.","default":null,"type":["string","null"]},"number":{"description":"The POSIX signal number.","default":null,"type":["integer","null"],"format":"int64"}}}]},"ProguardDebugImage":{"anyOf":[{"type":"object","required":["uuid"],"properties":{"uuid":{"description":"UUID computed from the file contents.","type":["string","null"],"format":"uuid"}}}]},"Query":{"anyOf":[{"anyOf":[{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#/definitions/JsonLenientString"},{"type":"null"}]}},{"type":"array","items":{"type":["array","null"],"items":[{"type":["string","null"]},{"anyOf":[{"$ref":"#/definitions/JsonLenientString"},{"type":"null"}]}],"maxItems":2,"minItems":2}}]}]},"RawStacktrace":{"anyOf":[{"type":"object","required":["frames"],"properties":{"frames":{"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/Frame"},{"type":"null"}]}},"lang":{"description":"The language of the stacktrace.","default":null,"type":["string","null"]},"registers":{"description":"Register values of the thread (top frame).","default":null,"type":["object","null"],"additionalProperties":{"anyOf":[{"$ref":"#/definitions/RegVal"},{"type":"null"}]}}}}]},"RegVal":{"type":"string"},"Request":{"anyOf":[{"type":"object","properties":{"cookies":{"description":"URL encoded contents of the Cookie header.","default":null,"anyOf":[{"$ref":"#/definitions/Cookies"},{"type":"null"}]},"data":{"description":"Request data in any format that makes sense.","default":null},"env":{"description":"Server environment data, such as CGI/WSGI.","default":null,"type":["object","null"],"additionalProperties":true},"fragment":{"description":"The fragment of the request URL.","default":null,"type":["string","null"]},"headers":{"description":"HTTP request headers.","default":null,"anyOf":[{"$ref":"#/definitions/Headers"},{"type":"null"}]},"inferred_content_type":{"description":"The inferred content type of the request payload.","default":null,"type":["string","null"]},"method":{"description":"HTTP request method.","default":null,"type":["string","null"]},"query_string":{"description":"URL encoded HTTP query string.","default":null,"anyOf":[{"$ref":"#/definitions/Query"},{"type":"null"}]},"url":{"description":"URL of the request.","default":null,"type":["string","null"]}}}]},"RuntimeContext":{"anyOf":[{"type":"object","properties":{"build":{"description":"Application build string, if it is separate from the version.","default":null,"type":["string","null"]},"name":{"description":"Runtime name.","default":null,"type":["string","null"]},"raw_description":{"description":"Unprocessed runtime info.","default":null,"type":["string","null"]},"version":{"description":"Runtime version string.","default":null,"type":["string","null"]}}}]},"Span":{"anyOf":[{"type":"object","required":["span_id","start_timestamp","timestamp","trace_id"],"properties":{"description":{"description":"Human readable description of a span (e.g. method URL).","default":null,"type":["string","null"]},"op":{"description":"Span type (see `OperationType` docs).","default":null,"type":["string","null"]},"parent_span_id":{"description":"The ID of the span enclosing this span.","default":null,"anyOf":[{"$ref":"#/definitions/SpanId"},{"type":"null"}]},"span_id":{"description":"The Span id.","anyOf":[{"$ref":"#/definitions/SpanId"},{"type":"null"}]},"start_timestamp":{"description":"Timestamp when the span started.","anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"status":{"description":"The status of a span","default":null,"anyOf":[{"$ref":"#/definitions/SpanStatus"},{"type":"null"}]},"timestamp":{"description":"Timestamp when the span was ended.","anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"trace_id":{"description":"The ID of the trace the span belongs to.","anyOf":[{"$ref":"#/definitions/TraceId"},{"type":"null"}]}}}]},"SpanId":{"anyOf":[{"type":"string"}]},"SpanStatus":{"description":"Trace status.\n\nValues from https://github.com/open-telemetry/opentelemetry-specification/blob/8fb6c14e4709e75a9aaa64b0dbbdf02a6067682a/specification/api-tracing.md#status Mapping to HTTP from https://github.com/open-telemetry/opentelemetry-specification/blob/8fb6c14e4709e75a9aaa64b0dbbdf02a6067682a/specification/data-http.md#status","type":"string","enum":["ok","cancelled","unknown","invalid_argument","deadline_exceeded","not_found","already_exists","permission_denied","resource_exhausted","failed_precondition","aborted","out_of_range","unimplemented","internal_error","unavailable","data_loss","unauthenticated"]},"Stacktrace":{"anyOf":[{"$ref":"#/definitions/RawStacktrace"}]},"String":{"type":"string"},"SystemSdkInfo":{"anyOf":[{"type":"object","properties":{"sdk_name":{"description":"The internal name of the SDK.","default":null,"type":["string","null"]},"version_major":{"description":"The major version of the SDK as integer or 0.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"version_minor":{"description":"The minor version of the SDK as integer or 0.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"version_patchlevel":{"description":"The patch version of the SDK as integer or 0.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0}}}]},"TagEntry":{"anyOf":[{"type":"array","items":[{"type":["string","null"]},{"type":["string","null"]}],"maxItems":2,"minItems":2}]},"Tags":{"anyOf":[{"anyOf":[{"type":"object","additionalProperties":{"type":["string","null"]}},{"type":"array","items":{"anyOf":[{"$ref":"#/definitions/TagEntry"},{"type":"null"}]}}]}]},"Thread":{"anyOf":[{"type":"object","properties":{"crashed":{"description":"Indicates that this thread requested the event (usually by crashing).","default":null,"type":["boolean","null"]},"current":{"description":"Indicates that the thread was not suspended when the event was created.","default":null,"type":["boolean","null"]},"id":{"description":"Identifier of this thread within the process (usually an integer).","default":null,"anyOf":[{"$ref":"#/definitions/ThreadId"},{"type":"null"}]},"name":{"description":"Display name of this thread.","default":null,"type":["string","null"]},"raw_stacktrace":{"description":"Optional unprocessed stack trace.","default":null,"anyOf":[{"$ref":"#/definitions/RawStacktrace"},{"type":"null"}]},"stacktrace":{"description":"Stack trace containing frames of this exception.","default":null,"anyOf":[{"$ref":"#/definitions/Stacktrace"},{"type":"null"}]}}}]},"ThreadId":{"anyOf":[{"type":"integer","format":"uint64","minimum":0.0},{"type":"string"}]},"Timestamp":{"description":"Can be a ISO-8601 formatted string or a unix timestamp in seconds (floating point values allowed).\n\nMust be UTC.","anyOf":[{"type":"number","format":"double"},{"type":"string"}]},"TraceContext":{"anyOf":[{"type":"object","required":["span_id","status","trace_id"],"properties":{"op":{"description":"Span type (see `OperationType` docs).","default":null,"type":["string","null"]},"parent_span_id":{"description":"The ID of the span enclosing this span.","default":null,"anyOf":[{"$ref":"#/definitions/SpanId"},{"type":"null"}]},"span_id":{"description":"The ID of the span.","anyOf":[{"$ref":"#/definitions/SpanId"},{"type":"null"}]},"status":{"description":"Whether the trace failed or succeeded. Currently only used to indicate status of individual transactions.","anyOf":[{"$ref":"#/definitions/SpanStatus"},{"type":"null"}]},"trace_id":{"description":"The trace ID.","anyOf":[{"$ref":"#/definitions/TraceId"},{"type":"null"}]}}}]},"TraceId":{"anyOf":[{"type":"string"}]},"User":{"anyOf":[{"type":"object","properties":{"data":{"description":"Additional arbitrary fields, as stored in the database (and sometimes as sent by clients). All data from `self.other` should end up here after store normalization.","default":null,"type":["object","null"],"additionalProperties":true},"email":{"description":"Email address of the user.","default":null,"type":["string","null"]},"geo":{"description":"Approximate geographical location of the end user or device.","default":null,"anyOf":[{"$ref":"#/definitions/Geo"},{"type":"null"}]},"id":{"description":"Unique identifier of the user.","default":null,"type":["string","null"]},"ip_address":{"description":"Remote IP address of the user. Defaults to \"{{auto}}\".","default":null,"anyOf":[{"$ref":"#/definitions/String"},{"type":"null"}]},"name":{"description":"Human readable name of the user.","default":null,"type":["string","null"]},"username":{"description":"Username of the user.","default":null,"type":["string","null"]}}}]}}}
diff --git a/mypy.ini b/mypy.ini
index 7b217649582..08e823b3e78 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -1,4 +1,6 @@
 [mypy]
+plugins = jsonschema_typed.plugin
+python_version = 3.8
 ignore_missing_imports = False
 
 [mypy-_strptime]
diff --git a/requirements.txt b/requirements.txt
index 2019b94a18f..ded7171f4f4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -19,13 +19,14 @@ honcho==1.0.1
 idna==2.7
 itsdangerous==0.24
 Jinja2==2.10.1
-jsonschema==3.0.1
+jsonschema==3.2.0
 lz4==2.0.0
 Markdown==2.6.11
 MarkupSafe==1.1.1
 mywsgi==1.0.3
 more-itertools==4.2.0
 mypy>=0.761
+git+https://github.com/untitaker/jsonschema-typed@df4a6a39c787c549cc361fb84730f6f643f15e8c
 packaging==17.1
 parsimonious==0.8.1
 py==1.5.3
diff --git a/snuba/datasets/events_processor.py b/snuba/datasets/events_processor.py
index 98a977f03b8..150fa85ca48 100644
--- a/snuba/datasets/events_processor.py
+++ b/snuba/datasets/events_processor.py
@@ -1,4 +1,4 @@
-from typing import Any, Mapping, MutableMapping, Optional
+from typing import Any, Mapping, MutableMapping, Optional, TypedDict
 
 import logging
 import _strptime  # NOQA fixes _strptime deferred import issue
@@ -6,7 +6,7 @@
 from snuba.clickhouse.columns import ColumnSet
 from snuba.consumer import KafkaMessageMetadata
 from snuba.datasets.events_format import extract_user
-from snuba.datasets.events_processor_base import EventsProcessorBase
+from snuba.datasets.events_processor_base import EventsProcessorBase, Event
 from snuba.processor import (
     _as_dict_safe,
     _boolify,
@@ -32,18 +32,18 @@ def extract_promoted_tags(
             }
         )
 
-    def _should_process(self, event: Mapping[str, Any]) -> bool:
+    def _should_process(self, event: Event) -> bool:
         return True
 
     def _extract_event_id(
-        self, output: MutableMapping[str, Any], event: Mapping[str, Any],
+        self, output: MutableMapping[str, Any], event: Event,
     ) -> None:
         output["event_id"] = event["event_id"]
 
     def extract_custom(
         self,
         output: MutableMapping[str, Any],
-        event: Mapping[str, Any],
+        event: Event,
         metadata: Optional[KafkaMessageMetadata] = None,
     ) -> None:
         data = event.get("data", {})
@@ -85,7 +85,7 @@ def extract_custom(
     def extract_tags_custom(
         self,
         output: MutableMapping[str, Any],
-        event: Mapping[str, Any],
+        event: Event,
         tags: Mapping[str, Any],
         metadata: Optional[KafkaMessageMetadata] = None,
     ) -> None:
@@ -145,7 +145,7 @@ def extract_promoted_contexts(
     def extract_contexts_custom(
         self,
         output: MutableMapping[str, Any],
-        event: Mapping[str, Any],
+        event: Event,
         tags: Mapping[str, Any],
         metadata: Optional[KafkaMessageMetadata] = None,
     ) -> None:
diff --git a/snuba/datasets/events_processor_base.py b/snuba/datasets/events_processor_base.py
index 645c1104485..87d27c91373 100644
--- a/snuba/datasets/events_processor_base.py
+++ b/snuba/datasets/events_processor_base.py
@@ -1,7 +1,7 @@
 import logging
 from abc import ABC, abstractmethod
 from datetime import datetime
-from typing import Any, Mapping, MutableMapping, Optional, Sequence
+from typing import Any, Mapping, MutableMapping, Optional, Sequence, TypedDict
 
 from snuba import settings
 from snuba.consumer import KafkaMessageMetadata
@@ -27,6 +27,16 @@
     _unicodify,
 )
 
+from jsonschema_typed import JSONSchema
+
+EventData = JSONSchema['/Users/untitaker/projects/snuba/event.schema.json']
+
+class Event(TypedDict):
+    data: EventData
+    search_message: Any
+    message: Any
+    event_id: Any
+
 logger = logging.getLogger(__name__)
 
 
@@ -36,12 +46,12 @@ class EventsProcessorBase(MessageProcessor, ABC):
     """
 
     @abstractmethod
-    def _should_process(self, event: Mapping[str, Any]) -> bool:
+    def _should_process(self, event: Event) -> bool:
         raise NotImplementedError
 
     @abstractmethod
     def _extract_event_id(
-        self, output: MutableMapping[str, Any], event: Mapping[str, Any],
+        self, output: MutableMapping[str, Any], event: Event,
     ) -> None:
         raise NotImplementedError
 
@@ -49,7 +59,7 @@ def _extract_event_id(
     def extract_custom(
         self,
         output: MutableMapping[str, Any],
-        event: Mapping[str, Any],
+        event: Event,
         metadata: Optional[KafkaMessageMetadata] = None,
     ) -> None:
         raise NotImplementedError
@@ -64,7 +74,7 @@ def extract_promoted_tags(
     def extract_tags_custom(
         self,
         output: MutableMapping[str, Any],
-        event: Mapping[str, Any],
+        event: Event,
         tags: Mapping[str, Any],
         metadata: Optional[KafkaMessageMetadata] = None,
     ) -> None:
@@ -83,14 +93,15 @@ def extract_promoted_contexts(
     def extract_contexts_custom(
         self,
         output: MutableMapping[str, Any],
-        event: Mapping[str, Any],
+        event: Event,
         contexts: Mapping[str, Any],
         metadata: Optional[KafkaMessageMetadata] = None,
     ) -> None:
         raise NotImplementedError
 
     def extract_required(
-        self, output: MutableMapping[str, Any], event: Mapping[str, Any]
+        self, output: MutableMapping[str, Any], 
+        event: Event,
     ) -> None:
         output["group_id"] = event["group_id"] or 0
 
@@ -194,12 +205,12 @@ def process_message(
         return ProcessedMessage(action=action_type, data=[processed])
 
     def process_insert(
-        self, event: Mapping[str, Any], metadata: Optional[KafkaMessageMetadata] = None
+        self, event: Event, metadata: Optional[KafkaMessageMetadata] = None
     ) -> Optional[Mapping[str, Any]]:
         if not self._should_process(event):
             return None
 
-        processed = {"deleted": 0}
+        processed= {"deleted": 0}
         extract_project_id(processed, event)
         self._extract_event_id(processed, event)
         processed["retention_days"] = enforce_retention(
@@ -252,7 +263,7 @@ def process_insert(
     def extract_common(
         self,
         output: MutableMapping[str, Any],
-        event: Mapping[str, Any],
+        event: Event,
         metadata: Optional[KafkaMessageMetadata] = None,
     ) -> None:
         # Properties we get from the top level of the message payload

From 26dd2516a8907064063966123fbdbe40b2dbea76 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Tue, 4 Aug 2020 11:24:58 -0700
Subject: [PATCH 02/17] Replace event with data (#1197)

The jsonschema produced by relay only covers event["data"] since that is the public facing event.
Using event[data] when possible.
---
 snuba/datasets/events_processor.py      |  4 ++--
 snuba/datasets/events_processor_base.py | 18 +++++++++---------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/snuba/datasets/events_processor.py b/snuba/datasets/events_processor.py
index 150fa85ca48..1ab545930b6 100644
--- a/snuba/datasets/events_processor.py
+++ b/snuba/datasets/events_processor.py
@@ -1,4 +1,4 @@
-from typing import Any, Mapping, MutableMapping, Optional, TypedDict
+from typing import Any, Mapping, MutableMapping, Optional
 
 import logging
 import _strptime  # NOQA fixes _strptime deferred import issue
@@ -38,7 +38,7 @@ def _should_process(self, event: Event) -> bool:
     def _extract_event_id(
         self, output: MutableMapping[str, Any], event: Event,
     ) -> None:
-        output["event_id"] = event["event_id"]
+        output["event_id"] = event["data"]["event_id"]
 
     def extract_custom(
         self,
diff --git a/snuba/datasets/events_processor_base.py b/snuba/datasets/events_processor_base.py
index 87d27c91373..98d0df5c22f 100644
--- a/snuba/datasets/events_processor_base.py
+++ b/snuba/datasets/events_processor_base.py
@@ -29,7 +29,8 @@
 
 from jsonschema_typed import JSONSchema
 
-EventData = JSONSchema['/Users/untitaker/projects/snuba/event.schema.json']
+EventData = JSONSchema["/Users/untitaker/projects/snuba/event.schema.json"]
+
 
 class Event(TypedDict):
     data: EventData
@@ -37,6 +38,7 @@ class Event(TypedDict):
     message: Any
     event_id: Any
 
+
 logger = logging.getLogger(__name__)
 
 
@@ -99,14 +101,12 @@ def extract_contexts_custom(
     ) -> None:
         raise NotImplementedError
 
-    def extract_required(
-        self, output: MutableMapping[str, Any], 
-        event: Event,
-    ) -> None:
+    def extract_required(self, output: MutableMapping[str, Any], event: Event,) -> None:
         output["group_id"] = event["group_id"] or 0
 
         # This is not ideal but it should never happen anyways
         timestamp = _ensure_valid_date(
+            # TODO: Switch to using event["data"]["timestamp"]
             datetime.strptime(event["datetime"], settings.PAYLOAD_DATETIME_FORMAT)
         )
         if timestamp is None:
@@ -210,7 +210,7 @@ def process_insert(
         if not self._should_process(event):
             return None
 
-        processed= {"deleted": 0}
+        processed = {"deleted": 0}
         extract_project_id(processed, event)
         self._extract_event_id(processed, event)
         processed["retention_days"] = enforce_retention(
@@ -267,16 +267,16 @@ def extract_common(
         metadata: Optional[KafkaMessageMetadata] = None,
     ) -> None:
         # Properties we get from the top level of the message payload
-        output["platform"] = _unicodify(event["platform"])
+        data = event.get("data", {})
+        output["platform"] = _unicodify(data["platform"])
         output["primary_hash"] = _hashify(event["primary_hash"])
 
         # Properties we get from the "data" dict, which is the actual event body.
-        data = event.get("data", {})
+
         received = _collapse_uint32(int(data["received"]))
         output["received"] = (
             datetime.utcfromtimestamp(received) if received is not None else None
         )
-
         output["culprit"] = _unicodify(data.get("culprit", None))
         output["type"] = _unicodify(data.get("type", None))
         output["version"] = _unicodify(data.get("version", None))

From 1354941f47ed4fdc9980210d45d9fdf31f926679 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Tue, 4 Aug 2020 14:19:26 -0700
Subject: [PATCH 03/17] Re-fix tests (#1200)

The previous PR #1197 broke two tests.
I am investigating what the issue is (I suspect the tests are wrong), but this is needed to get a green build
---
 snuba/datasets/events_processor.py      | 2 +-
 snuba/datasets/events_processor_base.py | 6 +-----
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/snuba/datasets/events_processor.py b/snuba/datasets/events_processor.py
index 6402c7fb357..88b00281616 100644
--- a/snuba/datasets/events_processor.py
+++ b/snuba/datasets/events_processor.py
@@ -31,7 +31,7 @@ def _should_process(self, event: InsertEvent) -> bool:
     def _extract_event_id(
         self, output: MutableMapping[str, Any], event: InsertEvent,
     ) -> None:
-        output["event_id"] = event["data"]["event_id"]
+        output["event_id"] = event["event_id"]
 
     def extract_custom(
         self,
diff --git a/snuba/datasets/events_processor_base.py b/snuba/datasets/events_processor_base.py
index 3344523726f..fc39904ce62 100644
--- a/snuba/datasets/events_processor_base.py
+++ b/snuba/datasets/events_processor_base.py
@@ -28,13 +28,9 @@
     _unicodify,
 )
 
-from jsonschema_typed import JSONSchema
-
 EventData = JSONSchema["/Users/untitaker/projects/snuba/event.schema.json"]
 
 
-
-
 logger = logging.getLogger(__name__)
 
 
@@ -242,7 +238,7 @@ def extract_common(
     ) -> None:
         # Properties we get from the top level of the message payload
         data = event.get("data", {})
-        output["platform"] = _unicodify(data["platform"])
+        output["platform"] = _unicodify(event["platform"])
         output["primary_hash"] = _hashify(event["primary_hash"])
 
         # Properties we get from the "data" dict, which is the actual event body.

From 0bfb66040d2f2f270258f118ef82cc901866c4a6 Mon Sep 17 00:00:00 2001
From: dbennett-sentry <64794809+dbennett-sentry@users.noreply.github.com>
Date: Tue, 4 Aug 2020 17:49:33 -0400
Subject: [PATCH 04/17] Hackweek: Added Makefile entry to fetch schema;
 eliminate type errors (#1198)

* Added Makefile entry to fetch schema; eliminate type errors
* Added package name to custom requirement for setuptools
* Add 3.7-safe import
---
 Makefile                                |  7 +++-
 requirements.txt                        |  2 +-
 snuba/datasets/events_processor.py      | 15 +++++++--
 snuba/datasets/events_processor_base.py | 44 ++++++++++++++++++-------
 4 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/Makefile b/Makefile
index b22baefd954..dec3338054e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 .PHONY: develop setup-git test install-python-dependencies
 
-develop: install-python-dependencies setup-git
+develop: install-python-dependencies setup-git fetchschemas
 
 setup-git:
 	pip install 'pre-commit==2.4.0'
@@ -11,3 +11,8 @@ test:
 
 install-python-dependencies:
 	pip install -e .
+
+fetchschemas:
+	mkdir -p schema
+	curl https://getsentry.github.io/relay/event-schema/event.schema.json -o schema/event.schema.json
+.PHONY: fetchschemas
diff --git a/requirements.txt b/requirements.txt
index a77f92968e5..a1723b1f4e0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -26,7 +26,7 @@ MarkupSafe==1.1.1
 mywsgi==1.0.3
 more-itertools==4.2.0
 mypy>=0.761
-git+https://github.com/untitaker/jsonschema-typed@df4a6a39c787c549cc361fb84730f6f643f15e8c
+jsonschema-typed-v2 @ git+https://github.com/untitaker/jsonschema-typed@df4a6a39c787c549cc361fb84730f6f643f15e8c#egg=jsonschema-typed-v2
 packaging==17.1
 parsimonious==0.8.1
 py==1.5.3
diff --git a/snuba/datasets/events_processor.py b/snuba/datasets/events_processor.py
index 88b00281616..e30804d1890 100644
--- a/snuba/datasets/events_processor.py
+++ b/snuba/datasets/events_processor.py
@@ -40,17 +40,26 @@ def extract_custom(
         metadata: KafkaMessageMetadata,
     ) -> None:
         data = event.get("data", {})
-
         output["message"] = _unicodify(event["message"])
 
         # USER REQUEST GEO
-        user = data.get("user", data.get("sentry.interfaces.User", None)) or {}
+        user = (
+            data.get(
+                "user", data.get("sentry.interfaces.User", None)  # type: ignore
+            )
+            or {}
+        )
         extract_user(output, user)
 
         geo = user.get("geo", None) or {}
         self.extract_geo(output, geo)
 
-        http = data.get("request", data.get("sentry.interfaces.Http", None)) or {}
+        http = (
+            data.get(
+                "request", data.get("sentry.interfaces.Http", None)  # type: ignore
+            )
+            or {}
+        )  # types: ignore
         self.extract_http(output, http)
 
     def extract_tags_custom(
diff --git a/snuba/datasets/events_processor_base.py b/snuba/datasets/events_processor_base.py
index fc39904ce62..d617df62312 100644
--- a/snuba/datasets/events_processor_base.py
+++ b/snuba/datasets/events_processor_base.py
@@ -1,7 +1,8 @@
 import logging
+import sys
 from abc import ABC, abstractmethod
 from datetime import datetime
-from typing import Any, Mapping, MutableMapping, Optional, Sequence, TypedDict
+from typing import Any, Mapping, MutableMapping, Optional, Sequence
 
 from jsonschema_typed import JSONSchema
 from snuba import settings
@@ -28,11 +29,26 @@
     _unicodify,
 )
 
-EventData = JSONSchema["/Users/untitaker/projects/snuba/event.schema.json"]
-
+# Required until we are 100% on Py 3.8
+if sys.version_info >= (3, 8):
+    from typing import TypedDict  # pylint: disable=no-name-in-module
+else:
+    from typing_extensions import TypedDict
 
 logger = logging.getLogger(__name__)
 
+EventData = JSONSchema["schema/event.schema.json"]
+
+
+class Event(TypedDict):
+    data: EventData
+    search_message: Any
+    message: Any
+    event_id: Any
+    datetime: str
+    group_id: str
+    primary_hash: str
+
 
 REPLACEMENT_EVENT_TYPES = frozenset(
     [
@@ -149,7 +165,7 @@ def extract_sdk(
         output["sdk_integrations"] = sdk_integrations
 
     def process_message(
-        self, message, metadata: KafkaMessageMetadata
+        self, message: Event, metadata: Optional[KafkaMessageMetadata]
     ) -> Optional[ProcessedMessage]:
         """\
         Process a raw message into an insertion or replacement batch. Returns
@@ -180,10 +196,12 @@ def process_message(
     def process_insert(
         self, event: InsertEvent, metadata: KafkaMessageMetadata
     ) -> Optional[Mapping[str, Any]]:
+
         if not self._should_process(event):
             return None
 
-        processed = {"deleted": 0}
+        processed: MutableMapping[str, Any] = {"deleted": 0}
+
         extract_project_id(processed, event)
         self._extract_event_id(processed, event)
         processed["retention_days"] = enforce_retention(
@@ -201,7 +219,7 @@ def process_insert(
         self.extract_common(processed, event, metadata)
         self.extract_custom(processed, event, metadata)
 
-        sdk = data.get("sdk", None) or {}
+        sdk = data.get("sdk", None) or {}  # type: ignore
         self.extract_sdk(processed, sdk)
 
         tags = _as_dict_safe(data.get("tags", None))
@@ -219,9 +237,13 @@ def process_insert(
         processed["_tags_flattened"] = ""
 
         exception = (
-            data.get("exception", data.get("sentry.interfaces.Exception", None)) or {}
+            data.get(
+                "exception",
+                data.get("sentry.interfaces.Exception", None),  # type: ignore
+            )
+            or {}
         )
-        stacks = exception.get("values", None) or []
+        stacks: Sequence[Any] = exception.get("values", None) or []
         self.extract_stacktraces(processed, stacks)
 
         processed["offset"] = metadata.offset
@@ -243,15 +265,15 @@ def extract_common(
 
         # Properties we get from the "data" dict, which is the actual event body.
 
-        received = _collapse_uint32(int(data["received"]))
+        received = _collapse_uint32(data["received"])
         output["received"] = (
             datetime.utcfromtimestamp(received) if received is not None else None
         )
         output["culprit"] = _unicodify(data.get("culprit", None))
         output["type"] = _unicodify(data.get("type", None))
         output["version"] = _unicodify(data.get("version", None))
-        output["title"] = _unicodify(data.get("title", None))
-        output["location"] = _unicodify(data.get("location", None))
+        output["title"] = _unicodify(data.get("title", None))  # type: ignore
+        output["location"] = _unicodify(data.get("location", None))  # type: ignore
 
         module_names = []
         module_versions = []

From f5823b2ebb0ae72edcb59923863dcd5657d5f7cc Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Wed, 5 Aug 2020 10:54:52 -0700
Subject: [PATCH 05/17] fix(hackweek): Use the correct event Typed Dict in
 event processor base. (#1201)

When I merged master I forgot to remove the duplicate Event type. Now there is only one and it has the right structure.
---
 snuba/datasets/errors_processor.py      |  1 -
 snuba/datasets/events_processor_base.py | 19 +++++--------------
 2 files changed, 5 insertions(+), 15 deletions(-)

diff --git a/snuba/datasets/errors_processor.py b/snuba/datasets/errors_processor.py
index 03b686dea67..f67610ccad6 100644
--- a/snuba/datasets/errors_processor.py
+++ b/snuba/datasets/errors_processor.py
@@ -47,7 +47,6 @@ def extract_custom(
     ) -> None:
         data = event.get("data", {})
         user_dict = data.get("user", data.get("sentry.interfaces.User", None)) or {}
-
         user_data: MutableMapping[str, Any] = {}
         extract_user(user_data, user_dict)
         output["user_name"] = user_data["username"]
diff --git a/snuba/datasets/events_processor_base.py b/snuba/datasets/events_processor_base.py
index d617df62312..2a4a04d8d4d 100644
--- a/snuba/datasets/events_processor_base.py
+++ b/snuba/datasets/events_processor_base.py
@@ -37,19 +37,6 @@
 
 logger = logging.getLogger(__name__)
 
-EventData = JSONSchema["schema/event.schema.json"]
-
-
-class Event(TypedDict):
-    data: EventData
-    search_message: Any
-    message: Any
-    event_id: Any
-    datetime: str
-    group_id: str
-    primary_hash: str
-
-
 REPLACEMENT_EVENT_TYPES = frozenset(
     [
         "start_delete_groups",
@@ -63,6 +50,8 @@ class Event(TypedDict):
     ]
 )
 
+EventData = JSONSchema["schema/event.schema.json"]
+
 
 class InsertEvent(TypedDict):
     group_id: Optional[int]
@@ -75,6 +64,7 @@ class InsertEvent(TypedDict):
     data: EventData
     primary_hash: str  # empty string represents None
     retention_days: int
+    search_message: Any
 
 
 class EventsProcessorBase(MessageProcessor, ABC):
@@ -165,7 +155,7 @@ def extract_sdk(
         output["sdk_integrations"] = sdk_integrations
 
     def process_message(
-        self, message: Event, metadata: Optional[KafkaMessageMetadata]
+        self, message, metadata: KafkaMessageMetadata
     ) -> Optional[ProcessedMessage]:
         """\
         Process a raw message into an insertion or replacement batch. Returns
@@ -176,6 +166,7 @@ def process_message(
             raise InvalidMessageVersion(f"Unsupported message version: {version}")
 
         # version 2: (2, type, data, [state])
+        event: InsertEvent
         type_, event = message[1:3]
         if type_ == "insert":
             try:

From 9fc5fee7793b4ca36b50c716c545cfb013641ac2 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Thu, 6 Aug 2020 12:58:27 -0700
Subject: [PATCH 06/17] Take the schema from the schema repo (#1203)

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index dec3338054e..b4f3cd4f6f0 100644
--- a/Makefile
+++ b/Makefile
@@ -14,5 +14,5 @@ install-python-dependencies:
 
 fetchschemas:
 	mkdir -p schema
-	curl https://getsentry.github.io/relay/event-schema/event.schema.json -o schema/event.schema.json
+	curl https://raw.githubusercontent.com/getsentry/sentry-data-schemas/main/relay/event.schema.json -o schema/event.schema.json
 .PHONY: fetchschemas

From ce6d4e2396842dde119443081cafca956c4c6c20 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Thu, 6 Aug 2020 17:15:43 -0700
Subject: [PATCH 07/17] feat(hackweek) Remove merged jsonschema and validate it
 is downloaded properly. (#1202)

Removes the jsonschema initially committed since we download the schema during make develop and avoid accidentally merge the schema downloaded during make.

Also runs mypy right after downloading the schema. If the schema is not there, malformed or in the wrong place mypy fails with code 2. Then make will fail instead of silently be ok until we run it later.
---
 .gitignore        | 1 +
 Makefile          | 7 ++++---
 event.schema.json | 1 -
 3 files changed, 5 insertions(+), 4 deletions(-)
 delete mode 100644 event.schema.json

diff --git a/.gitignore b/.gitignore
index f26bd307f36..fd8e04364cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@
 .venv
 htmlcov/
 snuba.egg-info/
+schema/
diff --git a/Makefile b/Makefile
index b4f3cd4f6f0..41b572320c7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 .PHONY: develop setup-git test install-python-dependencies
 
-develop: install-python-dependencies setup-git fetchschemas
+develop: install-python-dependencies setup-git fetch-and-validate-schema
 
 setup-git:
 	pip install 'pre-commit==2.4.0'
@@ -12,7 +12,8 @@ test:
 install-python-dependencies:
 	pip install -e .
 
-fetchschemas:
+fetch-and-validate-schema:
 	mkdir -p schema
 	curl https://raw.githubusercontent.com/getsentry/sentry-data-schemas/main/relay/event.schema.json -o schema/event.schema.json
-.PHONY: fetchschemas
+	mypy snuba > /dev/null || (if [ "$$?" -gt 1 ]; then exit 1; fi)
+.PHONY: fetch-and-validate-schema
diff --git a/event.schema.json b/event.schema.json
deleted file mode 100644
index ce365c72a7f..00000000000
--- a/event.schema.json
+++ /dev/null
@@ -1 +0,0 @@
-{"$schema":"http://json-schema.org/draft-07/schema#","title":"Event","anyOf":[{"type":"object","properties":{"breadcrumbs":{"description":"List of breadcrumbs recorded before this event.","default":null,"type":["object","null"],"required":["values"],"properties":{"values":{"type":"array","items":{"anyOf":[{"$ref":"#/definitions/Breadcrumb"},{"type":"null"}]}}}},"contexts":{"description":"Contexts describing the environment (e.g. device, os or browser).","default":null,"anyOf":[{"$ref":"#/definitions/Contexts"},{"type":"null"}]},"culprit":{"description":"Custom culprit of the event.","default":null,"type":["string","null"]},"debug_meta":{"description":"Meta data for event processing and debugging.","default":null,"anyOf":[{"$ref":"#/definitions/DebugMeta"},{"type":"null"}]},"dist":{"description":"Program's distribution identifier.","default":null,"type":["string","null"]},"environment":{"description":"Environment the environment was generated in (\"production\" or \"development\").","default":null,"type":["string","null"]},"errors":{"description":"Errors encountered during processing. Intended to be phased out in favor of annotation/metadata system.","default":null,"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/EventProcessingError"},{"type":"null"}]}},"event_id":{"description":"Unique identifier of this event.","default":null,"anyOf":[{"$ref":"#/definitions/EventId"},{"type":"null"}]},"exception":{"description":"One or multiple chained (nested) exceptions.","default":null,"type":["object","null"],"required":["values"],"properties":{"values":{"type":"array","items":{"anyOf":[{"$ref":"#/definitions/Exception"},{"type":"null"}]}}}},"extra":{"description":"Arbitrary extra information set by the user.","default":null,"type":["object","null"],"additionalProperties":true},"fingerprint":{"description":"Manual fingerprint override.","default":null,"anyOf":[{"$ref":"#/definitions/Fingerprint"},{"type":"null"}]},"key_id":{"description":"Project key which sent this event.","default":null,"type":["string","null"]},"level":{"description":"Severity level of the event.","default":null,"anyOf":[{"$ref":"#/definitions/Level"},{"type":"null"}]},"logentry":{"description":"Custom parameterized message for this event.","default":null,"anyOf":[{"$ref":"#/definitions/LogEntry"},{"type":"null"}]},"logger":{"description":"Logger that created the event.","default":null,"type":["string","null"]},"modules":{"description":"Name and versions of installed modules.","default":null,"type":["object","null"],"additionalProperties":{"type":["string","null"]}},"platform":{"description":"Platform identifier of this event (defaults to \"other\").","default":null,"type":["string","null"]},"project":{"description":"Project which sent this event.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"received":{"description":"Timestamp when the event has been received by Sentry.","default":null,"anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"release":{"description":"Program's release identifier.","default":null,"type":["string","null"]},"request":{"description":"Information about a web request that occurred during the event.","default":null,"anyOf":[{"$ref":"#/definitions/Request"},{"type":"null"}]},"sdk":{"description":"Information about the Sentry SDK that generated this event.","default":null,"anyOf":[{"$ref":"#/definitions/ClientSdkInfo"},{"type":"null"}]},"server_name":{"description":"Server or device name the event was generated on.","default":null,"type":["string","null"]},"site":{"description":"Deprecated in favor of tags.","default":null,"type":["string","null"]},"spans":{"description":"Spans for tracing.","default":null,"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/Span"},{"type":"null"}]}},"stacktrace":{"description":"Event stacktrace.\n\nDEPRECATED: Prefer `threads` or `exception` depending on which is more appropriate.","default":null,"anyOf":[{"$ref":"#/definitions/Stacktrace"},{"type":"null"}]},"start_timestamp":{"description":"Timestamp when the event has started (relevant for event type = \"transaction\")","default":null,"anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"tags":{"description":"Custom tags for this event.","default":null,"anyOf":[{"$ref":"#/definitions/Tags"},{"type":"null"}]},"threads":{"description":"Threads that were active when the event occurred.","default":null,"type":["object","null"],"required":["values"],"properties":{"values":{"type":"array","items":{"anyOf":[{"$ref":"#/definitions/Thread"},{"type":"null"}]}}}},"time_spent":{"description":"Time since the start of the transaction until the error occurred.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"timestamp":{"description":"Timestamp when the event was created.","default":null,"anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"transaction":{"description":"Transaction name of the event.","default":null,"type":["string","null"]},"type":{"description":"Type of event: error, csp, default","default":null,"anyOf":[{"$ref":"#/definitions/EventType"},{"type":"null"}]},"user":{"description":"Information about the user who triggered this event.","default":null,"anyOf":[{"$ref":"#/definitions/User"},{"type":"null"}]},"version":{"description":"Version","default":null,"type":["string","null"]}}}],"definitions":{"Addr":{"type":"string"},"AppContext":{"anyOf":[{"type":"object","properties":{"app_build":{"description":"Internal build ID as it appears on the platform.","default":null,"type":["string","null"]},"app_identifier":{"description":"App identifier (dotted bundle id).","default":null,"type":["string","null"]},"app_name":{"description":"Application name as it appears on the platform.","default":null,"type":["string","null"]},"app_start_time":{"description":"Start time of the app.","default":null,"type":["string","null"]},"app_version":{"description":"Application version as it appears on the platform.","default":null,"type":["string","null"]},"build_type":{"description":"Build identicator.","default":null,"type":["string","null"]},"device_app_hash":{"description":"Device app hash (app specific device ID)","default":null,"type":["string","null"]}}}]},"AppleDebugImage":{"anyOf":[{"type":"object","required":["image_addr","image_size","name","uuid"],"properties":{"arch":{"description":"CPU architecture target.","default":null,"type":["string","null"]},"cpu_subtype":{"description":"MachO CPU subtype identifier.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"cpu_type":{"description":"MachO CPU type identifier.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"image_addr":{"description":"Starting memory address of the image (required).","anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"image_size":{"description":"Size of the image in bytes (required).","type":["integer","null"],"format":"uint64","minimum":0.0},"image_vmaddr":{"description":"Loading address in virtual memory.","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"name":{"description":"Path and name of the debug image (required).","type":["string","null"]},"uuid":{"description":"The unique UUID of the image.","type":["string","null"],"format":"uuid"}}}]},"Breadcrumb":{"anyOf":[{"type":"object","properties":{"category":{"description":"The optional category of the breadcrumb.","default":null,"type":["string","null"]},"data":{"description":"Custom user-defined data of this breadcrumb.","default":null,"type":["object","null"],"additionalProperties":true},"level":{"description":"Severity level of the breadcrumb.","default":null,"anyOf":[{"$ref":"#/definitions/Level"},{"type":"null"}]},"message":{"description":"Human readable message for the breadcrumb.","default":null,"type":["string","null"]},"timestamp":{"description":"The timestamp of the breadcrumb.","default":null,"anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"type":{"description":"The type of the breadcrumb.","default":null,"type":["string","null"]}}}]},"BrowserContext":{"anyOf":[{"type":"object","properties":{"name":{"description":"Runtime name.","default":null,"type":["string","null"]},"version":{"description":"Runtime version.","default":null,"type":["string","null"]}}}]},"CError":{"anyOf":[{"type":"object","properties":{"name":{"description":"Optional name of the errno constant.","default":null,"type":["string","null"]},"number":{"description":"The error code as specified by ISO C99, POSIX.1-2001 or POSIX.1-2008.","default":null,"type":["integer","null"],"format":"int64"}}}]},"ClientSdkInfo":{"anyOf":[{"type":"object","required":["name","version"],"properties":{"client_ip":{"description":"IP Address of sender??? Seems unused.","default":null,"anyOf":[{"$ref":"#/definitions/String"},{"type":"null"}]},"integrations":{"description":"List of integrations that are enabled in the SDK.","default":null,"type":["array","null"],"items":{"type":["string","null"]}},"name":{"description":"Unique SDK name.","type":["string","null"]},"packages":{"description":"List of installed and loaded SDK packages.","default":null,"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/ClientSdkPackage"},{"type":"null"}]}},"version":{"description":"SDK version.","type":["string","null"]}}}]},"ClientSdkPackage":{"anyOf":[{"type":"object","properties":{"name":{"description":"Name of the package.","default":null,"type":["string","null"]},"version":{"description":"Version of the package.","default":null,"type":["string","null"]}}}]},"CodeId":{"type":"string"},"Context":{"anyOf":[{"$ref":"#/definitions/DeviceContext"},{"$ref":"#/definitions/OsContext"},{"$ref":"#/definitions/RuntimeContext"},{"$ref":"#/definitions/AppContext"},{"$ref":"#/definitions/BrowserContext"},{"$ref":"#/definitions/GpuContext"},{"$ref":"#/definitions/TraceContext"},{"$ref":"#/definitions/MonitorContext"},{"type":"object","additionalProperties":true}]},"ContextInner":{"anyOf":[{"$ref":"#/definitions/Context"}]},"Contexts":{"anyOf":[{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#/definitions/ContextInner"},{"type":"null"}]}}]},"Cookies":{"anyOf":[{"anyOf":[{"type":"object","additionalProperties":{"type":["string","null"]}},{"type":"array","items":{"type":["array","null"],"items":[{"type":["string","null"]},{"type":["string","null"]}],"maxItems":2,"minItems":2}}]}]},"DebugId":{"type":"string"},"DebugImage":{"anyOf":[{"$ref":"#/definitions/AppleDebugImage"},{"$ref":"#/definitions/NativeDebugImage"},{"$ref":"#/definitions/NativeDebugImage"},{"$ref":"#/definitions/NativeDebugImage"},{"$ref":"#/definitions/NativeDebugImage"},{"$ref":"#/definitions/ProguardDebugImage"},{"type":"object","additionalProperties":true}]},"DebugMeta":{"anyOf":[{"type":"object","properties":{"images":{"description":"List of debug information files (debug images).","default":null,"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/DebugImage"},{"type":"null"}]}},"sdk_info":{"description":"Information about the system SDK (e.g. iOS SDK).","default":null,"anyOf":[{"$ref":"#/definitions/SystemSdkInfo"},{"type":"null"}]}}}]},"DeviceContext":{"anyOf":[{"type":"object","properties":{"arch":{"description":"Native cpu architecture of the device.","default":null,"type":["string","null"]},"battery_level":{"description":"Current battery level (0-100).","default":null,"type":["number","null"],"format":"double"},"boot_time":{"description":"Indicator when the device was booted.","default":null,"type":["string","null"]},"brand":{"description":"Brand of the device.","default":null,"type":["string","null"]},"charging":{"description":"Whether the device was charging or not.","default":null,"type":["boolean","null"]},"external_free_storage":{"description":"Free size of the attached external storage in bytes (eg: android SDK card).","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"external_storage_size":{"description":"Total size of the attached external storage in bytes (eg: android SDK card).","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"family":{"description":"Family of the device model.","default":null,"type":["string","null"]},"free_memory":{"description":"How much memory is still available in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"free_storage":{"description":"How much storage is free in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"low_memory":{"description":"Whether the device was low on memory.","default":null,"type":["boolean","null"]},"manufacturer":{"description":"Manufacturer of the device","default":null,"type":["string","null"]},"memory_size":{"description":"Total memory available in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"model":{"description":"Device model (human readable).","default":null,"type":["string","null"]},"model_id":{"description":"Device model (internal identifier).","default":null,"type":["string","null"]},"name":{"description":"Name of the device.","default":null,"type":["string","null"]},"online":{"description":"Whether the device was online or not.","default":null,"type":["boolean","null"]},"orientation":{"description":"Current screen orientation.","default":null,"type":["string","null"]},"screen_density":{"description":"Device screen density.","default":null,"type":["number","null"],"format":"double"},"screen_dpi":{"description":"Screen density as dots-per-inch.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"screen_resolution":{"description":"Device screen resolution.","default":null,"type":["string","null"]},"simulator":{"description":"Simulator/prod indicator.","default":null,"type":["boolean","null"]},"storage_size":{"description":"Total storage size of the device in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"timezone":{"description":"Timezone of the device.","default":null,"type":["string","null"]},"usable_memory":{"description":"How much memory is usable for the app in bytes.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0}}}]},"EventId":{"anyOf":[{"type":"string","format":"uuid"}]},"EventProcessingError":{"anyOf":[{"type":"object","required":["type"],"properties":{"name":{"description":"Affected key or deep path.","default":null,"type":["string","null"]},"type":{"description":"The error kind.","type":["string","null"]},"value":{"description":"The original value causing this error.","default":null}}}]},"EventType":{"description":"The type of an event.","type":"string","enum":["error","csp","hpkp","expectct","expectstaple","transaction","default"]},"Exception":{"anyOf":[{"type":"object","properties":{"mechanism":{"description":"Mechanism by which this exception was generated and handled.","default":null,"anyOf":[{"$ref":"#/definitions/Mechanism"},{"type":"null"}]},"module":{"description":"Module name of this exception.","default":null,"type":["string","null"]},"raw_stacktrace":{"description":"Optional unprocessed stack trace.","default":null,"anyOf":[{"$ref":"#/definitions/RawStacktrace"},{"type":"null"}]},"stacktrace":{"description":"Stack trace containing frames of this exception.","default":null,"anyOf":[{"$ref":"#/definitions/Stacktrace"},{"type":"null"}]},"thread_id":{"description":"Identifier of the thread this exception occurred in.","default":null,"anyOf":[{"$ref":"#/definitions/ThreadId"},{"type":"null"}]},"type":{"description":"Exception type. One of value or exception is required, checked in StoreNormalizeProcessor","default":null,"type":["string","null"]},"value":{"description":"Human readable display value.","default":null,"anyOf":[{"$ref":"#/definitions/JsonLenientString"},{"type":"null"}]}}}]},"Fingerprint":{"anyOf":[{"type":"array","items":{"type":"string"}}]},"Frame":{"anyOf":[{"type":"object","properties":{"abs_path":{"description":"Absolute path to the source file.","default":null,"anyOf":[{"$ref":"#/definitions/NativeImagePath"},{"type":"null"}]},"colno":{"description":"Column number within the source file.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"context_line":{"description":"Source code of the current line.","default":null,"type":["string","null"]},"data":{"description":"Auxiliary information about the frame that is platform specific.","default":null,"anyOf":[{"$ref":"#/definitions/FrameData"},{"type":"null"}]},"filename":{"description":"The source file name (basename only).","default":null,"anyOf":[{"$ref":"#/definitions/NativeImagePath"},{"type":"null"}]},"function":{"description":"Name of the frame's function. This might include the name of a class.","default":null,"type":["string","null"]},"image_addr":{"description":"Start address of the containing code module (image).","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"in_app":{"description":"Override whether this frame should be considered in-app.","default":null,"type":["boolean","null"]},"instruction_addr":{"description":"Absolute address of the frame's CPU instruction.","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"lang":{"description":"The language of the frame if it overrides the stacktrace language.","default":null,"type":["string","null"]},"lineno":{"description":"Line number within the source file.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"module":{"description":"Name of the module the frame is contained in.\n\nNote that this might also include a class name if that is something the language natively considers to be part of the stack (for instance in Java).","default":null,"type":["string","null"]},"package":{"description":"Name of the package that contains the frame.\n\nFor instance this can be a dylib for native languages, the name of the jar or .NET assembly.","default":null,"type":["string","null"]},"platform":{"description":"Which platform this frame is from.","default":null,"type":["string","null"]},"post_context":{"description":"Source code of the lines after the current line.","default":null,"type":["array","null"],"items":{"type":["string","null"]}},"pre_context":{"description":"Source code leading up to the current line.","default":null,"type":["array","null"],"items":{"type":["string","null"]}},"raw_function":{"description":"A raw (but potentially truncated) function value.\n\nIf this has the same value as `function` it's best to be omitted.  This exists because on many platforms the function itself contains additional information like overload specifies or a lot of generics which can make it exceed the maximum limit we provide for the field.  In those cases then we cannot reliably trim down the function any more at a later point because the more valuable information has been removed.\n\nThe logic to be applied is that an intelligently trimmed function name should be stored in `function` and the value before trimming is stored in this field instead.  However also this field will be capped at 256 characters at the moment which often means that not the entire original value can be stored.","default":null,"type":["string","null"]},"symbol":{"description":"Potentially mangled name of the symbol as it appears in an executable.\n\nThis is different from a function name by generally being the mangled name that appears natively in the binary.  This is relevant for languages like Swift, C++ or Rust.","default":null,"type":["string","null"]},"symbol_addr":{"description":"Start address of the frame's function.","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"trust":{"description":"Used for native crashes to indicate how much we can \"trust\" the instruction_addr","default":null,"type":["string","null"]},"vars":{"description":"Local variables in a convenient format.","default":null,"anyOf":[{"$ref":"#/definitions/FrameVars"},{"type":"null"}]}}}]},"FrameData":{"anyOf":[{"type":"object","properties":{"orig_colno":{"description":"The original column number.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"orig_filename":{"description":"The original minified filename.","default":null,"type":["string","null"]},"orig_function":{"description":"The original function name before it was resolved.","default":null,"type":["string","null"]},"orig_in_app":{"description":"The original value of the in_app flag before grouping enhancers ran.\n\nBecause we need to handle more cases the following values are used:\n\n- missing / `null`: information not available - `-1`: in_app was set to `null` - `0`: in_app was set to `false` - `1`: in_app was set to `true`","default":null,"type":["integer","null"],"format":"int64"},"orig_lineno":{"description":"The original line number.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"sourcemap":{"description":"A reference to the sourcemap used.","default":null,"type":["string","null"]}}}]},"FrameVars":{"anyOf":[{"type":"object","additionalProperties":true}]},"Geo":{"anyOf":[{"type":"object","properties":{"city":{"description":"Human readable city name.","default":null,"type":["string","null"]},"country_code":{"description":"Two-letter country code (ISO 3166-1 alpha-2).","default":null,"type":["string","null"]},"region":{"description":"Human readable region name or code.","default":null,"type":["string","null"]}}}]},"GpuContext":{"anyOf":[{"type":"object","additionalProperties":true}]},"HeaderName":{"anyOf":[{"type":"string"}]},"HeaderValue":{"anyOf":[{"type":"string"}]},"Headers":{"anyOf":[{"anyOf":[{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#/definitions/HeaderValue"},{"type":"null"}]}},{"type":"array","items":{"type":["array","null"],"items":[{"anyOf":[{"$ref":"#/definitions/HeaderName"},{"type":"null"}]},{"anyOf":[{"$ref":"#/definitions/HeaderValue"},{"type":"null"}]}],"maxItems":2,"minItems":2}}]}]},"JsonLenientString":{"anyOf":[{"type":"string"}]},"Level":{"description":"Severity level of an event or breadcrumb.","type":"string","enum":["debug","info","warning","error","fatal"]},"LogEntry":{"anyOf":[{"type":"object","properties":{"formatted":{"description":"The formatted message","default":null,"anyOf":[{"$ref":"#/definitions/Message"},{"type":"null"}]},"message":{"description":"The log message with parameter placeholders.","default":null,"anyOf":[{"$ref":"#/definitions/Message"},{"type":"null"}]},"params":{"description":"Positional parameters to be interpolated into the log message.","default":null}}}]},"MachException":{"anyOf":[{"type":"object","properties":{"code":{"description":"The mach exception code.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"exception":{"description":"The mach exception type.","default":null,"type":["integer","null"],"format":"int64"},"name":{"description":"Optional name of the mach exception.","default":null,"type":["string","null"]},"subcode":{"description":"The mach exception subcode.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0}}}]},"Mechanism":{"anyOf":[{"type":"object","required":["type"],"properties":{"data":{"description":"Additional attributes depending on the mechanism type.","default":null,"type":["object","null"],"additionalProperties":true},"description":{"description":"Human readable detail description.","default":null,"type":["string","null"]},"handled":{"description":"Flag indicating whether this exception was handled.","default":null,"type":["boolean","null"]},"help_link":{"description":"Link to online resources describing this error.","default":null,"type":["string","null"]},"meta":{"description":"Operating system or runtime meta information.","default":null,"anyOf":[{"$ref":"#/definitions/MechanismMeta"},{"type":"null"}]},"synthetic":{"description":"If this is set then the exception is not a real exception but some form of synthetic error for instance from a signal handler, a hard segfault or similar where type and value are not useful for grouping or display purposes.","default":null,"type":["boolean","null"]},"type":{"description":"Mechanism type (required).","type":["string","null"]}}}]},"MechanismMeta":{"anyOf":[{"type":"object","properties":{"errno":{"description":"Optional ISO C standard error code.","default":null,"anyOf":[{"$ref":"#/definitions/CError"},{"type":"null"}]},"mach_exception":{"description":"Optional mach exception information.","default":null,"anyOf":[{"$ref":"#/definitions/MachException"},{"type":"null"}]},"signal":{"description":"Optional POSIX signal number.","default":null,"anyOf":[{"$ref":"#/definitions/PosixSignal"},{"type":"null"}]}}}]},"Message":{"anyOf":[{"type":"string"}]},"MonitorContext":{"anyOf":[{"type":"object","additionalProperties":true}]},"NativeDebugImage":{"anyOf":[{"type":"object","required":["code_file","debug_id","image_addr","image_size"],"properties":{"arch":{"description":"CPU architecture target.","default":null,"type":["string","null"]},"code_file":{"description":"Path and name of the image file (required).","anyOf":[{"$ref":"#/definitions/NativeImagePath"},{"type":"null"}]},"code_id":{"description":"Optional identifier of the code file.\n\nIf not specified, it is assumed to be identical to the debug identifier.","default":null,"anyOf":[{"$ref":"#/definitions/CodeId"},{"type":"null"}]},"debug_file":{"description":"Path and name of the debug companion file (required).","default":null,"anyOf":[{"$ref":"#/definitions/NativeImagePath"},{"type":"null"}]},"debug_id":{"description":"Unique debug identifier of the image.","anyOf":[{"$ref":"#/definitions/DebugId"},{"type":"null"}]},"image_addr":{"description":"Starting memory address of the image (required).","anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]},"image_size":{"description":"Size of the image in bytes (required).","type":["integer","null"],"format":"uint64","minimum":0.0},"image_vmaddr":{"description":"Loading address in virtual memory.","default":null,"anyOf":[{"$ref":"#/definitions/Addr"},{"type":"null"}]}}}]},"NativeImagePath":{"anyOf":[{"type":"string"}]},"OsContext":{"anyOf":[{"type":"object","properties":{"build":{"description":"Internal build number of the operating system.","default":null,"type":["string","null"]},"kernel_version":{"description":"Current kernel version.","default":null,"type":["string","null"]},"name":{"description":"Name of the operating system.","default":null,"type":["string","null"]},"raw_description":{"description":"Unprocessed operating system info.","default":null,"type":["string","null"]},"rooted":{"description":"Indicator if the OS is rooted (mobile mostly).","default":null,"type":["boolean","null"]},"version":{"description":"Version of the operating system.","default":null,"type":["string","null"]}}}]},"PosixSignal":{"anyOf":[{"type":"object","properties":{"code":{"description":"An optional signal code present on Apple systems.","default":null,"type":["integer","null"],"format":"int64"},"code_name":{"description":"Optional name of the errno constant.","default":null,"type":["string","null"]},"name":{"description":"Optional name of the errno constant.","default":null,"type":["string","null"]},"number":{"description":"The POSIX signal number.","default":null,"type":["integer","null"],"format":"int64"}}}]},"ProguardDebugImage":{"anyOf":[{"type":"object","required":["uuid"],"properties":{"uuid":{"description":"UUID computed from the file contents.","type":["string","null"],"format":"uuid"}}}]},"Query":{"anyOf":[{"anyOf":[{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#/definitions/JsonLenientString"},{"type":"null"}]}},{"type":"array","items":{"type":["array","null"],"items":[{"type":["string","null"]},{"anyOf":[{"$ref":"#/definitions/JsonLenientString"},{"type":"null"}]}],"maxItems":2,"minItems":2}}]}]},"RawStacktrace":{"anyOf":[{"type":"object","required":["frames"],"properties":{"frames":{"type":["array","null"],"items":{"anyOf":[{"$ref":"#/definitions/Frame"},{"type":"null"}]}},"lang":{"description":"The language of the stacktrace.","default":null,"type":["string","null"]},"registers":{"description":"Register values of the thread (top frame).","default":null,"type":["object","null"],"additionalProperties":{"anyOf":[{"$ref":"#/definitions/RegVal"},{"type":"null"}]}}}}]},"RegVal":{"type":"string"},"Request":{"anyOf":[{"type":"object","properties":{"cookies":{"description":"URL encoded contents of the Cookie header.","default":null,"anyOf":[{"$ref":"#/definitions/Cookies"},{"type":"null"}]},"data":{"description":"Request data in any format that makes sense.","default":null},"env":{"description":"Server environment data, such as CGI/WSGI.","default":null,"type":["object","null"],"additionalProperties":true},"fragment":{"description":"The fragment of the request URL.","default":null,"type":["string","null"]},"headers":{"description":"HTTP request headers.","default":null,"anyOf":[{"$ref":"#/definitions/Headers"},{"type":"null"}]},"inferred_content_type":{"description":"The inferred content type of the request payload.","default":null,"type":["string","null"]},"method":{"description":"HTTP request method.","default":null,"type":["string","null"]},"query_string":{"description":"URL encoded HTTP query string.","default":null,"anyOf":[{"$ref":"#/definitions/Query"},{"type":"null"}]},"url":{"description":"URL of the request.","default":null,"type":["string","null"]}}}]},"RuntimeContext":{"anyOf":[{"type":"object","properties":{"build":{"description":"Application build string, if it is separate from the version.","default":null,"type":["string","null"]},"name":{"description":"Runtime name.","default":null,"type":["string","null"]},"raw_description":{"description":"Unprocessed runtime info.","default":null,"type":["string","null"]},"version":{"description":"Runtime version string.","default":null,"type":["string","null"]}}}]},"Span":{"anyOf":[{"type":"object","required":["span_id","start_timestamp","timestamp","trace_id"],"properties":{"description":{"description":"Human readable description of a span (e.g. method URL).","default":null,"type":["string","null"]},"op":{"description":"Span type (see `OperationType` docs).","default":null,"type":["string","null"]},"parent_span_id":{"description":"The ID of the span enclosing this span.","default":null,"anyOf":[{"$ref":"#/definitions/SpanId"},{"type":"null"}]},"span_id":{"description":"The Span id.","anyOf":[{"$ref":"#/definitions/SpanId"},{"type":"null"}]},"start_timestamp":{"description":"Timestamp when the span started.","anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"status":{"description":"The status of a span","default":null,"anyOf":[{"$ref":"#/definitions/SpanStatus"},{"type":"null"}]},"timestamp":{"description":"Timestamp when the span was ended.","anyOf":[{"$ref":"#/definitions/Timestamp"},{"type":"null"}]},"trace_id":{"description":"The ID of the trace the span belongs to.","anyOf":[{"$ref":"#/definitions/TraceId"},{"type":"null"}]}}}]},"SpanId":{"anyOf":[{"type":"string"}]},"SpanStatus":{"description":"Trace status.\n\nValues from https://github.com/open-telemetry/opentelemetry-specification/blob/8fb6c14e4709e75a9aaa64b0dbbdf02a6067682a/specification/api-tracing.md#status Mapping to HTTP from https://github.com/open-telemetry/opentelemetry-specification/blob/8fb6c14e4709e75a9aaa64b0dbbdf02a6067682a/specification/data-http.md#status","type":"string","enum":["ok","cancelled","unknown","invalid_argument","deadline_exceeded","not_found","already_exists","permission_denied","resource_exhausted","failed_precondition","aborted","out_of_range","unimplemented","internal_error","unavailable","data_loss","unauthenticated"]},"Stacktrace":{"anyOf":[{"$ref":"#/definitions/RawStacktrace"}]},"String":{"type":"string"},"SystemSdkInfo":{"anyOf":[{"type":"object","properties":{"sdk_name":{"description":"The internal name of the SDK.","default":null,"type":["string","null"]},"version_major":{"description":"The major version of the SDK as integer or 0.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"version_minor":{"description":"The minor version of the SDK as integer or 0.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0},"version_patchlevel":{"description":"The patch version of the SDK as integer or 0.","default":null,"type":["integer","null"],"format":"uint64","minimum":0.0}}}]},"TagEntry":{"anyOf":[{"type":"array","items":[{"type":["string","null"]},{"type":["string","null"]}],"maxItems":2,"minItems":2}]},"Tags":{"anyOf":[{"anyOf":[{"type":"object","additionalProperties":{"type":["string","null"]}},{"type":"array","items":{"anyOf":[{"$ref":"#/definitions/TagEntry"},{"type":"null"}]}}]}]},"Thread":{"anyOf":[{"type":"object","properties":{"crashed":{"description":"Indicates that this thread requested the event (usually by crashing).","default":null,"type":["boolean","null"]},"current":{"description":"Indicates that the thread was not suspended when the event was created.","default":null,"type":["boolean","null"]},"id":{"description":"Identifier of this thread within the process (usually an integer).","default":null,"anyOf":[{"$ref":"#/definitions/ThreadId"},{"type":"null"}]},"name":{"description":"Display name of this thread.","default":null,"type":["string","null"]},"raw_stacktrace":{"description":"Optional unprocessed stack trace.","default":null,"anyOf":[{"$ref":"#/definitions/RawStacktrace"},{"type":"null"}]},"stacktrace":{"description":"Stack trace containing frames of this exception.","default":null,"anyOf":[{"$ref":"#/definitions/Stacktrace"},{"type":"null"}]}}}]},"ThreadId":{"anyOf":[{"type":"integer","format":"uint64","minimum":0.0},{"type":"string"}]},"Timestamp":{"description":"Can be a ISO-8601 formatted string or a unix timestamp in seconds (floating point values allowed).\n\nMust be UTC.","anyOf":[{"type":"number","format":"double"},{"type":"string"}]},"TraceContext":{"anyOf":[{"type":"object","required":["span_id","status","trace_id"],"properties":{"op":{"description":"Span type (see `OperationType` docs).","default":null,"type":["string","null"]},"parent_span_id":{"description":"The ID of the span enclosing this span.","default":null,"anyOf":[{"$ref":"#/definitions/SpanId"},{"type":"null"}]},"span_id":{"description":"The ID of the span.","anyOf":[{"$ref":"#/definitions/SpanId"},{"type":"null"}]},"status":{"description":"Whether the trace failed or succeeded. Currently only used to indicate status of individual transactions.","anyOf":[{"$ref":"#/definitions/SpanStatus"},{"type":"null"}]},"trace_id":{"description":"The trace ID.","anyOf":[{"$ref":"#/definitions/TraceId"},{"type":"null"}]}}}]},"TraceId":{"anyOf":[{"type":"string"}]},"User":{"anyOf":[{"type":"object","properties":{"data":{"description":"Additional arbitrary fields, as stored in the database (and sometimes as sent by clients). All data from `self.other` should end up here after store normalization.","default":null,"type":["object","null"],"additionalProperties":true},"email":{"description":"Email address of the user.","default":null,"type":["string","null"]},"geo":{"description":"Approximate geographical location of the end user or device.","default":null,"anyOf":[{"$ref":"#/definitions/Geo"},{"type":"null"}]},"id":{"description":"Unique identifier of the user.","default":null,"type":["string","null"]},"ip_address":{"description":"Remote IP address of the user. Defaults to \"{{auto}}\".","default":null,"anyOf":[{"$ref":"#/definitions/String"},{"type":"null"}]},"name":{"description":"Human readable name of the user.","default":null,"type":["string","null"]},"username":{"description":"Username of the user.","default":null,"type":["string","null"]}}}]}}}

From 6ada6bfc4b07a9c6d03b79c779c427c3f20f5ccd Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Wed, 9 Sep 2020 21:21:54 -0700
Subject: [PATCH 08/17] Fix import and python version

---
 requirements.txt                        |  2 +-
 snuba/datasets/events_processor_base.py | 10 ++--------
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/requirements.txt b/requirements.txt
index e6f2ae265df..5cc0f2a8f3a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -26,7 +26,7 @@ MarkupSafe==1.1.1
 mywsgi==1.0.3
 more-itertools==4.2.0
 mypy>=0.761
-jsonschema-typed-v2 @ git+https://github.com/untitaker/jsonschema-typed@df4a6a39c787c549cc361fb84730f6f643f15e8c#egg=jsonschema-typed-v2
+jsonschema-typed-v2==0.8.0
 packaging==17.1
 parsimonious==0.8.1
 py==1.5.3
diff --git a/snuba/datasets/events_processor_base.py b/snuba/datasets/events_processor_base.py
index 2a4a04d8d4d..e1ebc02f922 100644
--- a/snuba/datasets/events_processor_base.py
+++ b/snuba/datasets/events_processor_base.py
@@ -1,10 +1,10 @@
 import logging
-import sys
 from abc import ABC, abstractmethod
 from datetime import datetime
-from typing import Any, Mapping, MutableMapping, Optional, Sequence
+from typing import Any, Mapping, MutableMapping, Optional, Sequence, TypedDict
 
 from jsonschema_typed import JSONSchema
+
 from snuba import settings
 from snuba.consumer import KafkaMessageMetadata
 from snuba.datasets.events_format import (
@@ -29,12 +29,6 @@
     _unicodify,
 )
 
-# Required until we are 100% on Py 3.8
-if sys.version_info >= (3, 8):
-    from typing import TypedDict  # pylint: disable=no-name-in-module
-else:
-    from typing_extensions import TypedDict
-
 logger = logging.getLogger(__name__)
 
 REPLACEMENT_EVENT_TYPES = frozenset(

From 016323e995218bbee997d8d30d9d6a7b3862659a Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Thu, 10 Sep 2020 12:20:51 -0700
Subject: [PATCH 09/17] update readme

---
 README.md | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 7d8770e9bda..1f4b81faa15 100644
--- a/README.md
+++ b/README.md
@@ -36,8 +36,7 @@ A quick way to get these services running is to set up sentry, then use:
 
     mkvirtualenv snuba --python=python3.7
     workon snuba
-    make install-python-dependencies
-    make setup-git
+    make develop
 
     # Run API server
     snuba api

From 69c83b19925110dcce8958cff063b326a46cea57 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Mon, 21 Sep 2020 22:39:11 -0700
Subject: [PATCH 10/17] Code review comments

---
 .gitignore                              | 2 +-
 Makefile                                | 4 ++--
 snuba/datasets/events_processor.py      | 9 ++-------
 snuba/datasets/events_processor_base.py | 7 +++----
 4 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/.gitignore b/.gitignore
index fd8e04364cd..aeeb3c273af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,4 @@
 .venv
 htmlcov/
 snuba.egg-info/
-schema/
+schemas/
diff --git a/Makefile b/Makefile
index 8a09e03a0df..a1bfdef41de 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ install-python-dependencies:
 	pip install -e .
 
 fetch-and-validate-schema:
-	mkdir -p schema
-	curl https://raw.githubusercontent.com/getsentry/sentry-data-schemas/main/relay/event.schema.json -o schema/event.schema.json
+	mkdir -p schemas
+	curl https://raw.githubusercontent.com/getsentry/sentry-data-schemas/main/relay/event.schema.json -o schemas/event.schema.json
 	mypy snuba > /dev/null || (if [ "$$?" -gt 1 ]; then exit 1; fi)
 .PHONY: fetch-and-validate-schema
diff --git a/snuba/datasets/events_processor.py b/snuba/datasets/events_processor.py
index e8a42d97b4b..e74995ec073 100644
--- a/snuba/datasets/events_processor.py
+++ b/snuba/datasets/events_processor.py
@@ -1,17 +1,12 @@
+import _strptime  # NOQA fixes _strptime deferred import issue
 import logging
 from typing import Any, Mapping, MutableMapping
 
-import _strptime  # NOQA fixes _strptime deferred import issue
 from snuba.clickhouse.columns import ColumnSet
 from snuba.consumer import KafkaMessageMetadata
 from snuba.datasets.events_format import extract_http, extract_user
 from snuba.datasets.events_processor_base import EventsProcessorBase, InsertEvent
-from snuba.processor import (
-    _boolify,
-    _floatify,
-    _unicodify,
-)
-
+from snuba.processor import _boolify, _floatify, _unicodify
 
 logger = logging.getLogger("snuba.processor")
 
diff --git a/snuba/datasets/events_processor_base.py b/snuba/datasets/events_processor_base.py
index e1ebc02f922..266592d31ad 100644
--- a/snuba/datasets/events_processor_base.py
+++ b/snuba/datasets/events_processor_base.py
@@ -1,7 +1,7 @@
 import logging
 from abc import ABC, abstractmethod
 from datetime import datetime
-from typing import Any, Mapping, MutableMapping, Optional, Sequence, TypedDict
+from typing import Any, cast, Mapping, MutableMapping, Optional, Sequence, TypedDict
 
 from jsonschema_typed import JSONSchema
 
@@ -44,7 +44,7 @@
     ]
 )
 
-EventData = JSONSchema["schema/event.schema.json"]
+EventData = JSONSchema["schemas/event.schema.json"]
 
 
 class InsertEvent(TypedDict):
@@ -160,11 +160,10 @@ def process_message(
             raise InvalidMessageVersion(f"Unsupported message version: {version}")
 
         # version 2: (2, type, data, [state])
-        event: InsertEvent
         type_, event = message[1:3]
         if type_ == "insert":
             try:
-                row = self.process_insert(event, metadata)
+                row = self.process_insert(cast(InsertEvent, event), metadata)
             except EventTooOld:
                 return None
 

From c9fda8e3233f6eaaf507dd319db5315202f6398d Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Mon, 21 Sep 2020 23:21:15 -0700
Subject: [PATCH 11/17] Add post merge hook

---
 config/hooks/post-merge | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/config/hooks/post-merge b/config/hooks/post-merge
index dcb24e7f126..f500897883b 100755
--- a/config/hooks/post-merge
+++ b/config/hooks/post-merge
@@ -4,6 +4,17 @@ red="$(tput setaf 1)"
 bold="$(tput bold)"
 reset="$(tput sgr0)"
 
+# Ensures up to data event schemas are downloaded
+mkdir -p schemas
+curl https://raw.githubusercontent.com/getsentry/sentry-data-schemas/main/relay/event.schema.json -o schemas/event.schema.json
+mypy snuba > /dev/null
+if [ "$$?" -gt 1 ]; then
+cat <<EOF
+[${red}${bold}!!!${reset}] Error loading schemas.
+EOF
+fi
+
+# Ensures migrations are executed
 
 files_changed_upstream="$(mktemp)"
 trap "rm -f ${files_changed_upstream}" EXIT

From 5aa582ad9434885b75c0601759c329d89102f348 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Mon, 21 Sep 2020 23:56:36 -0700
Subject: [PATCH 12/17] Post merge hook

---
 config/hooks/post-merge | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/config/hooks/post-merge b/config/hooks/post-merge
index f500897883b..89986634d46 100755
--- a/config/hooks/post-merge
+++ b/config/hooks/post-merge
@@ -8,14 +8,11 @@ reset="$(tput sgr0)"
 mkdir -p schemas
 curl https://raw.githubusercontent.com/getsentry/sentry-data-schemas/main/relay/event.schema.json -o schemas/event.schema.json
 mypy snuba > /dev/null
-if [ "$$?" -gt 1 ]; then
-cat <<EOF
-[${red}${bold}!!!${reset}] Error loading schemas.
-EOF
+if [ $? -gt 1 ]; then
+  echo [${red}${bold}!!!${reset}] Could not dowload schemas.
 fi
 
 # Ensures migrations are executed
-
 files_changed_upstream="$(mktemp)"
 trap "rm -f ${files_changed_upstream}" EXIT
 

From 117b37ddebfce64dda3e66f4eb852476b6e33c5f Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Thu, 24 Sep 2020 09:14:06 -0700
Subject: [PATCH 13/17] Temporarily commit the schema

---
 schemas/event.schema.json | 2761 +++++++++++++++++++++++++++++++++++++
 1 file changed, 2761 insertions(+)
 create mode 100644 schemas/event.schema.json

diff --git a/schemas/event.schema.json b/schemas/event.schema.json
new file mode 100644
index 00000000000..04092c86a7b
--- /dev/null
+++ b/schemas/event.schema.json
@@ -0,0 +1,2761 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "title": "Event",
+  "description": " The sentry v7 event structure.",
+  "anyOf": [
+    {
+      "type": "object",
+      "properties": {
+        "breadcrumbs": {
+          "description": " List of breadcrumbs recorded before this event.",
+          "default": null,
+          "type": [
+            "object",
+            "null"
+          ],
+          "required": [
+            "values"
+          ],
+          "properties": {
+            "values": {
+              "type": "array",
+              "items": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/Breadcrumb"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            }
+          }
+        },
+        "contexts": {
+          "description": " Contexts describing the environment (e.g. device, os or browser).",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/Contexts"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "culprit": {
+          "description": " Custom culprit of the event.",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "debug_meta": {
+          "description": " Meta data for event processing and debugging.",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/DebugMeta"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "dist": {
+          "description": " Program's distribution identifier.\n\n The distribution of the application.\n\n Distributions are used to disambiguate build or deployment variants of the same release of\n an application. For example, the dist can be the build number of an XCode build or the\n version code of an Android build.",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "environment": {
+          "description": " The environment name, such as `production` or `staging`.\n\n ```json\n { \"environment\": \"production\" }\n ```",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "errors": {
+          "description": " Errors encountered during processing. Intended to be phased out in favor of\n annotation/metadata system.",
+          "default": null,
+          "type": [
+            "array",
+            "null"
+          ],
+          "items": {
+            "anyOf": [
+              {
+                "$ref": "#/definitions/EventProcessingError"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "event_id": {
+          "description": " Unique identifier of this event.\n\n Hexadecimal string representing a uuid4 value. The length is exactly 32 characters. Dashes\n are not allowed. Has to be lowercase.\n\n Even though this field is backfilled on the server with a new uuid4, it is strongly\n recommended to generate that uuid4 clientside. There are some features like user feedback\n which are easier to implement that way, and debugging in case events get lost in your\n Sentry installation is also easier.\n\n Example:\n\n ```json\n {\n   \"event_id\": \"fc6d8c0c43fc4630ad850ee518f1b9d0\"\n }\n ```",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/EventId"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "exception": {
+          "description": " One or multiple chained (nested) exceptions.",
+          "default": null,
+          "type": [
+            "object",
+            "null"
+          ],
+          "required": [
+            "values"
+          ],
+          "properties": {
+            "values": {
+              "type": "array",
+              "items": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/Exception"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            }
+          }
+        },
+        "extra": {
+          "description": " Arbitrary extra information set by the user.\n\n ```json\n {\n     \"extra\": {\n         \"my_key\": 1,\n         \"some_other_value\": \"foo bar\"\n     }\n }```",
+          "default": null,
+          "type": [
+            "object",
+            "null"
+          ],
+          "additionalProperties": true
+        },
+        "fingerprint": {
+          "description": " Manual fingerprint override.\n\n A list of strings used to dictate how this event is supposed to be grouped with other\n events into issues. For more information about overriding grouping see [Customize Grouping\n with Fingerprints](https://docs.sentry.io/data-management/event-grouping/).\n\n ```json\n {\n     \"fingerprint\": [\"myrpc\", \"POST\", \"/foo.bar\"]\n }",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/Fingerprint"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "level": {
+          "description": " Severity level of the event. Defaults to `error`.\n\n Example:\n\n ```json\n {\"level\": \"warning\"}\n ```",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/Level"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "logentry": {
+          "description": " Custom parameterized message for this event.",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/LogEntry"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "logger": {
+          "description": " Logger that created the event.",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "modules": {
+          "description": " Name and versions of all installed modules/packages/dependencies in the current\n environment/application.\n\n ```json\n { \"django\": \"3.0.0\", \"celery\": \"4.2.1\" }\n ```\n\n In Python this is a list of installed packages as reported by `pkg_resources` together with\n their reported version string.\n\n This is primarily used for suggesting to enable certain SDK integrations from within the UI\n and for making informed decisions on which frameworks to support in future development\n efforts.",
+          "default": null,
+          "type": [
+            "object",
+            "null"
+          ],
+          "additionalProperties": {
+            "type": [
+              "string",
+              "null"
+            ]
+          }
+        },
+        "platform": {
+          "description": " Platform identifier of this event (defaults to \"other\").\n\n A string representing the platform the SDK is submitting from. This will be used by the\n Sentry interface to customize various components in the interface, but also to enter or\n skip stacktrace processing.\n\n Acceptable values are: `as3`, `c`, `cfml`, `cocoa`, `csharp`, `elixir`, `haskell`, `go`,\n `groovy`, `java`, `javascript`, `native`, `node`, `objc`, `other`, `perl`, `php`, `python`,\n `ruby`",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "received": {
+          "description": " Timestamp when the event has been received by Sentry.",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/Timestamp"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "release": {
+          "description": " The release version of the application.\n\n **Release versions must be unique across all projects in your organization.** This value\n can be the git SHA for the given project, or a product identifier with a semantic version.",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "request": {
+          "description": " Information about a web request that occurred during the event.",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/Request"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "sdk": {
+          "description": " Information about the Sentry SDK that generated this event.",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/ClientSdkInfo"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "server_name": {
+          "description": " Server or device name the event was generated on.\n\n This is supposed to be a hostname.",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "stacktrace": {
+          "description": " Event stacktrace.\n\n DEPRECATED: Prefer `threads` or `exception` depending on which is more appropriate.",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/Stacktrace"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "tags": {
+          "description": " Custom tags for this event.\n\n A map or list of tags for this event. Each tag must be less than 200 characters.",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/Tags"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "threads": {
+          "description": " Threads that were active when the event occurred.",
+          "default": null,
+          "type": [
+            "object",
+            "null"
+          ],
+          "required": [
+            "values"
+          ],
+          "properties": {
+            "values": {
+              "type": "array",
+              "items": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/Thread"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            }
+          }
+        },
+        "time_spent": {
+          "description": " Time since the start of the transaction until the error occurred.",
+          "default": null,
+          "type": [
+            "integer",
+            "null"
+          ],
+          "format": "uint64",
+          "minimum": 0.0
+        },
+        "timestamp": {
+          "description": " Timestamp when the event was created.\n\n Indicates when the event was created in the Sentry SDK. The format is either a string as\n defined in [RFC 3339](https://tools.ietf.org/html/rfc3339) or a numeric (integer or float)\n value representing the number of seconds that have elapsed since the [Unix\n epoch](https://en.wikipedia.org/wiki/Unix_time).\n\n Sub-microsecond precision is not preserved with numeric values due to precision\n limitations with floats (at least in our systems). With that caveat in mind, just send\n whatever is easiest to produce.\n\n All timestamps in the event protocol are formatted this way.\n\n ```json\n { \"timestamp\": \"2011-05-02T17:41:36Z\" }\n { \"timestamp\": 1304358096.0 }\n ```",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/Timestamp"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "transaction": {
+          "description": " Transaction name of the event.\n\n For example, in a web app, this might be the route name (`\"/users/<username>/\"` or\n `UserView`), in a task queue it might be the function + module name.",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "type": {
+          "description": " Type of event: error, csp, default",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/EventType"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "user": {
+          "description": " Information about the user who triggered this event.",
+          "default": null,
+          "anyOf": [
+            {
+              "$ref": "#/definitions/User"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "version": {
+          "description": " Version",
+          "default": null,
+          "type": [
+            "string",
+            "null"
+          ]
+        }
+      }
+    }
+  ],
+  "definitions": {
+    "Addr": {
+      "type": "string"
+    },
+    "AppContext": {
+      "description": " Application information.\n\n App context describes the application. As opposed to the runtime, this is the actual\n application that was running and carries metadata about the current session.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "app_build": {
+              "description": " Internal build ID as it appears on the platform.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "app_identifier": {
+              "description": " Version-independent application identifier, often a dotted bundle ID.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "app_name": {
+              "description": " Application name as it appears on the platform.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "app_start_time": {
+              "description": " Start time of the app.\n\n Formatted UTC timestamp when the user started the application.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "app_version": {
+              "description": " Application version as it appears on the platform.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "build_type": {
+              "description": " String identifying the kind of build. For example, `testflight`.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "device_app_hash": {
+              "description": " Application-specific device identifier.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "AppleDebugImage": {
+      "description": " Legacy apple debug images (MachO).\n\n This was also used for non-apple platforms with similar debug setups.",
+      "anyOf": [
+        {
+          "type": "object",
+          "required": [
+            "image_addr",
+            "image_size",
+            "name",
+            "uuid"
+          ],
+          "properties": {
+            "arch": {
+              "description": " CPU architecture target.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "cpu_subtype": {
+              "description": " MachO CPU subtype identifier.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "cpu_type": {
+              "description": " MachO CPU type identifier.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "image_addr": {
+              "description": " Starting memory address of the image (required).",
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Addr"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "image_size": {
+              "description": " Size of the image in bytes (required).",
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "image_vmaddr": {
+              "description": " Loading address in virtual memory.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Addr"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "name": {
+              "description": " Path and name of the debug image (required).",
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "uuid": {
+              "description": " The unique UUID of the image.",
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          }
+        }
+      ]
+    },
+    "Breadcrumb": {
+      "description": " The Breadcrumbs Interface specifies a series of application events, or \"breadcrumbs\", that\n occurred before an event.\n\n An event may contain one or more breadcrumbs in an attribute named `breadcrumbs`. The entries\n are ordered from oldest to newest. Consequently, the last entry in the list should be the last\n entry before the event occurred.\n\n While breadcrumb attributes are not strictly validated in Sentry, a breadcrumb is most useful\n when it includes at least a `timestamp` and `type`, `category` or `message`. The rendering of\n breadcrumbs in Sentry depends on what is provided.\n\n The following example illustrates the breadcrumbs part of the event payload and omits other\n attributes for simplicity.\n\n ```json\n {\n   \"breadcrumbs\": {\n     \"values\": [\n       {\n         \"timestamp\": \"2016-04-20T20:55:53.845Z\",\n         \"message\": \"Something happened\",\n         \"category\": \"log\",\n         \"data\": {\n           \"foo\": \"bar\",\n           \"blub\": \"blah\"\n         }\n       },\n       {\n         \"timestamp\": \"2016-04-20T20:55:53.847Z\",\n         \"type\": \"navigation\",\n         \"data\": {\n           \"from\": \"/login\",\n           \"to\": \"/dashboard\"\n         }\n       }\n     ]\n   }\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "category": {
+              "description": " A dotted string indicating what the crumb is or from where it comes. _Optional._\n\n Typically it is a module name or a descriptive string. For instance, _ui.click_ could be\n used to indicate that a click happened in the UI or _flask_ could be used to indicate that\n the event originated in the Flask framework.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "data": {
+              "description": " Arbitrary data associated with this breadcrumb.\n\n Contains a dictionary whose contents depend on the breadcrumb `type`. Additional parameters\n that are unsupported by the type are rendered as a key/value table.",
+              "default": null,
+              "type": [
+                "object",
+                "null"
+              ],
+              "additionalProperties": true
+            },
+            "level": {
+              "description": " Severity level of the breadcrumb. _Optional._\n\n Allowed values are, from highest to lowest: `fatal`, `error`, `warning`, `info`, and\n `debug`. Levels are used in the UI to emphasize and deemphasize the crumb. Defaults to\n `info`.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Level"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "message": {
+              "description": " Human readable message for the breadcrumb.\n\n If a message is provided, it is rendered as text with all whitespace preserved. Very long\n text might be truncated in the UI.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "timestamp": {
+              "description": " The timestamp of the breadcrumb. Recommended.\n\n A timestamp representing when the breadcrumb occurred. The format is either a string as\n defined in [RFC 3339](https://tools.ietf.org/html/rfc3339) or a numeric (integer or float)\n value representing the number of seconds that have elapsed since the [Unix\n epoch](https://en.wikipedia.org/wiki/Unix_time).\n\n Breadcrumbs are most useful when they include a timestamp, as it creates a timeline leading\n up to an event.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Timestamp"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "type": {
+              "description": " The type of the breadcrumb. _Optional_, defaults to `default`.\n\n - `default`: Describes a generic breadcrumb. This is typically a log message or\n   user-generated breadcrumb. The `data` field is entirely undefined and as such, completely\n   rendered as a key/value table.\n\n - `navigation`: Describes a navigation breadcrumb. A navigation event can be a URL change\n   in a web application, or a UI transition in a mobile or desktop application, etc.\n\n   Such a breadcrumb's `data` object has the required fields `from` and `to`, which\n   represent an application route/url each.\n\n - `http`: Describes an HTTP request breadcrumb. This represents an HTTP request transmitted\n   from your application. This could be an AJAX request from a web application, or a\n   server-to-server HTTP request to an API service provider, etc.\n\n   Such a breadcrumb's `data` property has the fields `url`, `method`, `status_code`\n   (integer) and `reason` (string).",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "BrowserContext": {
+      "description": " Web browser information.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "name": {
+              "description": " Display name of the browser application.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "version": {
+              "description": " Version string of the browser.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "CError": {
+      "description": " POSIX signal with optional extended data.\n\n Error codes set by Linux system calls and some library functions as specified in ISO C99,\n POSIX.1-2001, and POSIX.1-2008. See\n [`errno(3)`](https://man7.org/linux/man-pages/man3/errno.3.html) for more information.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "name": {
+              "description": " Optional name of the errno constant.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "number": {
+              "description": " The error code as specified by ISO C99, POSIX.1-2001 or POSIX.1-2008.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          }
+        }
+      ]
+    },
+    "ClientSdkInfo": {
+      "description": " The SDK Interface describes the Sentry SDK and its configuration used to capture and transmit an event.",
+      "anyOf": [
+        {
+          "type": "object",
+          "required": [
+            "name",
+            "version"
+          ],
+          "properties": {
+            "integrations": {
+              "description": " List of integrations that are enabled in the SDK. _Optional._\n\n The list should have all enabled integrations, including default integrations. Default\n integrations are included because different SDK releases may contain different default\n integrations.",
+              "default": null,
+              "type": [
+                "array",
+                "null"
+              ],
+              "items": {
+                "type": [
+                  "string",
+                  "null"
+                ]
+              }
+            },
+            "name": {
+              "description": " Unique SDK name. _Required._\n\n The name of the SDK. The format is `entity.ecosystem[.flavor]` where entity identifies the\n developer of the SDK, ecosystem refers to the programming language or platform where the\n SDK is to be used and the optional flavor is used to identify standalone SDKs that are part\n of a major ecosystem.\n\n Official Sentry SDKs use the entity `sentry`, as in `sentry.python` or\n `sentry.javascript.react-native`. Please use a different entity for your own SDKs.",
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "packages": {
+              "description": " List of installed and loaded SDK packages. _Optional._\n\n A list of packages that were installed as part of this SDK or the activated integrations.\n Each package consists of a name in the format `source:identifier` and `version`. If the\n source is a Git repository, the `source` should be `git`, the identifier should be a\n checkout link and the version should be a Git reference (branch, tag or SHA).",
+              "default": null,
+              "type": [
+                "array",
+                "null"
+              ],
+              "items": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/ClientSdkPackage"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            },
+            "version": {
+              "description": " The version of the SDK. _Required._\n\n It should have the [Semantic Versioning](https://semver.org/) format `MAJOR.MINOR.PATCH`,\n without any prefix (no `v` or anything else in front of the major version number).\n\n Examples: `0.1.0`, `1.0.0`, `4.3.12`",
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "ClientSdkPackage": {
+      "description": " An installed and loaded package as part of the Sentry SDK.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "name": {
+              "description": " Name of the package.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "version": {
+              "description": " Version of the package.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "CodeId": {
+      "type": "string"
+    },
+    "Context": {
+      "description": " A context describes environment info (e.g. device, os or browser).",
+      "anyOf": [
+        {
+          "$ref": "#/definitions/DeviceContext"
+        },
+        {
+          "$ref": "#/definitions/OsContext"
+        },
+        {
+          "$ref": "#/definitions/RuntimeContext"
+        },
+        {
+          "$ref": "#/definitions/AppContext"
+        },
+        {
+          "$ref": "#/definitions/BrowserContext"
+        },
+        {
+          "$ref": "#/definitions/GpuContext"
+        },
+        {
+          "$ref": "#/definitions/TraceContext"
+        },
+        {
+          "$ref": "#/definitions/MonitorContext"
+        },
+        {
+          "type": "object",
+          "additionalProperties": true
+        }
+      ]
+    },
+    "ContextInner": {
+      "anyOf": [
+        {
+          "$ref": "#/definitions/Context"
+        }
+      ]
+    },
+    "Contexts": {
+      "description": " The Contexts Interface provides additional context data. Typically, this is data related to the\n current user and the environment. For example, the device or application version. Its canonical\n name is `contexts`.\n\n The `contexts` type can be used to define arbitrary contextual data on the event. It accepts an\n object of key/value pairs. The key is the “alias” of the context and can be freely chosen.\n However, as per policy, it should match the type of the context unless there are two values for\n a type. You can omit `type` if the key name is the type.\n\n Unknown data for the contexts is rendered as a key/value list.\n\n For more details about sending additional data with your event, see the [full documentation on\n Additional Data](https://docs.sentry.io/enriching-error-data/additional-data/).",
+      "anyOf": [
+        {
+          "type": "object",
+          "additionalProperties": {
+            "anyOf": [
+              {
+                "$ref": "#/definitions/ContextInner"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        }
+      ]
+    },
+    "Cookies": {
+      "description": " A map holding cookies.",
+      "anyOf": [
+        {
+          "anyOf": [
+            {
+              "type": "object",
+              "additionalProperties": {
+                "type": [
+                  "string",
+                  "null"
+                ]
+              }
+            },
+            {
+              "type": "array",
+              "items": {
+                "type": [
+                  "array",
+                  "null"
+                ],
+                "items": [
+                  {
+                    "type": [
+                      "string",
+                      "null"
+                    ]
+                  },
+                  {
+                    "type": [
+                      "string",
+                      "null"
+                    ]
+                  }
+                ],
+                "maxItems": 2,
+                "minItems": 2
+              }
+            }
+          ]
+        }
+      ]
+    },
+    "DebugId": {
+      "type": "string"
+    },
+    "DebugImage": {
+      "description": " A debug information file (debug image).",
+      "anyOf": [
+        {
+          "$ref": "#/definitions/AppleDebugImage"
+        },
+        {
+          "$ref": "#/definitions/NativeDebugImage"
+        },
+        {
+          "$ref": "#/definitions/NativeDebugImage"
+        },
+        {
+          "$ref": "#/definitions/NativeDebugImage"
+        },
+        {
+          "$ref": "#/definitions/NativeDebugImage"
+        },
+        {
+          "$ref": "#/definitions/ProguardDebugImage"
+        },
+        {
+          "type": "object",
+          "additionalProperties": true
+        }
+      ]
+    },
+    "DebugMeta": {
+      "description": " Debugging and processing meta information.\n\n The debug meta interface carries debug information for processing errors and crash reports.\n Sentry amends the information in this interface.\n\n Example (look at field types to see more detail):\n\n ```json\n {\n   \"debug_meta\": {\n     \"images\": [],\n     \"sdk_info\": {\n       \"sdk_name\": \"iOS\",\n       \"version_major\": 10,\n       \"version_minor\": 3,\n       \"version_patchlevel\": 0\n     }\n   }\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "images": {
+              "description": " List of debug information files (debug images).",
+              "default": null,
+              "type": [
+                "array",
+                "null"
+              ],
+              "items": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/DebugImage"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            },
+            "sdk_info": {
+              "description": " Information about the system SDK (e.g. iOS SDK).",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/SystemSdkInfo"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "DeviceContext": {
+      "description": " Device information.\n\n Device context describes the device that caused the event. This is most appropriate for mobile\n applications.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "arch": {
+              "description": " Native cpu architecture of the device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "battery_level": {
+              "description": " Current battery level in %.\n\n If the device has a battery, this can be a floating point value defining the battery level\n (in the range 0-100).",
+              "default": null,
+              "type": [
+                "number",
+                "null"
+              ],
+              "format": "double"
+            },
+            "boot_time": {
+              "description": " Indicator when the device was booted.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "brand": {
+              "description": " Brand of the device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "charging": {
+              "description": " Whether the device was charging or not.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "external_free_storage": {
+              "description": " Free size of the attached external storage in bytes (eg: android SDK card).",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "external_storage_size": {
+              "description": " Total size of the attached external storage in bytes (eg: android SDK card).",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "family": {
+              "description": " Family of the device model.\n\n This is usually the common part of model names across generations. For instance, `iPhone`\n would be a reasonable family, so would be `Samsung Galaxy`.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "free_memory": {
+              "description": " How much memory is still available in bytes.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "free_storage": {
+              "description": " How much storage is free in bytes.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "low_memory": {
+              "description": " Whether the device was low on memory.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "manufacturer": {
+              "description": " Manufacturer of the device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "memory_size": {
+              "description": " Total memory available in bytes.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "model": {
+              "description": " Device model.\n\n This, for example, can be `Samsung Galaxy S3`.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "model_id": {
+              "description": " Device model (internal identifier).\n\n An internal hardware revision to identify the device exactly.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "name": {
+              "description": " Name of the device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "online": {
+              "description": " Whether the device was online or not.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "orientation": {
+              "description": " Current screen orientation.\n\n This can be a string `portrait` or `landscape` to define the orientation of a device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "screen_density": {
+              "description": " Device screen density.",
+              "default": null,
+              "type": [
+                "number",
+                "null"
+              ],
+              "format": "double"
+            },
+            "screen_dpi": {
+              "description": " Screen density as dots-per-inch.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "screen_resolution": {
+              "description": " Device screen resolution.\n\n (e.g.: 800x600, 3040x1444)",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "simulator": {
+              "description": " Simulator/prod indicator.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "storage_size": {
+              "description": " Total storage size of the device in bytes.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "timezone": {
+              "description": " Timezone of the device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "usable_memory": {
+              "description": " How much memory is usable for the app in bytes.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            }
+          }
+        }
+      ]
+    },
+    "EventId": {
+      "description": " Wrapper around a UUID with slightly different formatting.",
+      "anyOf": [
+        {
+          "type": "string",
+          "format": "uuid"
+        }
+      ]
+    },
+    "EventProcessingError": {
+      "description": " An event processing error.",
+      "anyOf": [
+        {
+          "type": "object",
+          "required": [
+            "type"
+          ],
+          "properties": {
+            "name": {
+              "description": " Affected key or deep path.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "type": {
+              "description": " The error kind.",
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "value": {
+              "description": " The original value causing this error.",
+              "default": null
+            }
+          }
+        }
+      ]
+    },
+    "EventType": {
+      "description": "The type of an event.",
+      "type": "string",
+      "enum": [
+        "error",
+        "csp",
+        "hpkp",
+        "expectct",
+        "expectstaple",
+        "transaction",
+        "default"
+      ]
+    },
+    "Exception": {
+      "description": " A single exception.\n\n Multiple values inside of an [event](#typedef-Event) represent chained exceptions and should be sorted oldest to newest. For example, consider this Python code snippet:\n\n ```python\n try:\n     raise Exception(\"random boring invariant was not met!\")\n except Exception as e:\n     raise ValueError(\"something went wrong, help!\") from e\n ```\n\n `Exception` would be described first in the values list, followed by a description of `ValueError`:\n\n ```json\n {\n   \"exception\": {\n     \"values\": [\n       {\"type\": \"Exception\": \"value\": \"random boring invariant was not met!\"},\n       {\"type\": \"ValueError\", \"value\": \"something went wrong, help!\"},\n     ]\n   }\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "mechanism": {
+              "description": " Mechanism by which this exception was generated and handled.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Mechanism"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "module": {
+              "description": " The optional module, or package which the exception type lives in.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "stacktrace": {
+              "description": " Stack trace containing frames of this exception.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Stacktrace"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "thread_id": {
+              "description": " An optional value that refers to a [thread](#typedef-Thread).",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/ThreadId"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "type": {
+              "description": " Exception type, e.g. `ValueError`.\n\n At least one of `type` or `value` is required, otherwise the exception is discarded.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "value": {
+              "description": " Human readable display value.\n\n At least one of `type` or `value` is required, otherwise the exception is discarded.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/JsonLenientString"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "Fingerprint": {
+      "description": " A fingerprint value.",
+      "anyOf": [
+        {
+          "type": "array",
+          "items": {
+            "type": "string"
+          }
+        }
+      ]
+    },
+    "Frame": {
+      "description": " Holds information about a single stacktrace frame.\n\n Each object should contain **at least** a `filename`, `function` or `instruction_addr` attribute. All values are optional, but recommended.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "abs_path": {
+              "description": " Absolute path to the source file.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/NativeImagePath"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "colno": {
+              "description": " Column number within the source file, starting at 1.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "context_line": {
+              "description": " Source code of the current line (`lineno`).",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "filename": {
+              "description": " The source file name (basename only).",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/NativeImagePath"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "function": {
+              "description": " Name of the frame's function. This might include the name of a class.\n\n This function name may be shortened or demangled. If not, Sentry will demangle and shorten\n it for some platforms. The original function name will be stored in `raw_function`.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "image_addr": {
+              "description": " (C/C++/Native) Start address of the containing code module (image).",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Addr"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "in_app": {
+              "description": " Override whether this frame should be considered part of application code, or part of\n libraries/frameworks/dependencies.\n\n Setting this attribute to `false` causes the frame to be hidden/collapsed by default and\n mostly ignored during issue grouping.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "instruction_addr": {
+              "description": " (C/C++/Native) An optional instruction address for symbolication.\n\n This should be a string with a hexadecimal number that includes a 0x prefix.\n If this is set and a known image is defined in the\n [Debug Meta Interface]({%- link _documentation/development/sdk-dev/event-payloads/debugmeta.md -%}),\n then symbolication can take place.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Addr"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "lineno": {
+              "description": " Line number within the source file, starting at 1.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "module": {
+              "description": " Name of the module the frame is contained in.\n\n Note that this might also include a class name if that is something the\n language natively considers to be part of the stack (for instance in Java).",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "package": {
+              "description": " Name of the package that contains the frame.\n\n For instance this can be a dylib for native languages, the name of the jar\n or .NET assembly.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "platform": {
+              "description": " Which platform this frame is from.\n\n This can override the platform for a single frame. Otherwise, the platform of the event is\n assumed. This can be used for multi-platform stack traces, such as in React Native.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "post_context": {
+              "description": " Source code of the lines after `lineno`.",
+              "default": null,
+              "type": [
+                "array",
+                "null"
+              ],
+              "items": {
+                "type": [
+                  "string",
+                  "null"
+                ]
+              }
+            },
+            "pre_context": {
+              "description": " Source code leading up to `lineno`.",
+              "default": null,
+              "type": [
+                "array",
+                "null"
+              ],
+              "items": {
+                "type": [
+                  "string",
+                  "null"
+                ]
+              }
+            },
+            "raw_function": {
+              "description": " A raw (but potentially truncated) function value.\n\n The original function name, if the function name is shortened or demangled. Sentry shows\n the raw function when clicking on the shortened one in the UI.\n\n If this has the same value as `function` it's best to be omitted.  This\n exists because on many platforms the function itself contains additional\n information like overload specifies or a lot of generics which can make\n it exceed the maximum limit we provide for the field.  In those cases\n then we cannot reliably trim down the function any more at a later point\n because the more valuable information has been removed.\n\n The logic to be applied is that an intelligently trimmed function name\n should be stored in `function` and the value before trimming is stored\n in this field instead.  However also this field will be capped at 256\n characters at the moment which often means that not the entire original\n value can be stored.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "symbol": {
+              "description": " Potentially mangled name of the symbol as it appears in an executable.\n\n This is different from a function name by generally being the mangled\n name that appears natively in the binary.  This is relevant for languages\n like Swift, C++ or Rust.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "symbol_addr": {
+              "description": " (C/C++/Native) Start address of the frame's function.\n\n We use the instruction address for symbolication, but this can be used to calculate\n an instruction offset automatically.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Addr"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "vars": {
+              "description": " Mapping of local variables and expression names that were available in this frame.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/FrameVars"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "FrameVars": {
+      "description": " Frame local variables.",
+      "anyOf": [
+        {
+          "type": "object",
+          "additionalProperties": true
+        }
+      ]
+    },
+    "Geo": {
+      "description": " Geographical location of the end user or device.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "city": {
+              "description": " Human readable city name.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "country_code": {
+              "description": " Two-letter country code (ISO 3166-1 alpha-2).",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "region": {
+              "description": " Human readable region name or code.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "GpuContext": {
+      "description": " GPU information.\n\n Example:\n\n ```json\n \"gpu\": {\n   \"name\": \"AMD Radeon Pro 560\",\n   \"vendor_name\": \"Apple\",\n   \"memory_size\": 4096,\n   \"api_type\": \"Metal\",\n   \"multi_threaded_rendering\": true,\n   \"version\": \"Metal\",\n   \"npot_support\": \"Full\"\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "api_type": {
+              "description": " The device low-level API type.\n\n Examples: `\"Apple Metal\"` or `\"Direct3D11\"`",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "id": {
+              "description": " The PCI identifier of the graphics device.",
+              "default": null
+            },
+            "memory_size": {
+              "description": " The total GPU memory available in Megabytes.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "multi_threaded_rendering": {
+              "description": " Whether the GPU has multi-threaded rendering or not.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "name": {
+              "description": " The name of the graphics device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "npot_support": {
+              "description": " The Non-Power-Of-Two support.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "vendor_id": {
+              "description": " The PCI vendor identifier of the graphics device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "vendor_name": {
+              "description": " The vendor name as reported by the graphics device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "version": {
+              "description": " The Version of the graphics device.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "HeaderName": {
+      "description": " A \"into-string\" type that normalizes header names.",
+      "anyOf": [
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "HeaderValue": {
+      "description": " A \"into-string\" type that normalizes header values.",
+      "anyOf": [
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "Headers": {
+      "description": " A map holding headers.",
+      "anyOf": [
+        {
+          "anyOf": [
+            {
+              "type": "object",
+              "additionalProperties": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/HeaderValue"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            },
+            {
+              "type": "array",
+              "items": {
+                "type": [
+                  "array",
+                  "null"
+                ],
+                "items": [
+                  {
+                    "anyOf": [
+                      {
+                        "$ref": "#/definitions/HeaderName"
+                      },
+                      {
+                        "type": "null"
+                      }
+                    ]
+                  },
+                  {
+                    "anyOf": [
+                      {
+                        "$ref": "#/definitions/HeaderValue"
+                      },
+                      {
+                        "type": "null"
+                      }
+                    ]
+                  }
+                ],
+                "maxItems": 2,
+                "minItems": 2
+              }
+            }
+          ]
+        }
+      ]
+    },
+    "JsonLenientString": {
+      "description": " A \"into-string\" type of value. All non-string values are serialized as JSON.",
+      "anyOf": [
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "Level": {
+      "description": "Severity level of an event or breadcrumb.",
+      "type": "string",
+      "enum": [
+        "debug",
+        "info",
+        "warning",
+        "error",
+        "fatal"
+      ]
+    },
+    "LogEntry": {
+      "description": " A log entry message.\n\n A log message is similar to the `message` attribute on the event itself but\n can additionally hold optional parameters.\n\n ```json\n {\n   \"message\": {\n     \"message\": \"My raw message with interpreted strings like %s\",\n     \"params\": [\"this\"]\n   }\n }\n ```\n\n ```json\n {\n   \"message\": {\n     \"message\": \"My raw message with interpreted strings like {foo}\",\n     \"params\": {\"foo\": \"this\"}\n   }\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "formatted": {
+              "description": " The formatted message. If `message` and `params` are given, Sentry\n will attempt to backfill `formatted` if empty.\n\n It must not exceed 8192 characters. Longer messages will be truncated.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Message"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "message": {
+              "description": " The log message with parameter placeholders.\n\n This attribute is primarily used for grouping related events together into issues.\n Therefore this really should just be a string template, i.e. `Sending %d requests` instead\n of `Sending 9999 requests`. The latter is much better at home in `formatted`.\n\n It must not exceed 8192 characters. Longer messages will be truncated.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Message"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "params": {
+              "description": " Parameters to be interpolated into the log message. This can be an array of positional\n parameters as well as a mapping of named arguments to their values.",
+              "default": null
+            }
+          }
+        }
+      ]
+    },
+    "MachException": {
+      "description": " Mach exception information.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "code": {
+              "description": " The mach exception code.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "exception": {
+              "description": " The mach exception type.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            },
+            "name": {
+              "description": " Optional name of the mach exception.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "subcode": {
+              "description": " The mach exception subcode.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            }
+          }
+        }
+      ]
+    },
+    "Mechanism": {
+      "description": " The mechanism by which an exception was generated and handled.\n\n The exception mechanism is an optional field residing in the [exception](#typedef-Exception).\n It carries additional information about the way the exception was created on the target system.\n This includes general exception values obtained from the operating system or runtime APIs, as\n well as mechanism-specific values.",
+      "anyOf": [
+        {
+          "type": "object",
+          "required": [
+            "type"
+          ],
+          "properties": {
+            "data": {
+              "description": " Arbitrary extra data that might help the user understand the error thrown by this mechanism.",
+              "default": null,
+              "type": [
+                "object",
+                "null"
+              ],
+              "additionalProperties": true
+            },
+            "description": {
+              "description": " Optional human-readable description of the error mechanism.\n\n May include a possible hint on how to solve this error.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "handled": {
+              "description": " Flag indicating whether this exception was handled.\n\n This is a best-effort guess at whether the exception was handled by user code or not. For\n example:\n\n - Exceptions leading to a 500 Internal Server Error or to a hard process crash are\n   `handled=false`, as the SDK typically has an integration that automatically captures the\n   error.\n\n - Exceptions captured using `capture_exception` (called from user code) are `handled=true`\n   as the user explicitly captured the exception (and therefore kind of handled it)",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "help_link": {
+              "description": " Link to online resources describing this error.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "meta": {
+              "description": " Operating system or runtime meta information.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/MechanismMeta"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "synthetic": {
+              "description": " If this is set then the exception is not a real exception but some\n form of synthetic error for instance from a signal handler, a hard\n segfault or similar where type and value are not useful for grouping\n or display purposes.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "type": {
+              "description": " Mechanism type (required).\n\n Required unique identifier of this mechanism determining rendering and processing of the\n mechanism data.\n\n In the Python SDK this is merely the name of the framework integration that produced the\n exception, while for native it is e.g. `\"minidump\"` or `\"applecrashreport\"`.",
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "MechanismMeta": {
+      "description": " Operating system or runtime meta information to an exception mechanism.\n\n The mechanism metadata usually carries error codes reported by the runtime or operating system,\n along with a platform-dependent interpretation of these codes. SDKs can safely omit code names\n and descriptions for well-known error codes, as it will be filled out by Sentry. For\n proprietary or vendor-specific error codes, adding these values will give additional\n information to the user.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "errno": {
+              "description": " Optional ISO C standard error code.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/CError"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "mach_exception": {
+              "description": " A Mach Exception on Apple systems comprising a code triple and optional descriptions.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/MachException"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "signal": {
+              "description": " Information on the POSIX signal.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/PosixSignal"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "Message": {
+      "anyOf": [
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "MonitorContext": {
+      "description": " Monitor information.",
+      "anyOf": [
+        {
+          "type": "object",
+          "additionalProperties": true
+        }
+      ]
+    },
+    "NativeDebugImage": {
+      "description": " A generic (new-style) native platform debug information file.\n\n The `type` key must be one of:\n\n - `macho`\n - `elf`: ELF images are used on Linux platforms. Their structure is identical to other native images.\n - `pe`\n\n Examples:\n\n ```json\n {\n   \"type\": \"elf\",\n   \"code_id\": \"68220ae2c65d65c1b6aaa12fa6765a6ec2f5f434\",\n   \"code_file\": \"/lib/x86_64-linux-gnu/libgcc_s.so.1\",\n   \"debug_id\": \"e20a2268-5dc6-c165-b6aa-a12fa6765a6e\",\n   \"image_addr\": \"0x7f5140527000\",\n   \"image_size\": 90112,\n   \"image_vmaddr\": \"0x40000\",\n   \"arch\": \"x86_64\"\n }\n ```\n\n ```json\n {\n   \"type\": \"pe\",\n   \"code_id\": \"57898e12145000\",\n   \"code_file\": \"C:\\\\Windows\\\\System32\\\\dbghelp.dll\",\n   \"debug_id\": \"9c2a902b-6fdf-40ad-8308-588a41d572a0-1\",\n   \"debug_file\": \"dbghelp.pdb\",\n   \"image_addr\": \"0x70850000\",\n   \"image_size\": \"1331200\",\n   \"image_vmaddr\": \"0x40000\",\n   \"arch\": \"x86\"\n }\n ```\n\n ```json\n {\n   \"type\": \"macho\",\n   \"debug_id\": \"84a04d24-0e60-3810-a8c0-90a65e2df61a\",\n   \"debug_file\": \"libDiagnosticMessagesClient.dylib\",\n   \"code_file\": \"/usr/lib/libDiagnosticMessagesClient.dylib\",\n   \"image_addr\": \"0x7fffe668e000\",\n   \"image_size\": 8192,\n   \"image_vmaddr\": \"0x40000\",\n   \"arch\": \"x86_64\",\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "required": [
+            "code_file",
+            "debug_id",
+            "image_addr",
+            "image_size"
+          ],
+          "properties": {
+            "arch": {
+              "description": " CPU architecture target.\n\n Architecture of the module. If missing, this will be backfilled by Sentry.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "code_file": {
+              "description": " Path and name of the image file (required).\n\n The absolute path to the dynamic library or executable. This helps to locate the file if it is missing on Sentry.\n\n - `pe`: The code file should be provided to allow server-side stack walking of binary crash reports, such as Minidumps.",
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/NativeImagePath"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "code_id": {
+              "description": " Optional identifier of the code file.\n\n - `elf`: If the program was compiled with a relatively recent compiler, this should be the hex representation of the `NT_GNU_BUILD_ID` program header (type `PT_NOTE`), or the value of the `.note.gnu.build-id` note section (type `SHT_NOTE`). Otherwise, leave this value empty.\n\n   Certain symbol servers use the code identifier to locate debug information for ELF images, in which case this field should be included if possible.\n\n - `pe`: Identifier of the executable or DLL. It contains the values of the `time_date_stamp` from the COFF header and `size_of_image` from the optional header formatted together into a hex string using `%08x%X` (note that the second value is not padded):\n\n   ```text\n   time_date_stamp: 0x5ab38077\n   size_of_image:           0x9000\n   code_id:           5ab380779000\n   ```\n\n   The code identifier should be provided to allow server-side stack walking of binary crash reports, such as Minidumps.\n\n\n - `macho`: Identifier of the dynamic library or executable. It is the value of the `LC_UUID` load command in the Mach header, formatted as UUID. Can be empty for Mach images, as it is equivalent to the debug identifier.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/CodeId"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "debug_file": {
+              "description": " Path and name of the debug companion file.\n\n - `elf`: Name or absolute path to the file containing stripped debug information for this image. This value might be _required_ to retrieve debug files from certain symbol servers.\n\n - `pe`: Name of the PDB file containing debug information for this image. This value is often required to retrieve debug files from specific symbol servers.\n\n - `macho`: Name or absolute path to the dSYM file containing debug information for this image. This value might be required to retrieve debug files from certain symbol servers.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/NativeImagePath"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "debug_id": {
+              "description": " Unique debug identifier of the image.\n\n - `elf`: Debug identifier of the dynamic library or executable. If a code identifier is available, the debug identifier is the little-endian UUID representation of the first 16-bytes of that\n identifier. Spaces are inserted for readability, note the byte order of the first fields:\n\n   ```text\n   code id:  f1c3bcc0 2798 65fe 3058 404b2831d9e6 4135386c\n   debug id: c0bcc3f1-9827-fe65-3058-404b2831d9e6\n   ```\n\n   If no code id is available, the debug id should be computed by XORing the first 4096 bytes of the `.text` section in 16-byte chunks, and representing it as a little-endian UUID (again swapping the byte order).\n\n - `pe`: `signature` and `age` of the PDB file. Both values can be read from the CodeView PDB70 debug information header in the PE. The value should be represented as little-endian UUID, with the age appended at the end. Note that the byte order of the UUID fields must be swapped (spaces inserted for readability):\n\n   ```text\n   signature: f1c3bcc0 2798 65fe 3058 404b2831d9e6\n   age:                                            1\n   debug_id:  c0bcc3f1-9827-fe65-3058-404b2831d9e6-1\n   ```\n\n - `macho`: Identifier of the dynamic library or executable. It is the value of the `LC_UUID` load command in the Mach header, formatted as UUID.",
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/DebugId"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "image_addr": {
+              "description": " Starting memory address of the image (required).\n\n Memory address, at which the image is mounted in the virtual address space of the process. Should be a string in hex representation prefixed with `\"0x\"`.",
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Addr"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "image_size": {
+              "description": " Size of the image in bytes (required).\n\n The size of the image in virtual memory. If missing, Sentry will assume that the image spans up to the next image, which might lead to invalid stack traces.",
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "image_vmaddr": {
+              "description": " Loading address in virtual memory.\n\n Preferred load address of the image in virtual memory, as declared in the headers of the\n image. When loading an image, the operating system may still choose to place it at a\n different address.\n\n Symbols and addresses in the native image are always relative to the start of the image and do not consider the preferred load address. It is merely a hint to the loader.\n\n - `elf`/`macho`: If this value is non-zero, all symbols and addresses declared in the native image start at this address, rather than 0. By contrast, Sentry deals with addresses relative to the start of the image. For example, with `image_vmaddr: 0x40000`, a symbol located at `0x401000` has a relative address of `0x1000`.\n\n   Relative addresses used in Apple Crash Reports and `addr2line` are usually in the preferred address space, and not relative address space.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Addr"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "NativeImagePath": {
+      "description": " A type for strings that are generally paths, might contain system user names, but still cannot\n be stripped liberally because it would break processing for certain platforms.\n\n Those strings get special treatment in our PII processor to avoid stripping the basename.",
+      "anyOf": [
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "OsContext": {
+      "description": " Operating system information.\n\n OS context describes the operating system on which the event was created. In web contexts, this\n is the operating system of the browser (generally pulled from the User-Agent string).",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "build": {
+              "description": " Internal build number of the operating system.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "kernel_version": {
+              "description": " Current kernel version.\n\n This is typically the entire output of the `uname` syscall.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "name": {
+              "description": " Name of the operating system.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "raw_description": {
+              "description": " Unprocessed operating system info.\n\n An unprocessed description string obtained by the operating system. For some well-known\n runtimes, Sentry will attempt to parse `name` and `version` from this string, if they are\n not explicitly given.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "rooted": {
+              "description": " Indicator if the OS is rooted (mobile mostly).",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "version": {
+              "description": " Version of the operating system.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "PosixSignal": {
+      "description": " POSIX signal with optional extended data.\n\n On Apple systems, signals also carry a code in addition to the signal number describing the\n signal in more detail. On Linux, this code does not exist.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "code": {
+              "description": " An optional signal code present on Apple systems.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            },
+            "code_name": {
+              "description": " Optional name of the errno constant.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "name": {
+              "description": " Optional name of the errno constant.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "number": {
+              "description": " The POSIX signal number.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "int64"
+            }
+          }
+        }
+      ]
+    },
+    "ProguardDebugImage": {
+      "description": " Proguard mapping file.\n\n Proguard images refer to `mapping.txt` files generated when Proguard obfuscates function names. The Java SDK integrations assign this file a unique identifier, which has to be included in the list of images.",
+      "anyOf": [
+        {
+          "type": "object",
+          "required": [
+            "uuid"
+          ],
+          "properties": {
+            "uuid": {
+              "description": " UUID computed from the file contents, assigned by the Java SDK.",
+              "type": [
+                "string",
+                "null"
+              ],
+              "format": "uuid"
+            }
+          }
+        }
+      ]
+    },
+    "RawStacktrace": {
+      "description": " A stack trace of a single thread.\n\n A stack trace contains a list of frames, each with various bits (most optional) describing the context of that frame. Frames should be sorted from oldest to newest.\n\n For the given example program written in Python:\n\n ```python\n def foo():\n     my_var = 'foo'\n     raise ValueError()\n\n def main():\n     foo()\n ```\n\n A minimalistic stack trace for the above program in the correct order:\n\n ```json\n {\n   \"frames\": [\n     {\"function\": \"main\"},\n     {\"function\": \"foo\"}\n   ]\n }\n ```\n\n The top frame fully symbolicated with five lines of source context:\n\n ```json\n {\n   \"frames\": [{\n     \"in_app\": true,\n     \"function\": \"myfunction\",\n     \"abs_path\": \"/real/file/name.py\",\n     \"filename\": \"file/name.py\",\n     \"lineno\": 3,\n     \"vars\": {\n       \"my_var\": \"'value'\"\n     },\n     \"pre_context\": [\n       \"def foo():\",\n       \"  my_var = 'foo'\",\n     ],\n     \"context_line\": \"  raise ValueError()\",\n     \"post_context\": [\n       \"\",\n       \"def main():\"\n     ],\n   }]\n }\n ```\n\n A minimal native stack trace with register values. Note that the `package` event attribute must be \"native\" for these frames to be symbolicated.\n\n ```json\n {\n   \"frames\": [\n     {\"instruction_addr\": \"0x7fff5bf3456c\"},\n     {\"instruction_addr\": \"0x7fff5bf346c0\"},\n   ],\n   \"registers\": {\n     \"rip\": \"0x00007ff6eef54be2\",\n     \"rsp\": \"0x0000003b710cd9e0\"\n   }\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "required": [
+            "frames"
+          ],
+          "properties": {
+            "frames": {
+              "description": " Required. A non-empty list of stack frames. The list is ordered from caller to callee, or oldest to youngest. The last frame is the one creating the exception.",
+              "type": [
+                "array",
+                "null"
+              ],
+              "items": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/Frame"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            },
+            "lang": {
+              "description": " The language of the stacktrace.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "registers": {
+              "description": " Register values of the thread (top frame).\n\n A map of register names and their values. The values should contain the actual register values of the thread, thus mapping to the last frame in the list.",
+              "default": null,
+              "type": [
+                "object",
+                "null"
+              ],
+              "additionalProperties": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/RegVal"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            }
+          }
+        }
+      ]
+    },
+    "RegVal": {
+      "type": "string"
+    },
+    "Request": {
+      "description": " Http request information.\n\n The Request interface contains information on a HTTP request related to the event. In client\n SDKs, this can be an outgoing request, or the request that rendered the current web page. On\n server SDKs, this could be the incoming web request that is being handled.\n\n The data variable should only contain the request body (not the query string). It can either be\n a dictionary (for standard HTTP requests) or a raw request body.\n\n ### Ordered Maps\n\n In the Request interface, several attributes can either be declared as string, object, or list\n of tuples. Sentry attempts to parse structured information from the string representation in\n such cases.\n\n Sometimes, keys can be declared multiple times, or the order of elements matters. In such\n cases, use the tuple representation over a plain object.\n\n Example of request headers as object:\n\n ```json\n {\n   \"content-type\": \"application/json\",\n   \"accept\": \"application/json, application/xml\"\n }\n ```\n\n Example of the same headers as list of tuples:\n\n ```json\n [\n   [\"content-type\", \"application/json\"],\n   [\"accept\", \"application/json\"],\n   [\"accept\", \"application/xml\"]\n ]\n ```\n\n Example of a fully populated request object:\n\n ```json\n {\n   \"request\": {\n     \"method\": \"POST\",\n     \"url\": \"http://absolute.uri/foo\",\n     \"query_string\": \"query=foobar&page=2\",\n     \"data\": {\n       \"foo\": \"bar\"\n     },\n     \"cookies\": \"PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1;\",\n     \"headers\": {\n       \"content-type\": \"text/html\"\n     },\n     \"env\": {\n       \"REMOTE_ADDR\": \"192.168.0.1\"\n     }\n   }\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "cookies": {
+              "description": " The cookie values.\n\n Can be given unparsed as string, as dictionary, or as a list of tuples.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Cookies"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "data": {
+              "description": " Request data in any format that makes sense.\n\n SDKs should discard large and binary bodies by default. Can be given as string or\n structural data of any format.",
+              "default": null
+            },
+            "env": {
+              "description": " Server environment data, such as CGI/WSGI.\n\n A dictionary containing environment information passed from the server. This is where\n information such as CGI/WSGI/Rack keys go that are not HTTP headers.\n\n Sentry will explicitly look for `REMOTE_ADDR` to extract an IP address.",
+              "default": null,
+              "type": [
+                "object",
+                "null"
+              ],
+              "additionalProperties": true
+            },
+            "fragment": {
+              "description": " The fragment of the request URL.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "headers": {
+              "description": " A dictionary of submitted headers.\n\n If a header appears multiple times it, needs to be merged according to the HTTP standard\n for header merging. Header names are treated case-insensitively by Sentry.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Headers"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "inferred_content_type": {
+              "description": " The inferred content type of the request payload.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "method": {
+              "description": " HTTP request method.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "query_string": {
+              "description": " The query string component of the URL.\n\n Can be given as unparsed string, dictionary, or list of tuples.\n\n If the query string is not declared and part of the `url`, Sentry moves it to the\n query string.",
+              "default": null,
+              "anyOf": [
+                {
+                  "anyOf": [
+                    {
+                      "type": "string"
+                    },
+                    {
+                      "anyOf": [
+                        {
+                          "type": "object",
+                          "additionalProperties": {
+                            "type": [
+                              "string",
+                              "null"
+                            ]
+                          }
+                        },
+                        {
+                          "type": "array",
+                          "items": {
+                            "type": [
+                              "array",
+                              "null"
+                            ],
+                            "items": [
+                              {
+                                "type": [
+                                  "string",
+                                  "null"
+                                ]
+                              },
+                              {
+                                "type": [
+                                  "string",
+                                  "null"
+                                ]
+                              }
+                            ],
+                            "maxItems": 2,
+                            "minItems": 2
+                          }
+                        }
+                      ]
+                    }
+                  ]
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "url": {
+              "description": " The URL of the request if available.\n\nThe query string can be declared either as part of the `url`, or separately in `query_string`.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "RuntimeContext": {
+      "description": " Runtime information.\n\n Runtime context describes a runtime in more detail. Typically, this context is present in\n `contexts` multiple times if multiple runtimes are involved (for instance, if you have a\n JavaScript application running on top of JVM).",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "build": {
+              "description": " Application build string, if it is separate from the version.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "name": {
+              "description": " Runtime name.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "raw_description": {
+              "description": " Unprocessed runtime info.\n\n An unprocessed description string obtained by the runtime. For some well-known runtimes,\n Sentry will attempt to parse `name` and `version` from this string, if they are not\n explicitly given.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "version": {
+              "description": " Runtime version string.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "SpanId": {
+      "description": " A 16-character hex string as described in the W3C trace context spec.",
+      "anyOf": [
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "SpanStatus": {
+      "description": "Trace status.\n\nValues from https://github.com/open-telemetry/opentelemetry-specification/blob/8fb6c14e4709e75a9aaa64b0dbbdf02a6067682a/specification/api-tracing.md#status Mapping to HTTP from https://github.com/open-telemetry/opentelemetry-specification/blob/8fb6c14e4709e75a9aaa64b0dbbdf02a6067682a/specification/data-http.md#status",
+      "type": "string",
+      "enum": [
+        "ok",
+        "cancelled",
+        "unknown",
+        "invalid_argument",
+        "deadline_exceeded",
+        "not_found",
+        "already_exists",
+        "permission_denied",
+        "resource_exhausted",
+        "failed_precondition",
+        "aborted",
+        "out_of_range",
+        "unimplemented",
+        "internal_error",
+        "unavailable",
+        "data_loss",
+        "unauthenticated"
+      ]
+    },
+    "Stacktrace": {
+      "anyOf": [
+        {
+          "$ref": "#/definitions/RawStacktrace"
+        }
+      ]
+    },
+    "String": {
+      "type": "string"
+    },
+    "SystemSdkInfo": {
+      "description": " Holds information about the system SDK.\n\n This is relevant for iOS and other platforms that have a system\n SDK.  Not to be confused with the client SDK.",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "sdk_name": {
+              "description": " The internal name of the SDK.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "version_major": {
+              "description": " The major version of the SDK as integer or 0.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "version_minor": {
+              "description": " The minor version of the SDK as integer or 0.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            },
+            "version_patchlevel": {
+              "description": " The patch version of the SDK as integer or 0.",
+              "default": null,
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint64",
+              "minimum": 0.0
+            }
+          }
+        }
+      ]
+    },
+    "TagEntry": {
+      "anyOf": [
+        {
+          "type": "array",
+          "items": [
+            {
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          ],
+          "maxItems": 2,
+          "minItems": 2
+        }
+      ]
+    },
+    "Tags": {
+      "description": " Manual key/value tag pairs.",
+      "anyOf": [
+        {
+          "anyOf": [
+            {
+              "type": "object",
+              "additionalProperties": {
+                "type": [
+                  "string",
+                  "null"
+                ]
+              }
+            },
+            {
+              "type": "array",
+              "items": {
+                "anyOf": [
+                  {
+                    "$ref": "#/definitions/TagEntry"
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            }
+          ]
+        }
+      ]
+    },
+    "Thread": {
+      "description": " A process thread of an event.\n\n The Threads Interface specifies threads that were running at the time an event happened. These threads can also contain stack traces.\n\n An event may contain one or more threads in an attribute named `threads`.\n\n The following example illustrates the threads part of the event payload and omits other attributes for simplicity.\n\n ```json\n {\n   \"threads\": {\n     \"values\": [\n       {\n         \"id\": \"0\",\n         \"name\": \"main\",\n         \"crashed\": true,\n         \"stacktrace\": {}\n       }\n     ]\n   }\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "crashed": {
+              "description": " A flag indicating whether the thread crashed. Defaults to `false`.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "current": {
+              "description": " A flag indicating whether the thread was in the foreground.  Defaults to `false`.",
+              "default": null,
+              "type": [
+                "boolean",
+                "null"
+              ]
+            },
+            "id": {
+              "description": " The ID of the thread. Typically a number or numeric string.\n\n Needs to be unique among the threads. An exception can set the `thread_id` attribute to cross-reference this thread.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/ThreadId"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "name": {
+              "description": " Display name of this thread.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "stacktrace": {
+              "description": " Stack trace containing frames of this exception.\n\n The thread that crashed with an exception should not have a stack trace, but instead, the `thread_id` attribute should be set on the exception and Sentry will connect the two.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Stacktrace"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "ThreadId": {
+      "description": " Represents a thread id.",
+      "anyOf": [
+        {
+          "type": "integer",
+          "format": "uint64",
+          "minimum": 0.0
+        },
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "Timestamp": {
+      "description": "Can be a ISO-8601 formatted string or a unix timestamp in seconds (floating point values allowed).\n\nMust be UTC.",
+      "anyOf": [
+        {
+          "type": "number",
+          "format": "double"
+        },
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "TraceContext": {
+      "description": " Trace context",
+      "anyOf": [
+        {
+          "type": "object",
+          "required": [
+            "span_id",
+            "trace_id"
+          ],
+          "properties": {
+            "op": {
+              "description": " Span type (see `OperationType` docs).",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "parent_span_id": {
+              "description": " The ID of the span enclosing this span.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/SpanId"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "span_id": {
+              "description": " The ID of the span.",
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/SpanId"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "status": {
+              "description": " Whether the trace failed or succeeded. Currently only used to indicate status of individual\n transactions.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/SpanStatus"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "trace_id": {
+              "description": " The trace ID.",
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/TraceId"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "TraceId": {
+      "description": " A 32-character hex string as described in the W3C trace context spec.",
+      "anyOf": [
+        {
+          "type": "string"
+        }
+      ]
+    },
+    "User": {
+      "description": " Information about the user who triggered an event.\n\n ```json\n {\n   \"user\": {\n     \"id\": \"unique_id\",\n     \"username\": \"my_user\",\n     \"email\": \"foo@example.com\",\n     \"ip_address\": \"127.0.0.1\",\n     \"subscription\": \"basic\"\n   }\n }\n ```",
+      "anyOf": [
+        {
+          "type": "object",
+          "properties": {
+            "data": {
+              "description": " Additional arbitrary fields, as stored in the database (and sometimes as sent by clients).\n All data from `self.other` should end up here after store normalization.",
+              "default": null,
+              "type": [
+                "object",
+                "null"
+              ],
+              "additionalProperties": true
+            },
+            "email": {
+              "description": " Email address of the user.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "geo": {
+              "description": " Approximate geographical location of the end user or device.",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/Geo"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "id": {
+              "description": " Unique identifier of the user.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "ip_address": {
+              "description": " Remote IP address of the user. Defaults to \"{{auto}}\".",
+              "default": null,
+              "anyOf": [
+                {
+                  "$ref": "#/definitions/String"
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "name": {
+              "description": " Human readable name of the user.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            },
+            "username": {
+              "description": " Username of the user.",
+              "default": null,
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      ]
+    }
+  }
+}

From 74afa60c80986b8ae9d82467c816b1a9543d2cb9 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Thu, 24 Sep 2020 09:19:44 -0700
Subject: [PATCH 14/17] Temporarily commit the schema 2

---
 .gitignore                | 1 -
 .pre-commit-config.yaml   | 1 +
 schemas/event.schema.json | 2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index aeeb3c273af..f26bd307f36 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,3 @@
 .venv
 htmlcov/
 snuba.egg-info/
-schemas/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index cef2a2ab999..7a145d588cd 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -13,6 +13,7 @@ repos:
       - id: check-yaml
       - id: detect-private-key
       - id: end-of-file-fixer
+        exclude: ^schemas/
       - id: trailing-whitespace
       - id: fix-encoding-pragma
         args: ["--remove"]
diff --git a/schemas/event.schema.json b/schemas/event.schema.json
index 04092c86a7b..eb7d3a3256e 100644
--- a/schemas/event.schema.json
+++ b/schemas/event.schema.json
@@ -2758,4 +2758,4 @@
       ]
     }
   }
-}
+}
\ No newline at end of file

From 69368b9709a20d9c250409c581cbffea70eee17e Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Thu, 24 Sep 2020 09:20:18 -0700
Subject: [PATCH 15/17] Temporarily commit the schema 3

---
 .pre-commit-config.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7a145d588cd..ed44f1975ae 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -13,6 +13,7 @@ repos:
       - id: check-yaml
       - id: detect-private-key
       - id: end-of-file-fixer
+        # TODO: Remove this exclusion when we stop committing the schema.
         exclude: ^schemas/
       - id: trailing-whitespace
       - id: fix-encoding-pragma

From c19c91e1653552859129bf7afa942bbd5aabd454 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Fri, 2 Oct 2020 09:18:38 -0700
Subject: [PATCH 16/17] Try to import pip

---
 requirements.txt                        |    2 +-
 schemas/event.schema.json               | 2761 -----------------------
 snuba/datasets/events_processor_base.py |    5 +-
 3 files changed, 2 insertions(+), 2766 deletions(-)
 delete mode 100644 schemas/event.schema.json

diff --git a/requirements.txt b/requirements.txt
index 5cc0f2a8f3a..0fe8205c9f6 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -26,7 +26,7 @@ MarkupSafe==1.1.1
 mywsgi==1.0.3
 more-itertools==4.2.0
 mypy>=0.761
-jsonschema-typed-v2==0.8.0
+git+https://github.com/fpacifici/sentry-data-schemas.git@feat/add_package#subdirectory=pyschemas
 packaging==17.1
 parsimonious==0.8.1
 py==1.5.3
diff --git a/schemas/event.schema.json b/schemas/event.schema.json
deleted file mode 100644
index eb7d3a3256e..00000000000
--- a/schemas/event.schema.json
+++ /dev/null
@@ -1,2761 +0,0 @@
-{
-  "$schema": "http://json-schema.org/draft-07/schema#",
-  "title": "Event",
-  "description": " The sentry v7 event structure.",
-  "anyOf": [
-    {
-      "type": "object",
-      "properties": {
-        "breadcrumbs": {
-          "description": " List of breadcrumbs recorded before this event.",
-          "default": null,
-          "type": [
-            "object",
-            "null"
-          ],
-          "required": [
-            "values"
-          ],
-          "properties": {
-            "values": {
-              "type": "array",
-              "items": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/Breadcrumb"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            }
-          }
-        },
-        "contexts": {
-          "description": " Contexts describing the environment (e.g. device, os or browser).",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/Contexts"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "culprit": {
-          "description": " Custom culprit of the event.",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        },
-        "debug_meta": {
-          "description": " Meta data for event processing and debugging.",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/DebugMeta"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "dist": {
-          "description": " Program's distribution identifier.\n\n The distribution of the application.\n\n Distributions are used to disambiguate build or deployment variants of the same release of\n an application. For example, the dist can be the build number of an XCode build or the\n version code of an Android build.",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        },
-        "environment": {
-          "description": " The environment name, such as `production` or `staging`.\n\n ```json\n { \"environment\": \"production\" }\n ```",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        },
-        "errors": {
-          "description": " Errors encountered during processing. Intended to be phased out in favor of\n annotation/metadata system.",
-          "default": null,
-          "type": [
-            "array",
-            "null"
-          ],
-          "items": {
-            "anyOf": [
-              {
-                "$ref": "#/definitions/EventProcessingError"
-              },
-              {
-                "type": "null"
-              }
-            ]
-          }
-        },
-        "event_id": {
-          "description": " Unique identifier of this event.\n\n Hexadecimal string representing a uuid4 value. The length is exactly 32 characters. Dashes\n are not allowed. Has to be lowercase.\n\n Even though this field is backfilled on the server with a new uuid4, it is strongly\n recommended to generate that uuid4 clientside. There are some features like user feedback\n which are easier to implement that way, and debugging in case events get lost in your\n Sentry installation is also easier.\n\n Example:\n\n ```json\n {\n   \"event_id\": \"fc6d8c0c43fc4630ad850ee518f1b9d0\"\n }\n ```",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/EventId"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "exception": {
-          "description": " One or multiple chained (nested) exceptions.",
-          "default": null,
-          "type": [
-            "object",
-            "null"
-          ],
-          "required": [
-            "values"
-          ],
-          "properties": {
-            "values": {
-              "type": "array",
-              "items": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/Exception"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            }
-          }
-        },
-        "extra": {
-          "description": " Arbitrary extra information set by the user.\n\n ```json\n {\n     \"extra\": {\n         \"my_key\": 1,\n         \"some_other_value\": \"foo bar\"\n     }\n }```",
-          "default": null,
-          "type": [
-            "object",
-            "null"
-          ],
-          "additionalProperties": true
-        },
-        "fingerprint": {
-          "description": " Manual fingerprint override.\n\n A list of strings used to dictate how this event is supposed to be grouped with other\n events into issues. For more information about overriding grouping see [Customize Grouping\n with Fingerprints](https://docs.sentry.io/data-management/event-grouping/).\n\n ```json\n {\n     \"fingerprint\": [\"myrpc\", \"POST\", \"/foo.bar\"]\n }",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/Fingerprint"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "level": {
-          "description": " Severity level of the event. Defaults to `error`.\n\n Example:\n\n ```json\n {\"level\": \"warning\"}\n ```",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/Level"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "logentry": {
-          "description": " Custom parameterized message for this event.",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/LogEntry"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "logger": {
-          "description": " Logger that created the event.",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        },
-        "modules": {
-          "description": " Name and versions of all installed modules/packages/dependencies in the current\n environment/application.\n\n ```json\n { \"django\": \"3.0.0\", \"celery\": \"4.2.1\" }\n ```\n\n In Python this is a list of installed packages as reported by `pkg_resources` together with\n their reported version string.\n\n This is primarily used for suggesting to enable certain SDK integrations from within the UI\n and for making informed decisions on which frameworks to support in future development\n efforts.",
-          "default": null,
-          "type": [
-            "object",
-            "null"
-          ],
-          "additionalProperties": {
-            "type": [
-              "string",
-              "null"
-            ]
-          }
-        },
-        "platform": {
-          "description": " Platform identifier of this event (defaults to \"other\").\n\n A string representing the platform the SDK is submitting from. This will be used by the\n Sentry interface to customize various components in the interface, but also to enter or\n skip stacktrace processing.\n\n Acceptable values are: `as3`, `c`, `cfml`, `cocoa`, `csharp`, `elixir`, `haskell`, `go`,\n `groovy`, `java`, `javascript`, `native`, `node`, `objc`, `other`, `perl`, `php`, `python`,\n `ruby`",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        },
-        "received": {
-          "description": " Timestamp when the event has been received by Sentry.",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/Timestamp"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "release": {
-          "description": " The release version of the application.\n\n **Release versions must be unique across all projects in your organization.** This value\n can be the git SHA for the given project, or a product identifier with a semantic version.",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        },
-        "request": {
-          "description": " Information about a web request that occurred during the event.",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/Request"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "sdk": {
-          "description": " Information about the Sentry SDK that generated this event.",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/ClientSdkInfo"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "server_name": {
-          "description": " Server or device name the event was generated on.\n\n This is supposed to be a hostname.",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        },
-        "stacktrace": {
-          "description": " Event stacktrace.\n\n DEPRECATED: Prefer `threads` or `exception` depending on which is more appropriate.",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/Stacktrace"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "tags": {
-          "description": " Custom tags for this event.\n\n A map or list of tags for this event. Each tag must be less than 200 characters.",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/Tags"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "threads": {
-          "description": " Threads that were active when the event occurred.",
-          "default": null,
-          "type": [
-            "object",
-            "null"
-          ],
-          "required": [
-            "values"
-          ],
-          "properties": {
-            "values": {
-              "type": "array",
-              "items": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/Thread"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            }
-          }
-        },
-        "time_spent": {
-          "description": " Time since the start of the transaction until the error occurred.",
-          "default": null,
-          "type": [
-            "integer",
-            "null"
-          ],
-          "format": "uint64",
-          "minimum": 0.0
-        },
-        "timestamp": {
-          "description": " Timestamp when the event was created.\n\n Indicates when the event was created in the Sentry SDK. The format is either a string as\n defined in [RFC 3339](https://tools.ietf.org/html/rfc3339) or a numeric (integer or float)\n value representing the number of seconds that have elapsed since the [Unix\n epoch](https://en.wikipedia.org/wiki/Unix_time).\n\n Sub-microsecond precision is not preserved with numeric values due to precision\n limitations with floats (at least in our systems). With that caveat in mind, just send\n whatever is easiest to produce.\n\n All timestamps in the event protocol are formatted this way.\n\n ```json\n { \"timestamp\": \"2011-05-02T17:41:36Z\" }\n { \"timestamp\": 1304358096.0 }\n ```",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/Timestamp"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "transaction": {
-          "description": " Transaction name of the event.\n\n For example, in a web app, this might be the route name (`\"/users/<username>/\"` or\n `UserView`), in a task queue it might be the function + module name.",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        },
-        "type": {
-          "description": " Type of event: error, csp, default",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/EventType"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "user": {
-          "description": " Information about the user who triggered this event.",
-          "default": null,
-          "anyOf": [
-            {
-              "$ref": "#/definitions/User"
-            },
-            {
-              "type": "null"
-            }
-          ]
-        },
-        "version": {
-          "description": " Version",
-          "default": null,
-          "type": [
-            "string",
-            "null"
-          ]
-        }
-      }
-    }
-  ],
-  "definitions": {
-    "Addr": {
-      "type": "string"
-    },
-    "AppContext": {
-      "description": " Application information.\n\n App context describes the application. As opposed to the runtime, this is the actual\n application that was running and carries metadata about the current session.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "app_build": {
-              "description": " Internal build ID as it appears on the platform.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "app_identifier": {
-              "description": " Version-independent application identifier, often a dotted bundle ID.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "app_name": {
-              "description": " Application name as it appears on the platform.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "app_start_time": {
-              "description": " Start time of the app.\n\n Formatted UTC timestamp when the user started the application.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "app_version": {
-              "description": " Application version as it appears on the platform.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "build_type": {
-              "description": " String identifying the kind of build. For example, `testflight`.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "device_app_hash": {
-              "description": " Application-specific device identifier.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "AppleDebugImage": {
-      "description": " Legacy apple debug images (MachO).\n\n This was also used for non-apple platforms with similar debug setups.",
-      "anyOf": [
-        {
-          "type": "object",
-          "required": [
-            "image_addr",
-            "image_size",
-            "name",
-            "uuid"
-          ],
-          "properties": {
-            "arch": {
-              "description": " CPU architecture target.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "cpu_subtype": {
-              "description": " MachO CPU subtype identifier.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "cpu_type": {
-              "description": " MachO CPU type identifier.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "image_addr": {
-              "description": " Starting memory address of the image (required).",
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Addr"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "image_size": {
-              "description": " Size of the image in bytes (required).",
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "image_vmaddr": {
-              "description": " Loading address in virtual memory.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Addr"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "name": {
-              "description": " Path and name of the debug image (required).",
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "uuid": {
-              "description": " The unique UUID of the image.",
-              "type": [
-                "string",
-                "null"
-              ],
-              "format": "uuid"
-            }
-          }
-        }
-      ]
-    },
-    "Breadcrumb": {
-      "description": " The Breadcrumbs Interface specifies a series of application events, or \"breadcrumbs\", that\n occurred before an event.\n\n An event may contain one or more breadcrumbs in an attribute named `breadcrumbs`. The entries\n are ordered from oldest to newest. Consequently, the last entry in the list should be the last\n entry before the event occurred.\n\n While breadcrumb attributes are not strictly validated in Sentry, a breadcrumb is most useful\n when it includes at least a `timestamp` and `type`, `category` or `message`. The rendering of\n breadcrumbs in Sentry depends on what is provided.\n\n The following example illustrates the breadcrumbs part of the event payload and omits other\n attributes for simplicity.\n\n ```json\n {\n   \"breadcrumbs\": {\n     \"values\": [\n       {\n         \"timestamp\": \"2016-04-20T20:55:53.845Z\",\n         \"message\": \"Something happened\",\n         \"category\": \"log\",\n         \"data\": {\n           \"foo\": \"bar\",\n           \"blub\": \"blah\"\n         }\n       },\n       {\n         \"timestamp\": \"2016-04-20T20:55:53.847Z\",\n         \"type\": \"navigation\",\n         \"data\": {\n           \"from\": \"/login\",\n           \"to\": \"/dashboard\"\n         }\n       }\n     ]\n   }\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "category": {
-              "description": " A dotted string indicating what the crumb is or from where it comes. _Optional._\n\n Typically it is a module name or a descriptive string. For instance, _ui.click_ could be\n used to indicate that a click happened in the UI or _flask_ could be used to indicate that\n the event originated in the Flask framework.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "data": {
-              "description": " Arbitrary data associated with this breadcrumb.\n\n Contains a dictionary whose contents depend on the breadcrumb `type`. Additional parameters\n that are unsupported by the type are rendered as a key/value table.",
-              "default": null,
-              "type": [
-                "object",
-                "null"
-              ],
-              "additionalProperties": true
-            },
-            "level": {
-              "description": " Severity level of the breadcrumb. _Optional._\n\n Allowed values are, from highest to lowest: `fatal`, `error`, `warning`, `info`, and\n `debug`. Levels are used in the UI to emphasize and deemphasize the crumb. Defaults to\n `info`.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Level"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "message": {
-              "description": " Human readable message for the breadcrumb.\n\n If a message is provided, it is rendered as text with all whitespace preserved. Very long\n text might be truncated in the UI.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "timestamp": {
-              "description": " The timestamp of the breadcrumb. Recommended.\n\n A timestamp representing when the breadcrumb occurred. The format is either a string as\n defined in [RFC 3339](https://tools.ietf.org/html/rfc3339) or a numeric (integer or float)\n value representing the number of seconds that have elapsed since the [Unix\n epoch](https://en.wikipedia.org/wiki/Unix_time).\n\n Breadcrumbs are most useful when they include a timestamp, as it creates a timeline leading\n up to an event.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Timestamp"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "type": {
-              "description": " The type of the breadcrumb. _Optional_, defaults to `default`.\n\n - `default`: Describes a generic breadcrumb. This is typically a log message or\n   user-generated breadcrumb. The `data` field is entirely undefined and as such, completely\n   rendered as a key/value table.\n\n - `navigation`: Describes a navigation breadcrumb. A navigation event can be a URL change\n   in a web application, or a UI transition in a mobile or desktop application, etc.\n\n   Such a breadcrumb's `data` object has the required fields `from` and `to`, which\n   represent an application route/url each.\n\n - `http`: Describes an HTTP request breadcrumb. This represents an HTTP request transmitted\n   from your application. This could be an AJAX request from a web application, or a\n   server-to-server HTTP request to an API service provider, etc.\n\n   Such a breadcrumb's `data` property has the fields `url`, `method`, `status_code`\n   (integer) and `reason` (string).",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "BrowserContext": {
-      "description": " Web browser information.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "name": {
-              "description": " Display name of the browser application.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "version": {
-              "description": " Version string of the browser.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "CError": {
-      "description": " POSIX signal with optional extended data.\n\n Error codes set by Linux system calls and some library functions as specified in ISO C99,\n POSIX.1-2001, and POSIX.1-2008. See\n [`errno(3)`](https://man7.org/linux/man-pages/man3/errno.3.html) for more information.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "name": {
-              "description": " Optional name of the errno constant.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "number": {
-              "description": " The error code as specified by ISO C99, POSIX.1-2001 or POSIX.1-2008.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            }
-          }
-        }
-      ]
-    },
-    "ClientSdkInfo": {
-      "description": " The SDK Interface describes the Sentry SDK and its configuration used to capture and transmit an event.",
-      "anyOf": [
-        {
-          "type": "object",
-          "required": [
-            "name",
-            "version"
-          ],
-          "properties": {
-            "integrations": {
-              "description": " List of integrations that are enabled in the SDK. _Optional._\n\n The list should have all enabled integrations, including default integrations. Default\n integrations are included because different SDK releases may contain different default\n integrations.",
-              "default": null,
-              "type": [
-                "array",
-                "null"
-              ],
-              "items": {
-                "type": [
-                  "string",
-                  "null"
-                ]
-              }
-            },
-            "name": {
-              "description": " Unique SDK name. _Required._\n\n The name of the SDK. The format is `entity.ecosystem[.flavor]` where entity identifies the\n developer of the SDK, ecosystem refers to the programming language or platform where the\n SDK is to be used and the optional flavor is used to identify standalone SDKs that are part\n of a major ecosystem.\n\n Official Sentry SDKs use the entity `sentry`, as in `sentry.python` or\n `sentry.javascript.react-native`. Please use a different entity for your own SDKs.",
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "packages": {
-              "description": " List of installed and loaded SDK packages. _Optional._\n\n A list of packages that were installed as part of this SDK or the activated integrations.\n Each package consists of a name in the format `source:identifier` and `version`. If the\n source is a Git repository, the `source` should be `git`, the identifier should be a\n checkout link and the version should be a Git reference (branch, tag or SHA).",
-              "default": null,
-              "type": [
-                "array",
-                "null"
-              ],
-              "items": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/ClientSdkPackage"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            },
-            "version": {
-              "description": " The version of the SDK. _Required._\n\n It should have the [Semantic Versioning](https://semver.org/) format `MAJOR.MINOR.PATCH`,\n without any prefix (no `v` or anything else in front of the major version number).\n\n Examples: `0.1.0`, `1.0.0`, `4.3.12`",
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "ClientSdkPackage": {
-      "description": " An installed and loaded package as part of the Sentry SDK.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "name": {
-              "description": " Name of the package.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "version": {
-              "description": " Version of the package.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "CodeId": {
-      "type": "string"
-    },
-    "Context": {
-      "description": " A context describes environment info (e.g. device, os or browser).",
-      "anyOf": [
-        {
-          "$ref": "#/definitions/DeviceContext"
-        },
-        {
-          "$ref": "#/definitions/OsContext"
-        },
-        {
-          "$ref": "#/definitions/RuntimeContext"
-        },
-        {
-          "$ref": "#/definitions/AppContext"
-        },
-        {
-          "$ref": "#/definitions/BrowserContext"
-        },
-        {
-          "$ref": "#/definitions/GpuContext"
-        },
-        {
-          "$ref": "#/definitions/TraceContext"
-        },
-        {
-          "$ref": "#/definitions/MonitorContext"
-        },
-        {
-          "type": "object",
-          "additionalProperties": true
-        }
-      ]
-    },
-    "ContextInner": {
-      "anyOf": [
-        {
-          "$ref": "#/definitions/Context"
-        }
-      ]
-    },
-    "Contexts": {
-      "description": " The Contexts Interface provides additional context data. Typically, this is data related to the\n current user and the environment. For example, the device or application version. Its canonical\n name is `contexts`.\n\n The `contexts` type can be used to define arbitrary contextual data on the event. It accepts an\n object of key/value pairs. The key is the “alias” of the context and can be freely chosen.\n However, as per policy, it should match the type of the context unless there are two values for\n a type. You can omit `type` if the key name is the type.\n\n Unknown data for the contexts is rendered as a key/value list.\n\n For more details about sending additional data with your event, see the [full documentation on\n Additional Data](https://docs.sentry.io/enriching-error-data/additional-data/).",
-      "anyOf": [
-        {
-          "type": "object",
-          "additionalProperties": {
-            "anyOf": [
-              {
-                "$ref": "#/definitions/ContextInner"
-              },
-              {
-                "type": "null"
-              }
-            ]
-          }
-        }
-      ]
-    },
-    "Cookies": {
-      "description": " A map holding cookies.",
-      "anyOf": [
-        {
-          "anyOf": [
-            {
-              "type": "object",
-              "additionalProperties": {
-                "type": [
-                  "string",
-                  "null"
-                ]
-              }
-            },
-            {
-              "type": "array",
-              "items": {
-                "type": [
-                  "array",
-                  "null"
-                ],
-                "items": [
-                  {
-                    "type": [
-                      "string",
-                      "null"
-                    ]
-                  },
-                  {
-                    "type": [
-                      "string",
-                      "null"
-                    ]
-                  }
-                ],
-                "maxItems": 2,
-                "minItems": 2
-              }
-            }
-          ]
-        }
-      ]
-    },
-    "DebugId": {
-      "type": "string"
-    },
-    "DebugImage": {
-      "description": " A debug information file (debug image).",
-      "anyOf": [
-        {
-          "$ref": "#/definitions/AppleDebugImage"
-        },
-        {
-          "$ref": "#/definitions/NativeDebugImage"
-        },
-        {
-          "$ref": "#/definitions/NativeDebugImage"
-        },
-        {
-          "$ref": "#/definitions/NativeDebugImage"
-        },
-        {
-          "$ref": "#/definitions/NativeDebugImage"
-        },
-        {
-          "$ref": "#/definitions/ProguardDebugImage"
-        },
-        {
-          "type": "object",
-          "additionalProperties": true
-        }
-      ]
-    },
-    "DebugMeta": {
-      "description": " Debugging and processing meta information.\n\n The debug meta interface carries debug information for processing errors and crash reports.\n Sentry amends the information in this interface.\n\n Example (look at field types to see more detail):\n\n ```json\n {\n   \"debug_meta\": {\n     \"images\": [],\n     \"sdk_info\": {\n       \"sdk_name\": \"iOS\",\n       \"version_major\": 10,\n       \"version_minor\": 3,\n       \"version_patchlevel\": 0\n     }\n   }\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "images": {
-              "description": " List of debug information files (debug images).",
-              "default": null,
-              "type": [
-                "array",
-                "null"
-              ],
-              "items": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/DebugImage"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            },
-            "sdk_info": {
-              "description": " Information about the system SDK (e.g. iOS SDK).",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/SystemSdkInfo"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "DeviceContext": {
-      "description": " Device information.\n\n Device context describes the device that caused the event. This is most appropriate for mobile\n applications.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "arch": {
-              "description": " Native cpu architecture of the device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "battery_level": {
-              "description": " Current battery level in %.\n\n If the device has a battery, this can be a floating point value defining the battery level\n (in the range 0-100).",
-              "default": null,
-              "type": [
-                "number",
-                "null"
-              ],
-              "format": "double"
-            },
-            "boot_time": {
-              "description": " Indicator when the device was booted.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "brand": {
-              "description": " Brand of the device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "charging": {
-              "description": " Whether the device was charging or not.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "external_free_storage": {
-              "description": " Free size of the attached external storage in bytes (eg: android SDK card).",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "external_storage_size": {
-              "description": " Total size of the attached external storage in bytes (eg: android SDK card).",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "family": {
-              "description": " Family of the device model.\n\n This is usually the common part of model names across generations. For instance, `iPhone`\n would be a reasonable family, so would be `Samsung Galaxy`.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "free_memory": {
-              "description": " How much memory is still available in bytes.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "free_storage": {
-              "description": " How much storage is free in bytes.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "low_memory": {
-              "description": " Whether the device was low on memory.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "manufacturer": {
-              "description": " Manufacturer of the device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "memory_size": {
-              "description": " Total memory available in bytes.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "model": {
-              "description": " Device model.\n\n This, for example, can be `Samsung Galaxy S3`.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "model_id": {
-              "description": " Device model (internal identifier).\n\n An internal hardware revision to identify the device exactly.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "name": {
-              "description": " Name of the device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "online": {
-              "description": " Whether the device was online or not.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "orientation": {
-              "description": " Current screen orientation.\n\n This can be a string `portrait` or `landscape` to define the orientation of a device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "screen_density": {
-              "description": " Device screen density.",
-              "default": null,
-              "type": [
-                "number",
-                "null"
-              ],
-              "format": "double"
-            },
-            "screen_dpi": {
-              "description": " Screen density as dots-per-inch.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "screen_resolution": {
-              "description": " Device screen resolution.\n\n (e.g.: 800x600, 3040x1444)",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "simulator": {
-              "description": " Simulator/prod indicator.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "storage_size": {
-              "description": " Total storage size of the device in bytes.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "timezone": {
-              "description": " Timezone of the device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "usable_memory": {
-              "description": " How much memory is usable for the app in bytes.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            }
-          }
-        }
-      ]
-    },
-    "EventId": {
-      "description": " Wrapper around a UUID with slightly different formatting.",
-      "anyOf": [
-        {
-          "type": "string",
-          "format": "uuid"
-        }
-      ]
-    },
-    "EventProcessingError": {
-      "description": " An event processing error.",
-      "anyOf": [
-        {
-          "type": "object",
-          "required": [
-            "type"
-          ],
-          "properties": {
-            "name": {
-              "description": " Affected key or deep path.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "type": {
-              "description": " The error kind.",
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "value": {
-              "description": " The original value causing this error.",
-              "default": null
-            }
-          }
-        }
-      ]
-    },
-    "EventType": {
-      "description": "The type of an event.",
-      "type": "string",
-      "enum": [
-        "error",
-        "csp",
-        "hpkp",
-        "expectct",
-        "expectstaple",
-        "transaction",
-        "default"
-      ]
-    },
-    "Exception": {
-      "description": " A single exception.\n\n Multiple values inside of an [event](#typedef-Event) represent chained exceptions and should be sorted oldest to newest. For example, consider this Python code snippet:\n\n ```python\n try:\n     raise Exception(\"random boring invariant was not met!\")\n except Exception as e:\n     raise ValueError(\"something went wrong, help!\") from e\n ```\n\n `Exception` would be described first in the values list, followed by a description of `ValueError`:\n\n ```json\n {\n   \"exception\": {\n     \"values\": [\n       {\"type\": \"Exception\": \"value\": \"random boring invariant was not met!\"},\n       {\"type\": \"ValueError\", \"value\": \"something went wrong, help!\"},\n     ]\n   }\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "mechanism": {
-              "description": " Mechanism by which this exception was generated and handled.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Mechanism"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "module": {
-              "description": " The optional module, or package which the exception type lives in.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "stacktrace": {
-              "description": " Stack trace containing frames of this exception.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Stacktrace"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "thread_id": {
-              "description": " An optional value that refers to a [thread](#typedef-Thread).",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/ThreadId"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "type": {
-              "description": " Exception type, e.g. `ValueError`.\n\n At least one of `type` or `value` is required, otherwise the exception is discarded.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "value": {
-              "description": " Human readable display value.\n\n At least one of `type` or `value` is required, otherwise the exception is discarded.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/JsonLenientString"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "Fingerprint": {
-      "description": " A fingerprint value.",
-      "anyOf": [
-        {
-          "type": "array",
-          "items": {
-            "type": "string"
-          }
-        }
-      ]
-    },
-    "Frame": {
-      "description": " Holds information about a single stacktrace frame.\n\n Each object should contain **at least** a `filename`, `function` or `instruction_addr` attribute. All values are optional, but recommended.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "abs_path": {
-              "description": " Absolute path to the source file.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/NativeImagePath"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "colno": {
-              "description": " Column number within the source file, starting at 1.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "context_line": {
-              "description": " Source code of the current line (`lineno`).",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "filename": {
-              "description": " The source file name (basename only).",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/NativeImagePath"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "function": {
-              "description": " Name of the frame's function. This might include the name of a class.\n\n This function name may be shortened or demangled. If not, Sentry will demangle and shorten\n it for some platforms. The original function name will be stored in `raw_function`.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "image_addr": {
-              "description": " (C/C++/Native) Start address of the containing code module (image).",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Addr"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "in_app": {
-              "description": " Override whether this frame should be considered part of application code, or part of\n libraries/frameworks/dependencies.\n\n Setting this attribute to `false` causes the frame to be hidden/collapsed by default and\n mostly ignored during issue grouping.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "instruction_addr": {
-              "description": " (C/C++/Native) An optional instruction address for symbolication.\n\n This should be a string with a hexadecimal number that includes a 0x prefix.\n If this is set and a known image is defined in the\n [Debug Meta Interface]({%- link _documentation/development/sdk-dev/event-payloads/debugmeta.md -%}),\n then symbolication can take place.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Addr"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "lineno": {
-              "description": " Line number within the source file, starting at 1.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "module": {
-              "description": " Name of the module the frame is contained in.\n\n Note that this might also include a class name if that is something the\n language natively considers to be part of the stack (for instance in Java).",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "package": {
-              "description": " Name of the package that contains the frame.\n\n For instance this can be a dylib for native languages, the name of the jar\n or .NET assembly.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "platform": {
-              "description": " Which platform this frame is from.\n\n This can override the platform for a single frame. Otherwise, the platform of the event is\n assumed. This can be used for multi-platform stack traces, such as in React Native.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "post_context": {
-              "description": " Source code of the lines after `lineno`.",
-              "default": null,
-              "type": [
-                "array",
-                "null"
-              ],
-              "items": {
-                "type": [
-                  "string",
-                  "null"
-                ]
-              }
-            },
-            "pre_context": {
-              "description": " Source code leading up to `lineno`.",
-              "default": null,
-              "type": [
-                "array",
-                "null"
-              ],
-              "items": {
-                "type": [
-                  "string",
-                  "null"
-                ]
-              }
-            },
-            "raw_function": {
-              "description": " A raw (but potentially truncated) function value.\n\n The original function name, if the function name is shortened or demangled. Sentry shows\n the raw function when clicking on the shortened one in the UI.\n\n If this has the same value as `function` it's best to be omitted.  This\n exists because on many platforms the function itself contains additional\n information like overload specifies or a lot of generics which can make\n it exceed the maximum limit we provide for the field.  In those cases\n then we cannot reliably trim down the function any more at a later point\n because the more valuable information has been removed.\n\n The logic to be applied is that an intelligently trimmed function name\n should be stored in `function` and the value before trimming is stored\n in this field instead.  However also this field will be capped at 256\n characters at the moment which often means that not the entire original\n value can be stored.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "symbol": {
-              "description": " Potentially mangled name of the symbol as it appears in an executable.\n\n This is different from a function name by generally being the mangled\n name that appears natively in the binary.  This is relevant for languages\n like Swift, C++ or Rust.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "symbol_addr": {
-              "description": " (C/C++/Native) Start address of the frame's function.\n\n We use the instruction address for symbolication, but this can be used to calculate\n an instruction offset automatically.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Addr"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "vars": {
-              "description": " Mapping of local variables and expression names that were available in this frame.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/FrameVars"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "FrameVars": {
-      "description": " Frame local variables.",
-      "anyOf": [
-        {
-          "type": "object",
-          "additionalProperties": true
-        }
-      ]
-    },
-    "Geo": {
-      "description": " Geographical location of the end user or device.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "city": {
-              "description": " Human readable city name.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "country_code": {
-              "description": " Two-letter country code (ISO 3166-1 alpha-2).",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "region": {
-              "description": " Human readable region name or code.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "GpuContext": {
-      "description": " GPU information.\n\n Example:\n\n ```json\n \"gpu\": {\n   \"name\": \"AMD Radeon Pro 560\",\n   \"vendor_name\": \"Apple\",\n   \"memory_size\": 4096,\n   \"api_type\": \"Metal\",\n   \"multi_threaded_rendering\": true,\n   \"version\": \"Metal\",\n   \"npot_support\": \"Full\"\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "api_type": {
-              "description": " The device low-level API type.\n\n Examples: `\"Apple Metal\"` or `\"Direct3D11\"`",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "id": {
-              "description": " The PCI identifier of the graphics device.",
-              "default": null
-            },
-            "memory_size": {
-              "description": " The total GPU memory available in Megabytes.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "multi_threaded_rendering": {
-              "description": " Whether the GPU has multi-threaded rendering or not.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "name": {
-              "description": " The name of the graphics device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "npot_support": {
-              "description": " The Non-Power-Of-Two support.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "vendor_id": {
-              "description": " The PCI vendor identifier of the graphics device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "vendor_name": {
-              "description": " The vendor name as reported by the graphics device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "version": {
-              "description": " The Version of the graphics device.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "HeaderName": {
-      "description": " A \"into-string\" type that normalizes header names.",
-      "anyOf": [
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "HeaderValue": {
-      "description": " A \"into-string\" type that normalizes header values.",
-      "anyOf": [
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "Headers": {
-      "description": " A map holding headers.",
-      "anyOf": [
-        {
-          "anyOf": [
-            {
-              "type": "object",
-              "additionalProperties": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/HeaderValue"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            },
-            {
-              "type": "array",
-              "items": {
-                "type": [
-                  "array",
-                  "null"
-                ],
-                "items": [
-                  {
-                    "anyOf": [
-                      {
-                        "$ref": "#/definitions/HeaderName"
-                      },
-                      {
-                        "type": "null"
-                      }
-                    ]
-                  },
-                  {
-                    "anyOf": [
-                      {
-                        "$ref": "#/definitions/HeaderValue"
-                      },
-                      {
-                        "type": "null"
-                      }
-                    ]
-                  }
-                ],
-                "maxItems": 2,
-                "minItems": 2
-              }
-            }
-          ]
-        }
-      ]
-    },
-    "JsonLenientString": {
-      "description": " A \"into-string\" type of value. All non-string values are serialized as JSON.",
-      "anyOf": [
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "Level": {
-      "description": "Severity level of an event or breadcrumb.",
-      "type": "string",
-      "enum": [
-        "debug",
-        "info",
-        "warning",
-        "error",
-        "fatal"
-      ]
-    },
-    "LogEntry": {
-      "description": " A log entry message.\n\n A log message is similar to the `message` attribute on the event itself but\n can additionally hold optional parameters.\n\n ```json\n {\n   \"message\": {\n     \"message\": \"My raw message with interpreted strings like %s\",\n     \"params\": [\"this\"]\n   }\n }\n ```\n\n ```json\n {\n   \"message\": {\n     \"message\": \"My raw message with interpreted strings like {foo}\",\n     \"params\": {\"foo\": \"this\"}\n   }\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "formatted": {
-              "description": " The formatted message. If `message` and `params` are given, Sentry\n will attempt to backfill `formatted` if empty.\n\n It must not exceed 8192 characters. Longer messages will be truncated.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Message"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "message": {
-              "description": " The log message with parameter placeholders.\n\n This attribute is primarily used for grouping related events together into issues.\n Therefore this really should just be a string template, i.e. `Sending %d requests` instead\n of `Sending 9999 requests`. The latter is much better at home in `formatted`.\n\n It must not exceed 8192 characters. Longer messages will be truncated.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Message"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "params": {
-              "description": " Parameters to be interpolated into the log message. This can be an array of positional\n parameters as well as a mapping of named arguments to their values.",
-              "default": null
-            }
-          }
-        }
-      ]
-    },
-    "MachException": {
-      "description": " Mach exception information.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "code": {
-              "description": " The mach exception code.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "exception": {
-              "description": " The mach exception type.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            },
-            "name": {
-              "description": " Optional name of the mach exception.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "subcode": {
-              "description": " The mach exception subcode.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            }
-          }
-        }
-      ]
-    },
-    "Mechanism": {
-      "description": " The mechanism by which an exception was generated and handled.\n\n The exception mechanism is an optional field residing in the [exception](#typedef-Exception).\n It carries additional information about the way the exception was created on the target system.\n This includes general exception values obtained from the operating system or runtime APIs, as\n well as mechanism-specific values.",
-      "anyOf": [
-        {
-          "type": "object",
-          "required": [
-            "type"
-          ],
-          "properties": {
-            "data": {
-              "description": " Arbitrary extra data that might help the user understand the error thrown by this mechanism.",
-              "default": null,
-              "type": [
-                "object",
-                "null"
-              ],
-              "additionalProperties": true
-            },
-            "description": {
-              "description": " Optional human-readable description of the error mechanism.\n\n May include a possible hint on how to solve this error.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "handled": {
-              "description": " Flag indicating whether this exception was handled.\n\n This is a best-effort guess at whether the exception was handled by user code or not. For\n example:\n\n - Exceptions leading to a 500 Internal Server Error or to a hard process crash are\n   `handled=false`, as the SDK typically has an integration that automatically captures the\n   error.\n\n - Exceptions captured using `capture_exception` (called from user code) are `handled=true`\n   as the user explicitly captured the exception (and therefore kind of handled it)",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "help_link": {
-              "description": " Link to online resources describing this error.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "meta": {
-              "description": " Operating system or runtime meta information.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/MechanismMeta"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "synthetic": {
-              "description": " If this is set then the exception is not a real exception but some\n form of synthetic error for instance from a signal handler, a hard\n segfault or similar where type and value are not useful for grouping\n or display purposes.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "type": {
-              "description": " Mechanism type (required).\n\n Required unique identifier of this mechanism determining rendering and processing of the\n mechanism data.\n\n In the Python SDK this is merely the name of the framework integration that produced the\n exception, while for native it is e.g. `\"minidump\"` or `\"applecrashreport\"`.",
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "MechanismMeta": {
-      "description": " Operating system or runtime meta information to an exception mechanism.\n\n The mechanism metadata usually carries error codes reported by the runtime or operating system,\n along with a platform-dependent interpretation of these codes. SDKs can safely omit code names\n and descriptions for well-known error codes, as it will be filled out by Sentry. For\n proprietary or vendor-specific error codes, adding these values will give additional\n information to the user.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "errno": {
-              "description": " Optional ISO C standard error code.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/CError"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "mach_exception": {
-              "description": " A Mach Exception on Apple systems comprising a code triple and optional descriptions.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/MachException"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "signal": {
-              "description": " Information on the POSIX signal.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/PosixSignal"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "Message": {
-      "anyOf": [
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "MonitorContext": {
-      "description": " Monitor information.",
-      "anyOf": [
-        {
-          "type": "object",
-          "additionalProperties": true
-        }
-      ]
-    },
-    "NativeDebugImage": {
-      "description": " A generic (new-style) native platform debug information file.\n\n The `type` key must be one of:\n\n - `macho`\n - `elf`: ELF images are used on Linux platforms. Their structure is identical to other native images.\n - `pe`\n\n Examples:\n\n ```json\n {\n   \"type\": \"elf\",\n   \"code_id\": \"68220ae2c65d65c1b6aaa12fa6765a6ec2f5f434\",\n   \"code_file\": \"/lib/x86_64-linux-gnu/libgcc_s.so.1\",\n   \"debug_id\": \"e20a2268-5dc6-c165-b6aa-a12fa6765a6e\",\n   \"image_addr\": \"0x7f5140527000\",\n   \"image_size\": 90112,\n   \"image_vmaddr\": \"0x40000\",\n   \"arch\": \"x86_64\"\n }\n ```\n\n ```json\n {\n   \"type\": \"pe\",\n   \"code_id\": \"57898e12145000\",\n   \"code_file\": \"C:\\\\Windows\\\\System32\\\\dbghelp.dll\",\n   \"debug_id\": \"9c2a902b-6fdf-40ad-8308-588a41d572a0-1\",\n   \"debug_file\": \"dbghelp.pdb\",\n   \"image_addr\": \"0x70850000\",\n   \"image_size\": \"1331200\",\n   \"image_vmaddr\": \"0x40000\",\n   \"arch\": \"x86\"\n }\n ```\n\n ```json\n {\n   \"type\": \"macho\",\n   \"debug_id\": \"84a04d24-0e60-3810-a8c0-90a65e2df61a\",\n   \"debug_file\": \"libDiagnosticMessagesClient.dylib\",\n   \"code_file\": \"/usr/lib/libDiagnosticMessagesClient.dylib\",\n   \"image_addr\": \"0x7fffe668e000\",\n   \"image_size\": 8192,\n   \"image_vmaddr\": \"0x40000\",\n   \"arch\": \"x86_64\",\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "required": [
-            "code_file",
-            "debug_id",
-            "image_addr",
-            "image_size"
-          ],
-          "properties": {
-            "arch": {
-              "description": " CPU architecture target.\n\n Architecture of the module. If missing, this will be backfilled by Sentry.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "code_file": {
-              "description": " Path and name of the image file (required).\n\n The absolute path to the dynamic library or executable. This helps to locate the file if it is missing on Sentry.\n\n - `pe`: The code file should be provided to allow server-side stack walking of binary crash reports, such as Minidumps.",
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/NativeImagePath"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "code_id": {
-              "description": " Optional identifier of the code file.\n\n - `elf`: If the program was compiled with a relatively recent compiler, this should be the hex representation of the `NT_GNU_BUILD_ID` program header (type `PT_NOTE`), or the value of the `.note.gnu.build-id` note section (type `SHT_NOTE`). Otherwise, leave this value empty.\n\n   Certain symbol servers use the code identifier to locate debug information for ELF images, in which case this field should be included if possible.\n\n - `pe`: Identifier of the executable or DLL. It contains the values of the `time_date_stamp` from the COFF header and `size_of_image` from the optional header formatted together into a hex string using `%08x%X` (note that the second value is not padded):\n\n   ```text\n   time_date_stamp: 0x5ab38077\n   size_of_image:           0x9000\n   code_id:           5ab380779000\n   ```\n\n   The code identifier should be provided to allow server-side stack walking of binary crash reports, such as Minidumps.\n\n\n - `macho`: Identifier of the dynamic library or executable. It is the value of the `LC_UUID` load command in the Mach header, formatted as UUID. Can be empty for Mach images, as it is equivalent to the debug identifier.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/CodeId"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "debug_file": {
-              "description": " Path and name of the debug companion file.\n\n - `elf`: Name or absolute path to the file containing stripped debug information for this image. This value might be _required_ to retrieve debug files from certain symbol servers.\n\n - `pe`: Name of the PDB file containing debug information for this image. This value is often required to retrieve debug files from specific symbol servers.\n\n - `macho`: Name or absolute path to the dSYM file containing debug information for this image. This value might be required to retrieve debug files from certain symbol servers.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/NativeImagePath"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "debug_id": {
-              "description": " Unique debug identifier of the image.\n\n - `elf`: Debug identifier of the dynamic library or executable. If a code identifier is available, the debug identifier is the little-endian UUID representation of the first 16-bytes of that\n identifier. Spaces are inserted for readability, note the byte order of the first fields:\n\n   ```text\n   code id:  f1c3bcc0 2798 65fe 3058 404b2831d9e6 4135386c\n   debug id: c0bcc3f1-9827-fe65-3058-404b2831d9e6\n   ```\n\n   If no code id is available, the debug id should be computed by XORing the first 4096 bytes of the `.text` section in 16-byte chunks, and representing it as a little-endian UUID (again swapping the byte order).\n\n - `pe`: `signature` and `age` of the PDB file. Both values can be read from the CodeView PDB70 debug information header in the PE. The value should be represented as little-endian UUID, with the age appended at the end. Note that the byte order of the UUID fields must be swapped (spaces inserted for readability):\n\n   ```text\n   signature: f1c3bcc0 2798 65fe 3058 404b2831d9e6\n   age:                                            1\n   debug_id:  c0bcc3f1-9827-fe65-3058-404b2831d9e6-1\n   ```\n\n - `macho`: Identifier of the dynamic library or executable. It is the value of the `LC_UUID` load command in the Mach header, formatted as UUID.",
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/DebugId"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "image_addr": {
-              "description": " Starting memory address of the image (required).\n\n Memory address, at which the image is mounted in the virtual address space of the process. Should be a string in hex representation prefixed with `\"0x\"`.",
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Addr"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "image_size": {
-              "description": " Size of the image in bytes (required).\n\n The size of the image in virtual memory. If missing, Sentry will assume that the image spans up to the next image, which might lead to invalid stack traces.",
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "image_vmaddr": {
-              "description": " Loading address in virtual memory.\n\n Preferred load address of the image in virtual memory, as declared in the headers of the\n image. When loading an image, the operating system may still choose to place it at a\n different address.\n\n Symbols and addresses in the native image are always relative to the start of the image and do not consider the preferred load address. It is merely a hint to the loader.\n\n - `elf`/`macho`: If this value is non-zero, all symbols and addresses declared in the native image start at this address, rather than 0. By contrast, Sentry deals with addresses relative to the start of the image. For example, with `image_vmaddr: 0x40000`, a symbol located at `0x401000` has a relative address of `0x1000`.\n\n   Relative addresses used in Apple Crash Reports and `addr2line` are usually in the preferred address space, and not relative address space.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Addr"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "NativeImagePath": {
-      "description": " A type for strings that are generally paths, might contain system user names, but still cannot\n be stripped liberally because it would break processing for certain platforms.\n\n Those strings get special treatment in our PII processor to avoid stripping the basename.",
-      "anyOf": [
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "OsContext": {
-      "description": " Operating system information.\n\n OS context describes the operating system on which the event was created. In web contexts, this\n is the operating system of the browser (generally pulled from the User-Agent string).",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "build": {
-              "description": " Internal build number of the operating system.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "kernel_version": {
-              "description": " Current kernel version.\n\n This is typically the entire output of the `uname` syscall.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "name": {
-              "description": " Name of the operating system.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "raw_description": {
-              "description": " Unprocessed operating system info.\n\n An unprocessed description string obtained by the operating system. For some well-known\n runtimes, Sentry will attempt to parse `name` and `version` from this string, if they are\n not explicitly given.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "rooted": {
-              "description": " Indicator if the OS is rooted (mobile mostly).",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "version": {
-              "description": " Version of the operating system.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "PosixSignal": {
-      "description": " POSIX signal with optional extended data.\n\n On Apple systems, signals also carry a code in addition to the signal number describing the\n signal in more detail. On Linux, this code does not exist.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "code": {
-              "description": " An optional signal code present on Apple systems.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            },
-            "code_name": {
-              "description": " Optional name of the errno constant.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "name": {
-              "description": " Optional name of the errno constant.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "number": {
-              "description": " The POSIX signal number.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "int64"
-            }
-          }
-        }
-      ]
-    },
-    "ProguardDebugImage": {
-      "description": " Proguard mapping file.\n\n Proguard images refer to `mapping.txt` files generated when Proguard obfuscates function names. The Java SDK integrations assign this file a unique identifier, which has to be included in the list of images.",
-      "anyOf": [
-        {
-          "type": "object",
-          "required": [
-            "uuid"
-          ],
-          "properties": {
-            "uuid": {
-              "description": " UUID computed from the file contents, assigned by the Java SDK.",
-              "type": [
-                "string",
-                "null"
-              ],
-              "format": "uuid"
-            }
-          }
-        }
-      ]
-    },
-    "RawStacktrace": {
-      "description": " A stack trace of a single thread.\n\n A stack trace contains a list of frames, each with various bits (most optional) describing the context of that frame. Frames should be sorted from oldest to newest.\n\n For the given example program written in Python:\n\n ```python\n def foo():\n     my_var = 'foo'\n     raise ValueError()\n\n def main():\n     foo()\n ```\n\n A minimalistic stack trace for the above program in the correct order:\n\n ```json\n {\n   \"frames\": [\n     {\"function\": \"main\"},\n     {\"function\": \"foo\"}\n   ]\n }\n ```\n\n The top frame fully symbolicated with five lines of source context:\n\n ```json\n {\n   \"frames\": [{\n     \"in_app\": true,\n     \"function\": \"myfunction\",\n     \"abs_path\": \"/real/file/name.py\",\n     \"filename\": \"file/name.py\",\n     \"lineno\": 3,\n     \"vars\": {\n       \"my_var\": \"'value'\"\n     },\n     \"pre_context\": [\n       \"def foo():\",\n       \"  my_var = 'foo'\",\n     ],\n     \"context_line\": \"  raise ValueError()\",\n     \"post_context\": [\n       \"\",\n       \"def main():\"\n     ],\n   }]\n }\n ```\n\n A minimal native stack trace with register values. Note that the `package` event attribute must be \"native\" for these frames to be symbolicated.\n\n ```json\n {\n   \"frames\": [\n     {\"instruction_addr\": \"0x7fff5bf3456c\"},\n     {\"instruction_addr\": \"0x7fff5bf346c0\"},\n   ],\n   \"registers\": {\n     \"rip\": \"0x00007ff6eef54be2\",\n     \"rsp\": \"0x0000003b710cd9e0\"\n   }\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "required": [
-            "frames"
-          ],
-          "properties": {
-            "frames": {
-              "description": " Required. A non-empty list of stack frames. The list is ordered from caller to callee, or oldest to youngest. The last frame is the one creating the exception.",
-              "type": [
-                "array",
-                "null"
-              ],
-              "items": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/Frame"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            },
-            "lang": {
-              "description": " The language of the stacktrace.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "registers": {
-              "description": " Register values of the thread (top frame).\n\n A map of register names and their values. The values should contain the actual register values of the thread, thus mapping to the last frame in the list.",
-              "default": null,
-              "type": [
-                "object",
-                "null"
-              ],
-              "additionalProperties": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/RegVal"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            }
-          }
-        }
-      ]
-    },
-    "RegVal": {
-      "type": "string"
-    },
-    "Request": {
-      "description": " Http request information.\n\n The Request interface contains information on a HTTP request related to the event. In client\n SDKs, this can be an outgoing request, or the request that rendered the current web page. On\n server SDKs, this could be the incoming web request that is being handled.\n\n The data variable should only contain the request body (not the query string). It can either be\n a dictionary (for standard HTTP requests) or a raw request body.\n\n ### Ordered Maps\n\n In the Request interface, several attributes can either be declared as string, object, or list\n of tuples. Sentry attempts to parse structured information from the string representation in\n such cases.\n\n Sometimes, keys can be declared multiple times, or the order of elements matters. In such\n cases, use the tuple representation over a plain object.\n\n Example of request headers as object:\n\n ```json\n {\n   \"content-type\": \"application/json\",\n   \"accept\": \"application/json, application/xml\"\n }\n ```\n\n Example of the same headers as list of tuples:\n\n ```json\n [\n   [\"content-type\", \"application/json\"],\n   [\"accept\", \"application/json\"],\n   [\"accept\", \"application/xml\"]\n ]\n ```\n\n Example of a fully populated request object:\n\n ```json\n {\n   \"request\": {\n     \"method\": \"POST\",\n     \"url\": \"http://absolute.uri/foo\",\n     \"query_string\": \"query=foobar&page=2\",\n     \"data\": {\n       \"foo\": \"bar\"\n     },\n     \"cookies\": \"PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1;\",\n     \"headers\": {\n       \"content-type\": \"text/html\"\n     },\n     \"env\": {\n       \"REMOTE_ADDR\": \"192.168.0.1\"\n     }\n   }\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "cookies": {
-              "description": " The cookie values.\n\n Can be given unparsed as string, as dictionary, or as a list of tuples.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Cookies"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "data": {
-              "description": " Request data in any format that makes sense.\n\n SDKs should discard large and binary bodies by default. Can be given as string or\n structural data of any format.",
-              "default": null
-            },
-            "env": {
-              "description": " Server environment data, such as CGI/WSGI.\n\n A dictionary containing environment information passed from the server. This is where\n information such as CGI/WSGI/Rack keys go that are not HTTP headers.\n\n Sentry will explicitly look for `REMOTE_ADDR` to extract an IP address.",
-              "default": null,
-              "type": [
-                "object",
-                "null"
-              ],
-              "additionalProperties": true
-            },
-            "fragment": {
-              "description": " The fragment of the request URL.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "headers": {
-              "description": " A dictionary of submitted headers.\n\n If a header appears multiple times it, needs to be merged according to the HTTP standard\n for header merging. Header names are treated case-insensitively by Sentry.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Headers"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "inferred_content_type": {
-              "description": " The inferred content type of the request payload.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "method": {
-              "description": " HTTP request method.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "query_string": {
-              "description": " The query string component of the URL.\n\n Can be given as unparsed string, dictionary, or list of tuples.\n\n If the query string is not declared and part of the `url`, Sentry moves it to the\n query string.",
-              "default": null,
-              "anyOf": [
-                {
-                  "anyOf": [
-                    {
-                      "type": "string"
-                    },
-                    {
-                      "anyOf": [
-                        {
-                          "type": "object",
-                          "additionalProperties": {
-                            "type": [
-                              "string",
-                              "null"
-                            ]
-                          }
-                        },
-                        {
-                          "type": "array",
-                          "items": {
-                            "type": [
-                              "array",
-                              "null"
-                            ],
-                            "items": [
-                              {
-                                "type": [
-                                  "string",
-                                  "null"
-                                ]
-                              },
-                              {
-                                "type": [
-                                  "string",
-                                  "null"
-                                ]
-                              }
-                            ],
-                            "maxItems": 2,
-                            "minItems": 2
-                          }
-                        }
-                      ]
-                    }
-                  ]
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "url": {
-              "description": " The URL of the request if available.\n\nThe query string can be declared either as part of the `url`, or separately in `query_string`.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "RuntimeContext": {
-      "description": " Runtime information.\n\n Runtime context describes a runtime in more detail. Typically, this context is present in\n `contexts` multiple times if multiple runtimes are involved (for instance, if you have a\n JavaScript application running on top of JVM).",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "build": {
-              "description": " Application build string, if it is separate from the version.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "name": {
-              "description": " Runtime name.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "raw_description": {
-              "description": " Unprocessed runtime info.\n\n An unprocessed description string obtained by the runtime. For some well-known runtimes,\n Sentry will attempt to parse `name` and `version` from this string, if they are not\n explicitly given.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "version": {
-              "description": " Runtime version string.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "SpanId": {
-      "description": " A 16-character hex string as described in the W3C trace context spec.",
-      "anyOf": [
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "SpanStatus": {
-      "description": "Trace status.\n\nValues from https://github.com/open-telemetry/opentelemetry-specification/blob/8fb6c14e4709e75a9aaa64b0dbbdf02a6067682a/specification/api-tracing.md#status Mapping to HTTP from https://github.com/open-telemetry/opentelemetry-specification/blob/8fb6c14e4709e75a9aaa64b0dbbdf02a6067682a/specification/data-http.md#status",
-      "type": "string",
-      "enum": [
-        "ok",
-        "cancelled",
-        "unknown",
-        "invalid_argument",
-        "deadline_exceeded",
-        "not_found",
-        "already_exists",
-        "permission_denied",
-        "resource_exhausted",
-        "failed_precondition",
-        "aborted",
-        "out_of_range",
-        "unimplemented",
-        "internal_error",
-        "unavailable",
-        "data_loss",
-        "unauthenticated"
-      ]
-    },
-    "Stacktrace": {
-      "anyOf": [
-        {
-          "$ref": "#/definitions/RawStacktrace"
-        }
-      ]
-    },
-    "String": {
-      "type": "string"
-    },
-    "SystemSdkInfo": {
-      "description": " Holds information about the system SDK.\n\n This is relevant for iOS and other platforms that have a system\n SDK.  Not to be confused with the client SDK.",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "sdk_name": {
-              "description": " The internal name of the SDK.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "version_major": {
-              "description": " The major version of the SDK as integer or 0.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "version_minor": {
-              "description": " The minor version of the SDK as integer or 0.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            },
-            "version_patchlevel": {
-              "description": " The patch version of the SDK as integer or 0.",
-              "default": null,
-              "type": [
-                "integer",
-                "null"
-              ],
-              "format": "uint64",
-              "minimum": 0.0
-            }
-          }
-        }
-      ]
-    },
-    "TagEntry": {
-      "anyOf": [
-        {
-          "type": "array",
-          "items": [
-            {
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            {
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          ],
-          "maxItems": 2,
-          "minItems": 2
-        }
-      ]
-    },
-    "Tags": {
-      "description": " Manual key/value tag pairs.",
-      "anyOf": [
-        {
-          "anyOf": [
-            {
-              "type": "object",
-              "additionalProperties": {
-                "type": [
-                  "string",
-                  "null"
-                ]
-              }
-            },
-            {
-              "type": "array",
-              "items": {
-                "anyOf": [
-                  {
-                    "$ref": "#/definitions/TagEntry"
-                  },
-                  {
-                    "type": "null"
-                  }
-                ]
-              }
-            }
-          ]
-        }
-      ]
-    },
-    "Thread": {
-      "description": " A process thread of an event.\n\n The Threads Interface specifies threads that were running at the time an event happened. These threads can also contain stack traces.\n\n An event may contain one or more threads in an attribute named `threads`.\n\n The following example illustrates the threads part of the event payload and omits other attributes for simplicity.\n\n ```json\n {\n   \"threads\": {\n     \"values\": [\n       {\n         \"id\": \"0\",\n         \"name\": \"main\",\n         \"crashed\": true,\n         \"stacktrace\": {}\n       }\n     ]\n   }\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "crashed": {
-              "description": " A flag indicating whether the thread crashed. Defaults to `false`.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "current": {
-              "description": " A flag indicating whether the thread was in the foreground.  Defaults to `false`.",
-              "default": null,
-              "type": [
-                "boolean",
-                "null"
-              ]
-            },
-            "id": {
-              "description": " The ID of the thread. Typically a number or numeric string.\n\n Needs to be unique among the threads. An exception can set the `thread_id` attribute to cross-reference this thread.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/ThreadId"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "name": {
-              "description": " Display name of this thread.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "stacktrace": {
-              "description": " Stack trace containing frames of this exception.\n\n The thread that crashed with an exception should not have a stack trace, but instead, the `thread_id` attribute should be set on the exception and Sentry will connect the two.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Stacktrace"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "ThreadId": {
-      "description": " Represents a thread id.",
-      "anyOf": [
-        {
-          "type": "integer",
-          "format": "uint64",
-          "minimum": 0.0
-        },
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "Timestamp": {
-      "description": "Can be a ISO-8601 formatted string or a unix timestamp in seconds (floating point values allowed).\n\nMust be UTC.",
-      "anyOf": [
-        {
-          "type": "number",
-          "format": "double"
-        },
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "TraceContext": {
-      "description": " Trace context",
-      "anyOf": [
-        {
-          "type": "object",
-          "required": [
-            "span_id",
-            "trace_id"
-          ],
-          "properties": {
-            "op": {
-              "description": " Span type (see `OperationType` docs).",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "parent_span_id": {
-              "description": " The ID of the span enclosing this span.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/SpanId"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "span_id": {
-              "description": " The ID of the span.",
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/SpanId"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "status": {
-              "description": " Whether the trace failed or succeeded. Currently only used to indicate status of individual\n transactions.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/SpanStatus"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "trace_id": {
-              "description": " The trace ID.",
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/TraceId"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            }
-          }
-        }
-      ]
-    },
-    "TraceId": {
-      "description": " A 32-character hex string as described in the W3C trace context spec.",
-      "anyOf": [
-        {
-          "type": "string"
-        }
-      ]
-    },
-    "User": {
-      "description": " Information about the user who triggered an event.\n\n ```json\n {\n   \"user\": {\n     \"id\": \"unique_id\",\n     \"username\": \"my_user\",\n     \"email\": \"foo@example.com\",\n     \"ip_address\": \"127.0.0.1\",\n     \"subscription\": \"basic\"\n   }\n }\n ```",
-      "anyOf": [
-        {
-          "type": "object",
-          "properties": {
-            "data": {
-              "description": " Additional arbitrary fields, as stored in the database (and sometimes as sent by clients).\n All data from `self.other` should end up here after store normalization.",
-              "default": null,
-              "type": [
-                "object",
-                "null"
-              ],
-              "additionalProperties": true
-            },
-            "email": {
-              "description": " Email address of the user.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "geo": {
-              "description": " Approximate geographical location of the end user or device.",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/Geo"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "id": {
-              "description": " Unique identifier of the user.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "ip_address": {
-              "description": " Remote IP address of the user. Defaults to \"{{auto}}\".",
-              "default": null,
-              "anyOf": [
-                {
-                  "$ref": "#/definitions/String"
-                },
-                {
-                  "type": "null"
-                }
-              ]
-            },
-            "name": {
-              "description": " Human readable name of the user.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            },
-            "username": {
-              "description": " Username of the user.",
-              "default": null,
-              "type": [
-                "string",
-                "null"
-              ]
-            }
-          }
-        }
-      ]
-    }
-  }
-}
\ No newline at end of file
diff --git a/snuba/datasets/events_processor_base.py b/snuba/datasets/events_processor_base.py
index 266592d31ad..5dbb3b2922f 100644
--- a/snuba/datasets/events_processor_base.py
+++ b/snuba/datasets/events_processor_base.py
@@ -3,8 +3,7 @@
 from datetime import datetime
 from typing import Any, cast, Mapping, MutableMapping, Optional, Sequence, TypedDict
 
-from jsonschema_typed import JSONSchema
-
+from schemas import EventData
 from snuba import settings
 from snuba.consumer import KafkaMessageMetadata
 from snuba.datasets.events_format import (
@@ -44,8 +43,6 @@
     ]
 )
 
-EventData = JSONSchema["schemas/event.schema.json"]
-
 
 class InsertEvent(TypedDict):
     group_id: Optional[int]

From 60e8e501eb4465910b4e87c73b9850cd4cc60033 Mon Sep 17 00:00:00 2001
From: Filippo Pacifici <filippo.pacifici@gmail.com>
Date: Mon, 4 Jan 2021 09:30:37 -0800
Subject: [PATCH 17/17] Add script to update version

---
 requirements.txt          | 2 +-
 scripts/update-schemas.sh | 9 +++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100755 scripts/update-schemas.sh

diff --git a/requirements.txt b/requirements.txt
index 816ea022e92..603e7e43df8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -26,7 +26,7 @@ MarkupSafe==1.1.1
 mywsgi==1.0.3
 more-itertools==4.2.0
 mypy>=0.761
-git+https://github.com/fpacifici/sentry-data-schemas.git@feat/add_package#subdirectory=pyschemas
+git+https://github.com/getsentry/sentry-data-schemas.git@76c6870d4b81e9c7a3a983cf4f591aeecb579521#subdirectory=py
 packaging==17.1
 parsimonious==0.8.1
 py==1.5.3
diff --git a/scripts/update-schemas.sh b/scripts/update-schemas.sh
new file mode 100755
index 00000000000..ea8207f8230
--- /dev/null
+++ b/scripts/update-schemas.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+SCHEMAS_REPO='https://github.com/getsentry/sentry-data-schemas.git'
+LATEST_VERSION=$(git ls-remote $SCHEMAS_REPO HEAD | awk '{ print $1}')
+
+REGEX='^git\+https\:\/\/github\.com\/getsentry\/sentry\-data\-schemas\.git\@([a-f0-9]+)\#subdirectory=py'
+TEMP='git+https://github.com/getsentry/sentry-data-schemas.git@c123123#subdirectory=py'
+
+echo $TEMP | sed "s/c([1-f0-9]+)/\$LATEST_VERSION/"
