Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/webserial/tests/mochitest/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 25 kB image not shown  

Quelle  annotations.rs

  Sprache: Rust
 

/* 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 https://mozilla.org/MPL/2.0/. */


use super::glean_metrics;
use anyhow::Context;
use glean::private::{
    BooleanMetric, DatetimeMetric, ObjectMetric, QuantityMetric, StringListMetric, StringMetric,
    TimespanMetric,
};
use glean::TestGetValue;

pub struct Annotation {
    pub key: &'static str,
    pub glean_key: &'static str,
    #[cfg(test)]
    pub convert_fn: &'static str,
    pub set_glean_metric: fn(&serde_json::Value) -> anyhow::Result<()>,
    pub test_get_glean_value: fn() -> Option<serde_json::Value>,
}

macro_rules! convert {
    ( $category:ident :: $metric:ident = $func:ident ($key:literal $(, $($args:expr),*)? ) ) => {
        Annotation {
            key: $key,
            glean_key: concat!(stringify!($category), ".", stringify!($metric)),
            #[cfg(test)]
            convert_fn: stringify!($func),
            set_glean_metric: |value: &serde_json::Value| -> anyhow::Result<()> {
                SourceValue(value).try_into().map_err(|e| anyhow::Error::from(e))
                    .and_then(|v| $func(&glean_metrics::$category::$metric, v $(, $($args),*)? ))
                    .context(concat!("while trying to set ", stringify!($category), "::", stringify!($metric), " from annotation ", $key))
            },
            test_get_glean_value: || -> Option<serde_json::Value> {
                glean_metrics::$category::$metric.test_get_value(Some("crash".into()))
                    .map(|v| TestGetValueToJson(v).into())
            }
        }
    };
}

// Env variable set to the file generated by conversions.py (by build.rs).
include!(env!("CONVERSIONS_FILE"));

struct SourceValue<'a>(&'a serde_json::Value);

impl<'a> TryFrom<SourceValue<'a>> for &'a str {
    type Error = anyhow::Error;

    fn try_from(value: SourceValue<'a>) -> Result<Self, Self::Error> {
        value.0.as_str().context("expected a string")
    }
}

impl<'a> TryFrom<SourceValue<'a>> for &'a serde_json::Value {
    type Error = std::convert::Infallible;

    fn try_from(value: SourceValue<'a>) -> Result<Self, Self::Error> {
        Ok(value.0)
    }
}

struct TestGetValueToJson<T>(T);

macro_rules! TestGetValueToJson_passthrough {
    ( $($T:ty),* ) => {
        $(
        impl From<TestGetValueToJson<$T>> for serde_json::Value {
            fn from(value: TestGetValueToJson<$T>) -> Self {
                value.0.into()
            }
        })*
    }
}

TestGetValueToJson_passthrough![serde_json::Value, String, bool, i64, Vec<String>];

impl From<TestGetValueToJson<glean::Datetime>> for serde_json::Value {
    fn from(value: TestGetValueToJson<glean::Datetime>) -> Self {
        let glean::Datetime {
            year,
            month,
            day,
            hour,
            minute,
            second,
            nanosecond,
            offset_seconds,
        } = value.0;

        time::OffsetDateTime::new_in_offset(
            time::Date::from_calendar_date(year, (month as u8).try_into().unwrap(), day as u8)
                .unwrap(),
            time::Time::from_hms_nano(hour as u8, minute as u8, second as u8, nanosecond).unwrap(),
            time::UtcOffset::from_whole_seconds(offset_seconds).unwrap(),
        )
        .to_string()
        .into()
    }
}

fn convert_boolean_to_boolean(metric: &BooleanMetric, value: &str) -> anyhow::Result<()> {
    metric.set(value == "1");
    Ok(())
}

fn convert_string_to_string(metric: &StringMetric, value: &str) -> anyhow::Result<()> {
    metric.set(value.to_owned());
    Ok(())
}

fn convert_u64_to_quantity(metric: &QuantityMetric, value: &str) -> anyhow::Result<()> {
    metric.set(value.parse().context("couldn't parse quantity")?);
    Ok(())
}

fn convert_string_to_string_list(
    metric: &StringListMetric,
    value: &str,
    delimiter: &str,
) -> anyhow::Result<()> {
    metric.set(
        value
            .split(delimiter)
            .filter(|s| !s.is_empty())
            .map(|s| s.to_owned())
            .collect(),
    );
    Ok(())
}

fn convert_to_crash_time(metric: &DatetimeMetric, value: &str) -> anyhow::Result<()> {
    let seconds_since_epoch: i64 = value
        .parse()
        .context("failed to parse crash time seconds")?;
    metric.set(Some(glean_datetime(
        time::OffsetDateTime::from_unix_timestamp(seconds_since_epoch)
            .context("failed to convert crash time unix timestamp")?,
    )));
    Ok(())
}

fn convert_duration_seconds(metric: &TimespanMetric, value: &str) -> anyhow::Result<()> {
    metric.set_raw(std::time::Duration::from_secs(
        value
            .parse()
            .context("failed to parse seconds since last crash")?,
    ));
    Ok(())
}

fn convert_to_environment_uptime(metric: &TimespanMetric, value: &str) -> anyhow::Result<()> {
    metric.set_raw(std::time::Duration::from_secs_f32(
        value.parse().context("failed to parse uptime")?,
    ));
    Ok(())
}

fn convert_to_crash_windows_file_dialog_error_code(
    metric: &StringMetric,
    value: &str,
) -> anyhow::Result<()> {
    metric.set(value.to_owned()); // Just assume it is an integer as expected
    Ok(())
}

fn convert_to_crash_async_shutdown_timeout(
    metric: &ObjectMetric<glean_metrics::crash::AsyncShutdownTimeoutObject>,
    value: &str,
) -> anyhow::Result<()> {
    // The JSON value is stored as a string, so we need to deserialize it.
    let mut value: serde_json::Map<String, serde_json::Value> = serde_json::from_str(value)?;
    metric.set(glean_metrics::crash::AsyncShutdownTimeoutObject {
        broken_add_blockers: {
            if let Some(broken_add_blockers) = value.remove("brokenAddBlockers") {
                let broken_add_blockers = broken_add_blockers
                    .as_array()
                    .context("expected array for brokenAddBlockers")?;
                let mut ret = Vec::with_capacity(broken_add_blockers.len());
                for entry in broken_add_blockers {
                    ret.push(
                        entry
                            .as_str()
                            .context("expected brokenAddBlockers entry to be a string")?
                            .to_owned(),
                    );
                }
                ret
            } else {
                Default::default()
            }
        },
        conditions: {
            if let Some(conditions) = value.remove("conditions") {
                Some(if let Some(s) = conditions.as_str() {
                    s.to_owned()
                } else {
                    serde_json::to_string(&conditions).context("failed to serialize conditions")?
                })
            } else {
                None
            }
        },
        phase: {
            if let Some(phase) = value.remove("phase") {
                Some(
                    phase
                        .as_str()
                        .context("expected phase to be a string")?
                        .to_owned(),
                )
            } else {
                None
            }
        },
    });
    Ok(())
}

fn convert_to_crash_quota_manager_shutdown_timeout(
    metric: &ObjectMetric<glean_metrics::crash::QuotaManagerShutdownTimeoutObject>,
    value: &str,
) -> anyhow::Result<()> {
    // The Glean metric is an array of the lines.
    metric.set(value.lines().map(|s| s.to_owned()).collect::<Vec<_>>());
    Ok(())
}

fn convert_to_crash_stack_traces(
    metric: &ObjectMetric<glean_metrics::crash::StackTracesObject>,
    value: &str,
) -> anyhow::Result<()> {
    // The JSON value is stored as a string, so we need to deserialize it.
    let value: serde_json::Value = serde_json::from_str(value)?;
    let error = value["error"].as_str().map(|s| s.to_owned());
    let crash_type = value["crash_type"].as_str().map(|s| s.to_owned());
    let crash_address = value["crash_address"].as_str().map(|s| s.to_owned());
    let crash_thread = value["crash_thread"].as_i64();
    let main_module = value["main_module"].as_i64();
    let modules = value["modules"]
        .as_array()
        .map(|modules| {
            modules
                .iter()
                .map(|m| glean_metrics::crash::StackTracesObjectModulesItem {
                    base_address: m["base_address"].as_str().map(|s| s.to_owned()),
                    end_address: m["end_address"].as_str().map(|s| s.to_owned()),
                    code_id: m["code_id"].as_str().map(|s| s.to_owned()),
                    debug_file: m["debug_file"].as_str().map(|s| s.to_owned()),
                    debug_id: m["debug_id"].as_str().map(|s| s.to_owned()),
                    filename: m["filename"].as_str().map(|s| s.to_owned()),
                    version: m["version"].as_str().map(|s| s.to_owned()),
                })
                .collect::<Vec<_>>()
        })
        .unwrap_or_default();
    let threads = value["threads"]
        .as_array()
        .map(|threads| {
            threads
                .iter()
                .map(|t| glean_metrics::crash::StackTracesObjectThreadsItem {
                    frames: t["frames"]
                        .as_array()
                        .map(|frames| {
                            frames
                                .iter()
                                .map(|f| {
                                    glean_metrics::crash::StackTracesObjectThreadsItemFramesItem {
                                        module_index: f["module_index"].as_i64(),
                                        ip: f["ip"].as_str().map(|s| s.to_owned()),
                                        trust: f["trust"].as_str().map(|s| s.to_owned()),
                                    }
                                })
                                .collect::<Vec<_>>()
                        })
                        .unwrap_or_default(),
                })
                .collect::<Vec<_>>()
        })
        .unwrap_or_default();
    metric.set(glean_metrics::crash::StackTracesObject {
        error,
        crash_type,
        crash_address,
        crash_thread,
        main_module,
        modules,
        threads,
    });
    Ok(())
}

// The format of the JSON value is defined in getStacktraceAsJsonString
// (mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/ext/Throwable.kt).
fn convert_to_crash_java_exception(
    metric: &ObjectMetric<glean_metrics::crash::JavaExceptionObject>,
    value: &str,
) -> anyhow::Result<()> {
    // The JSON value is stored as a string, so we need to deserialize it.
    let value: serde_json::Map<String, serde_json::Value> = serde_json::from_str(value)?;
    let throwables = value["exception"]["values"]
        .as_array()
        .context("expected throwables array")?
        .iter()
        // The format stores throwables in reverse order (deepest cause first), but we define the
        // glean format to be by top cause first.
        .rev()
        .map(|throwable| &throwable["stacktrace"])
        .map(
            |throwable| glean_metrics::crash::JavaExceptionObjectThrowablesItem {
                message: throwable["value"].as_str().map(ToOwned::to_owned),
                type_name: throwable["module"]
                    .as_str()
                    .zip(throwable["type"].as_str())
                    .map(|(m, t)| format!("{m}.{t}")),
                stack: throwable["frames"]
                    .as_array()
                    .map(|frames| {
                        frames
                            .iter()
                            .map(|frame| {
                                glean_metrics::crash::JavaExceptionObjectThrowablesItemStackItem {
                                    class_name: frame["module"].as_str().map(ToOwned::to_owned),
                                    method_name: frame["function"].as_str().map(ToOwned::to_owned),
                                    is_native: frame["in_app"].as_bool().map(|b| !b),
                                    line: frame["lineno"].as_i64(),
                                    file: frame["filename"].as_str().map(ToOwned::to_owned),
                                }
                            })
                            .collect()
                    })
                    .unwrap_or_default(),
            },
        )
        .collect();

    metric.set(glean_metrics::crash::JavaExceptionObject { throwables });
    Ok(())
}

fn glean_datetime(datetime: time::OffsetDateTime) -> glean::Datetime {
    glean::Datetime {
        year: datetime.year(),
        month: datetime.month() as _,
        day: datetime.day() as _,
        hour: datetime.hour() as _,
        minute: datetime.minute() as _,
        second: datetime.second() as _,
        nanosecond: datetime.nanosecond(),
        offset_seconds: datetime.offset().whole_seconds(),
    }
}

Messung V0.5 in Prozent
C=87 H=90 G=88

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.9Bemerkung:  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.