Bug 1654413 - Add MarkerSchema struct and its enums for marker API r=emilio,gerald

You can see the `mozilla::MarkerSchema` for the C++ counterpart. This Rust
struct simply wraps the C++ object and keeps the reference of it as RAII. This
heap allocates the inner C++ object but it's fine to do it here, because it's
we only create a MarkerSchema object at the end of a profiling session and it
happens once per marker type. It should be very rare.

Differential Revision: https://phabricator.services.mozilla.com/D124025
This commit is contained in:
Nazım Can Altınova 2021-09-21 11:08:11 +00:00
Родитель c850585eae
Коммит a5b9cfdadb
6 изменённых файлов: 391 добавлений и 0 удалений

Просмотреть файл

@ -760,6 +760,11 @@ class MarkerSchema {
explicit MarkerSchema(Location aLocation, Locations... aLocations)
: mLocations{aLocation, aLocations...} {}
// Alternative constructor for MarkerSchema.
explicit MarkerSchema(const mozilla::MarkerSchema::Location* aLocations,
size_t aLength)
: mLocations(aLocations, aLocations + aLength) {}
// Marker schema for types that have special frontend handling.
// Nothing else should be set in this case.
// Implicit to allow quick return from MarkerTypeDisplay functions.

Просмотреть файл

@ -111,6 +111,107 @@ void gecko_profiler_destruct_marker_timing(
#endif
}
void gecko_profiler_construct_marker_schema(
mozilla::MarkerSchema* aMarkerSchema,
const mozilla::MarkerSchema::Location* aLocations, size_t aLength) {
#ifdef MOZ_GECKO_PROFILER
new (aMarkerSchema) mozilla::MarkerSchema(aLocations, aLength);
#endif
}
void gecko_profiler_construct_marker_schema_with_special_front_end_location(
mozilla::MarkerSchema* aMarkerSchema) {
#ifdef MOZ_GECKO_PROFILER
new (aMarkerSchema)
mozilla::MarkerSchema(mozilla::MarkerSchema::SpecialFrontendLocation{});
#endif
}
void gecko_profiler_destruct_marker_schema(
mozilla::MarkerSchema* aMarkerSchema) {
#ifdef MOZ_GECKO_PROFILER
aMarkerSchema->~MarkerSchema();
#endif
}
void gecko_profiler_marker_schema_set_chart_label(
mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength) {
#ifdef MOZ_GECKO_PROFILER
aSchema->SetChartLabel(std::string(aLabel, aLabelLength));
#endif
}
void gecko_profiler_marker_schema_set_tooltip_label(
mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength) {
#ifdef MOZ_GECKO_PROFILER
aSchema->SetTooltipLabel(std::string(aLabel, aLabelLength));
#endif
}
void gecko_profiler_marker_schema_set_table_label(
mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength) {
#ifdef MOZ_GECKO_PROFILER
aSchema->SetTableLabel(std::string(aLabel, aLabelLength));
#endif
}
void gecko_profiler_marker_schema_set_all_labels(mozilla::MarkerSchema* aSchema,
const char* aLabel,
size_t aLabelLength) {
#ifdef MOZ_GECKO_PROFILER
aSchema->SetAllLabels(std::string(aLabel, aLabelLength));
#endif
}
void gecko_profiler_marker_schema_add_key_format(
mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength,
mozilla::MarkerSchema::Format aFormat) {
#ifdef MOZ_GECKO_PROFILER
aSchema->AddKeyFormat(std::string(aKey, aKeyLength), aFormat);
#endif
}
void gecko_profiler_marker_schema_add_key_label_format(
mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength,
const char* aLabel, size_t aLabelLength,
mozilla::MarkerSchema::Format aFormat) {
#ifdef MOZ_GECKO_PROFILER
aSchema->AddKeyLabelFormat(std::string(aKey, aKeyLength),
std::string(aLabel, aLabelLength), aFormat);
#endif
}
void gecko_profiler_marker_schema_add_key_format_searchable(
mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength,
mozilla::MarkerSchema::Format aFormat,
mozilla::MarkerSchema::Searchable aSearchable) {
#ifdef MOZ_GECKO_PROFILER
aSchema->AddKeyFormatSearchable(std::string(aKey, aKeyLength), aFormat,
aSearchable);
#endif
}
void gecko_profiler_marker_schema_add_key_label_format_searchable(
mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength,
const char* aLabel, size_t aLabelLength,
mozilla::MarkerSchema::Format aFormat,
mozilla::MarkerSchema::Searchable aSearchable) {
#ifdef MOZ_GECKO_PROFILER
aSchema->AddKeyLabelFormatSearchable(std::string(aKey, aKeyLength),
std::string(aLabel, aLabelLength),
aFormat, aSearchable);
#endif
}
void gecko_profiler_marker_schema_add_static_label_value(
mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength,
const char* aValue, size_t aValueLength) {
#ifdef MOZ_GECKO_PROFILER
aSchema->AddStaticLabelValue(std::string(aLabel, aLabelLength),
std::string(aValue, aValueLength));
#endif
}
void gecko_profiler_json_writer_int_property(
mozilla::baseprofiler::SpliceableJSONWriter* aWriter, const char* aName,
size_t aNameLength, int64_t aValue) {

Просмотреть файл

@ -9,11 +9,14 @@
#ifndef ProfilerBindings_h
#define ProfilerBindings_h
#include "mozilla/BaseProfilerMarkersPrerequisites.h"
#include <cstddef>
#include <stdint.h>
namespace mozilla {
class AutoProfilerLabel;
class MarkerSchema;
class MarkerTiming;
class TimeStamp;
enum class StackCaptureOptions;
@ -61,6 +64,47 @@ void gecko_profiler_construct_marker_timing_interval_end(
void gecko_profiler_destruct_marker_timing(
mozilla::MarkerTiming* aMarkerTiming);
// MarkerSchema constructors and destructor.
void gecko_profiler_construct_marker_schema(
mozilla::MarkerSchema* aMarkerSchema,
const mozilla::MarkerSchema::Location* aLocations, size_t aLength);
void gecko_profiler_construct_marker_schema_with_special_front_end_location(
mozilla::MarkerSchema* aMarkerSchema);
void gecko_profiler_destruct_marker_schema(
mozilla::MarkerSchema* aMarkerSchema);
// MarkerSchema methods for adding labels.
void gecko_profiler_marker_schema_set_chart_label(
mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength);
void gecko_profiler_marker_schema_set_tooltip_label(
mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength);
void gecko_profiler_marker_schema_set_table_label(
mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength);
void gecko_profiler_marker_schema_set_all_labels(mozilla::MarkerSchema* aSchema,
const char* aLabel,
size_t aLabelLength);
// MarkerSchema methods for adding key/key-label values.
void gecko_profiler_marker_schema_add_key_format(
mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength,
mozilla::MarkerSchema::Format aFormat);
void gecko_profiler_marker_schema_add_key_label_format(
mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength,
const char* aLabel, size_t aLabelLength,
mozilla::MarkerSchema::Format aFormat);
void gecko_profiler_marker_schema_add_key_format_searchable(
mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength,
mozilla::MarkerSchema::Format aFormat,
mozilla::MarkerSchema::Searchable aSearchable);
void gecko_profiler_marker_schema_add_key_label_format_searchable(
mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength,
const char* aLabel, size_t aLabelLength,
mozilla::MarkerSchema::Format aFormat,
mozilla::MarkerSchema::Searchable aSearchable);
void gecko_profiler_marker_schema_add_static_label_value(
mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength,
const char* aValue, size_t aValueLength);
// Various SpliceableJSONWriter methods to add properties.
void gecko_profiler_json_writer_int_property(
mozilla::baseprofiler::SpliceableJSONWriter* aWriter, const char* aName,

Просмотреть файл

@ -90,6 +90,13 @@ fn generate_bindings() {
.whitelist_var("mozilla::profiler::detail::RacyFeatures::sActiveAndFeatures")
.whitelist_type("mozilla::profiler::detail::RacyFeatures")
.rustified_enum("mozilla::StackCaptureOptions")
.rustified_enum("mozilla::MarkerSchema_Location")
.rustified_enum("mozilla::MarkerSchema_Format")
.rustified_enum("mozilla::MarkerSchema_Searchable")
// Converting std::string to an opaque type makes some platforms build
// successfully. Otherwise, it fails to build because MarkerSchema has
// some std::strings as its fields.
.opaque_type("std::string")
.raw_line("pub use self::root::*;")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.

Просмотреть файл

@ -67,6 +67,7 @@
//! TODO: Explain the marker API once we have them in the following patches.
pub mod options;
pub mod schema;
use crate::gecko_bindings::{bindings, profiling_categories::ProfilingCategoryPair};
use crate::marker::options::MarkerOptions;

Просмотреть файл

@ -0,0 +1,233 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
//! [`MarkerSchema`] and other enums that will be used by `MarkerSchema`.
use crate::gecko_bindings::{bindings, structs::mozilla};
use std::mem::MaybeUninit;
use std::ops::DerefMut;
use std::os::raw::c_char;
use std::pin::Pin;
/// Marker locations to be displayed in the profiler front-end.
pub type Location = mozilla::MarkerSchema_Location;
/// Formats of marker properties for profiler front-end.
pub type Format = mozilla::MarkerSchema_Format;
/// Whether it's searchable or not in the profiler front-end.
pub type Searchable = mozilla::MarkerSchema_Searchable;
/// This object collects all the information necessary to stream the JSON schema
/// that informs the front-end how to display a type of markers.
/// It will be created and populated in `marker_type_display()` functions in each
/// marker type definition, see add/set functions.
///
/// It's a RAII object that constructs and destroys a C++ MarkerSchema object
/// pointed to a specified reference.
pub struct MarkerSchema {
pub(crate) pin: Pin<Box<MaybeUninit<mozilla::MarkerSchema>>>,
}
impl MarkerSchema {
// Initialize a marker schema with the given `Location`s.
pub fn new(locations: &[Location]) -> Self {
let mut marker_schema = Box::pin(std::mem::MaybeUninit::<mozilla::MarkerSchema>::uninit());
unsafe {
bindings::gecko_profiler_construct_marker_schema(
marker_schema.deref_mut().as_mut_ptr(),
locations.as_ptr(),
locations.len(),
);
}
MarkerSchema { pin: marker_schema }
}
/// Marker schema for types that have special frontend handling.
/// Nothing else should be set in this case.
pub fn new_with_special_frontend_location() -> Self {
let mut marker_schema = Box::pin(std::mem::MaybeUninit::<mozilla::MarkerSchema>::uninit());
unsafe {
bindings::gecko_profiler_construct_marker_schema_with_special_front_end_location(
marker_schema.deref_mut().as_mut_ptr(),
);
}
MarkerSchema { pin: marker_schema }
}
/// Optional label in the marker chart.
/// If not provided, the marker "name" will be used. The given string
/// can contain element keys in braces to include data elements streamed by
/// `stream_json_marker_data()`. E.g.: "This is {marker.data.text}"
pub fn set_chart_label(&mut self, label: &str) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_set_chart_label(
self.pin.deref_mut().as_mut_ptr(),
label.as_ptr() as *const c_char,
label.len(),
);
}
self
}
/// Optional label in the marker chart tooltip.
/// If not provided, the marker "name" will be used. The given string
/// can contain element keys in braces to include data elements streamed by
/// `stream_json_marker_data()`. E.g.: "This is {marker.data.text}"
pub fn set_tooltip_label(&mut self, label: &str) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_set_tooltip_label(
self.pin.deref_mut().as_mut_ptr(),
label.as_ptr() as *const c_char,
label.len(),
);
}
self
}
/// Optional label in the marker table.
/// If not provided, the marker "name" will be used. The given string
/// can contain element keys in braces to include data elements streamed by
/// `stream_json_marker_data()`. E.g.: "This is {marker.data.text}"
pub fn set_table_label(&mut self, label: &str) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_set_table_label(
self.pin.deref_mut().as_mut_ptr(),
label.as_ptr() as *const c_char,
label.len(),
);
}
self
}
/// Set all marker chart / marker tooltip / marker table labels with the same text.
/// Same as the individual methods, the given string can contain element keys
/// in braces to include data elements streamed by `stream_json_marker_data()`.
/// E.g.: "This is {marker.data.text}"
pub fn set_all_labels(&mut self, label: &str) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_set_all_labels(
self.pin.deref_mut().as_mut_ptr(),
label.as_ptr() as *const c_char,
label.len(),
);
}
self
}
// Each data element that is streamed by `stream_json_marker_data()` can be
// displayed as indicated by using one of the `add_...` function below.
// Each `add...` will add a line in the full marker description. Parameters:
// - `key`: Element property name as streamed by `stream_json_marker_data()`.
// - `label`: Optional label. Defaults to the key name.
// - `format`: How to format the data element value, see `Format` above.
// - `searchable`: Optional, indicates if the value is used in searches,
// defaults to false.
/// Add a key / format row for the marker data element.
/// - `key`: Element property name as streamed by `stream_json_marker_data()`.
/// - `format`: How to format the data element value, see `Format` above.
pub fn add_key_format(&mut self, key: &str, format: Format) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_add_key_format(
self.pin.deref_mut().as_mut_ptr(),
key.as_ptr() as *const c_char,
key.len(),
format,
);
}
self
}
/// Add a key / label / format row for the marker data element.
/// - `key`: Element property name as streamed by `stream_json_marker_data()`.
/// - `label`: Optional label. Defaults to the key name.
/// - `format`: How to format the data element value, see `Format` above.
pub fn add_key_label_format(&mut self, key: &str, label: &str, format: Format) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_add_key_label_format(
self.pin.deref_mut().as_mut_ptr(),
key.as_ptr() as *const c_char,
key.len(),
label.as_ptr() as *const c_char,
label.len(),
format,
);
}
self
}
/// Add a key / format / searchable row for the marker data element.
/// - `key`: Element property name as streamed by `stream_json_marker_data()`.
/// - `format`: How to format the data element value, see `Format` above.
pub fn add_key_format_searchable(
&mut self,
key: &str,
format: Format,
searchable: Searchable,
) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_add_key_format_searchable(
self.pin.deref_mut().as_mut_ptr(),
key.as_ptr() as *const c_char,
key.len(),
format,
searchable,
);
}
self
}
/// Add a key / label / format / searchable row for the marker data element.
/// - `key`: Element property name as streamed by `stream_json_marker_data()`.
/// - `label`: Optional label. Defaults to the key name.
/// - `format`: How to format the data element value, see `Format` above.
/// - `searchable`: Optional, indicates if the value is used in searches,
/// defaults to false.
pub fn add_key_label_format_searchable(
&mut self,
key: &str,
label: &str,
format: Format,
searchable: Searchable,
) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_add_key_label_format_searchable(
self.pin.deref_mut().as_mut_ptr(),
key.as_ptr() as *const c_char,
key.len(),
label.as_ptr() as *const c_char,
label.len(),
format,
searchable,
);
}
self
}
/// Add a key / value static row.
/// - `key`: Element property name as streamed by `stream_json_marker_data()`.
/// - `value`: Static value to display.
pub fn add_static_label_value(&mut self, label: &str, value: &str) -> &mut Self {
unsafe {
bindings::gecko_profiler_marker_schema_add_static_label_value(
self.pin.deref_mut().as_mut_ptr(),
label.as_ptr() as *const c_char,
label.len(),
value.as_ptr() as *const c_char,
value.len(),
);
}
self
}
}
impl Drop for MarkerSchema {
fn drop(&mut self) {
unsafe {
bindings::gecko_profiler_destruct_marker_schema(self.pin.deref_mut().as_mut_ptr());
}
}
}