зеркало из https://github.com/mozilla/glean.git
Add a crate for the nice control API
For now this only supports a minimal interface on top of Glean
This commit is contained in:
Родитель
1833a119f8
Коммит
d78b3041c7
|
@ -331,6 +331,20 @@ dependencies = [
|
|||
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glean-preview"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ffi-support 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glean-core 21.3.0",
|
||||
"glean-ffi 21.3.0",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "goblin"
|
||||
version = "0.0.24"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
members = [
|
||||
"glean-core",
|
||||
"glean-core/ffi",
|
||||
"glean-core/preview",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
|
|
@ -22,7 +22,7 @@ mod from_raw;
|
|||
mod handlemap_ext;
|
||||
mod labeled;
|
||||
mod memory_distribution;
|
||||
mod ping_type;
|
||||
pub mod ping_type;
|
||||
mod quantity;
|
||||
mod string;
|
||||
mod string_list;
|
||||
|
@ -97,11 +97,11 @@ pub extern "C" fn glean_enable_logging() {
|
|||
/// If this side is changed, the Kotlin side need to be changed, too.
|
||||
#[repr(C)]
|
||||
pub struct FfiConfiguration<'a> {
|
||||
data_dir: FfiStr<'a>,
|
||||
package_name: FfiStr<'a>,
|
||||
upload_enabled: u8,
|
||||
max_events: Option<&'a i32>,
|
||||
delay_ping_lifetime_io: u8,
|
||||
pub data_dir: FfiStr<'a>,
|
||||
pub package_name: FfiStr<'a>,
|
||||
pub upload_enabled: u8,
|
||||
pub max_events: Option<&'a i32>,
|
||||
pub delay_ping_lifetime_io: u8,
|
||||
}
|
||||
|
||||
/// Convert the FFI-compatible configuration object into the proper Rust configuration object.
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
[package]
|
||||
name = "glean-preview"
|
||||
version = "0.0.1"
|
||||
authors = ["Jan-Erik Rediger <jrediger@mozilla.com>", "The Glean Team <glean-team@mozilla.com>"]
|
||||
description = "Nice Glean SDK Rust API"
|
||||
repository = "https://github.com/mozilla/glean"
|
||||
readme = "README.md"
|
||||
license = "MPL-2.0"
|
||||
edition = "2018"
|
||||
keywords = ["telemetry", "glean"]
|
||||
include = [
|
||||
"README.md",
|
||||
"LICENSE",
|
||||
"src/**/*",
|
||||
"tests/**/*",
|
||||
"Cargo.toml",
|
||||
]
|
||||
|
||||
[badges]
|
||||
circle-ci = { repository = "mozilla/glean", branch = "master" }
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[dependencies.glean-ffi]
|
||||
path = "../ffi"
|
||||
version = "21.3.0"
|
||||
|
||||
[dependencies.glean-core]
|
||||
path = ".."
|
||||
version = "21.3.0"
|
||||
|
||||
[dependencies]
|
||||
ffi-support = "0.3.5"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
once_cell = "1.2.0"
|
||||
env_logger = { version = "0.7.1", default-features = false, features = ["termcolor", "atty", "humantime"] }
|
||||
tempfile = "3.0.7"
|
||||
log = "0.4.8"
|
|
@ -0,0 +1,45 @@
|
|||
// 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 std::env;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use tempfile::Builder;
|
||||
|
||||
use glean_preview as glean;
|
||||
use glean_preview::{metrics::PingType, Configuration, Error};
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static PrototypePing: Lazy<PingType> = Lazy::new(|| PingType::new("prototype", true, true));
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
env_logger::init();
|
||||
|
||||
let mut args = env::args().skip(1);
|
||||
|
||||
let data_path = if let Some(path) = args.next() {
|
||||
path
|
||||
} else {
|
||||
let root = Builder::new().prefix("simple-db").tempdir().unwrap();
|
||||
root.path().display().to_string()
|
||||
};
|
||||
|
||||
let cfg = Configuration {
|
||||
data_path,
|
||||
application_id: "org.mozilla.glean_core.example".into(),
|
||||
upload_enabled: true,
|
||||
max_events: None,
|
||||
delay_ping_lifetime_io: false,
|
||||
};
|
||||
glean::initialize(cfg)?;
|
||||
glean::register_ping_type(&PrototypePing);
|
||||
|
||||
if glean::send_ping_by_name("prototype") {
|
||||
log::info!("Successfully collected a prototype ping");
|
||||
} else {
|
||||
log::info!("Prototype ping failed");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
// 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/.
|
||||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
//! Glean is a modern approach for recording and sending Telemetry data.
|
||||
//!
|
||||
//! It's in use at Mozilla.
|
||||
//!
|
||||
//! All documentation can be found online:
|
||||
//!
|
||||
//! ## [The Glean SDK Book](https://mozilla.github.io/glean)
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! Initialize Glean, register a ping and then send it.
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! # use glean_preview::{Configuration, Error, metrics::*};
|
||||
//! # fn main() -> Result<(), Error> {
|
||||
//! let cfg = Configuration {
|
||||
//! data_path: "/tmp/data".into(),
|
||||
//! application_id: "org.mozilla.glean_core.example".into(),
|
||||
//! upload_enabled: true,
|
||||
//! max_events: None,
|
||||
//! delay_ping_lifetime_io: false,
|
||||
//! };
|
||||
//! glean_preview::initialize(cfg)?;
|
||||
//!
|
||||
//! let prototype_ping = PingType::new("prototype", true, true);
|
||||
//!
|
||||
//! glean_preview::register_ping_type(&prototype_ping);
|
||||
//!
|
||||
//! prototype_ping.send();
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
use ffi_support::FfiStr;
|
||||
use std::ffi::CString;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub use glean_core::{Configuration, Error, Result};
|
||||
|
||||
pub mod metrics;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref GLEAN_HANDLE: Mutex<u64> = Mutex::new(0);
|
||||
}
|
||||
|
||||
fn with_glean<F, R>(f: F) -> R
|
||||
where
|
||||
F: Fn(u64) -> R,
|
||||
{
|
||||
let lock = GLEAN_HANDLE.lock().unwrap();
|
||||
debug_assert!(*lock != 0);
|
||||
f(*lock)
|
||||
}
|
||||
|
||||
/// Create and initialize a new Glean object.
|
||||
///
|
||||
/// See `glean_core::Glean::new`.
|
||||
pub fn initialize(cfg: Configuration) -> Result<()> {
|
||||
unsafe {
|
||||
let data_dir = CString::new(cfg.data_path).unwrap();
|
||||
let package_name = CString::new(cfg.application_id).unwrap();
|
||||
let upload_enabled = cfg.upload_enabled;
|
||||
let max_events = cfg.max_events.map(|m| m as i32);
|
||||
|
||||
let ffi_cfg = glean_ffi::FfiConfiguration {
|
||||
data_dir: FfiStr::from_cstr(&data_dir),
|
||||
package_name: FfiStr::from_cstr(&package_name),
|
||||
upload_enabled: upload_enabled as u8,
|
||||
max_events: max_events.as_ref(),
|
||||
delay_ping_lifetime_io: false as u8,
|
||||
};
|
||||
|
||||
let handle = glean_ffi::glean_initialize(&ffi_cfg);
|
||||
if handle == 0 {
|
||||
return Err(glean_core::Error::utf8_error());
|
||||
}
|
||||
|
||||
let mut lock = GLEAN_HANDLE.lock().unwrap();
|
||||
*lock = handle;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Set whether upload is enabled or not.
|
||||
///
|
||||
/// See `glean_core::Glean.set_upload_enabled`.
|
||||
pub fn set_upload_enabled(flag: bool) -> bool {
|
||||
with_glean(|glean_handle| {
|
||||
glean_ffi::glean_set_upload_enabled(glean_handle, flag as u8);
|
||||
glean_ffi::glean_is_upload_enabled(glean_handle) != 0
|
||||
})
|
||||
}
|
||||
|
||||
/// Determine whether upload is enabled.
|
||||
///
|
||||
/// See `glean_core::Glean.is_upload_enabled`.
|
||||
pub fn is_upload_enabled() -> bool {
|
||||
with_glean(|glean_handle| glean_ffi::glean_is_upload_enabled(glean_handle) != 0)
|
||||
}
|
||||
|
||||
/// Register a new [`PingType`](metrics/struct.PingType.html).
|
||||
pub fn register_ping_type(ping: &metrics::PingType) {
|
||||
with_glean(|glean_handle| {
|
||||
glean_ffi::ping_type::glean_register_ping_type(glean_handle, ping.handle);
|
||||
})
|
||||
}
|
||||
|
||||
/// Send a ping.
|
||||
///
|
||||
/// See `glean_core::Glean.send_ping`.
|
||||
///
|
||||
/// ## Return value
|
||||
///
|
||||
/// Returns true if a ping was assembled and queued, false otherwise.
|
||||
pub fn send_ping(ping: &metrics::PingType) -> bool {
|
||||
send_ping_by_name(&ping.name)
|
||||
}
|
||||
|
||||
/// Send a ping by name.
|
||||
///
|
||||
/// See `glean_core::Glean.send_ping_by_name`.
|
||||
///
|
||||
/// ## Return value
|
||||
///
|
||||
/// Returns true if a ping was assembled and queued, false otherwise.
|
||||
pub fn send_ping_by_name(ping: &str) -> bool {
|
||||
send_pings_by_name(&[ping])
|
||||
}
|
||||
|
||||
/// Send multiple pings by name
|
||||
///
|
||||
/// ## Return value
|
||||
///
|
||||
/// Returns true if at least one ping was assembled and queued, false otherwise.
|
||||
pub fn send_pings_by_name(pings: &[&str]) -> bool {
|
||||
let array: Vec<CString> = pings.iter().map(|s| CString::new(*s).unwrap()).collect();
|
||||
let ptr_array: Vec<*const _> = array.iter().map(|s| s.as_ptr()).collect();
|
||||
with_glean(|glean_handle| {
|
||||
let res = glean_ffi::glean_send_pings_by_name(
|
||||
glean_handle,
|
||||
ptr_array.as_ptr(),
|
||||
array.len() as i32,
|
||||
);
|
||||
res != 0
|
||||
})
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// 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/.
|
||||
|
||||
//! The different metric types supported by the Glean SDK to handle data.
|
||||
|
||||
mod ping;
|
||||
|
||||
pub use ping::PingType;
|
|
@ -0,0 +1,46 @@
|
|||
// 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 ffi_support::FfiStr;
|
||||
use std::ffi::CString;
|
||||
|
||||
/// Stores information about a ping.
|
||||
///
|
||||
/// This is required so that given metric data queued on disk we can send
|
||||
/// pings with the correct settings, e.g. whether it has a client_id.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PingType {
|
||||
pub(crate) name: String,
|
||||
pub(crate) handle: u64,
|
||||
}
|
||||
|
||||
impl PingType {
|
||||
/// Create a new ping type for the given name, whether to include the client ID and whether to
|
||||
/// send this ping empty.
|
||||
///
|
||||
/// ## Arguments
|
||||
///
|
||||
/// * `name` - The name of the ping.
|
||||
/// * `include_client_id` - Whether to include the client ID in the assembled ping when.
|
||||
/// * `send_if_empty` - Whether the ping should be sent empty or not.
|
||||
pub fn new<A: Into<String>>(name: A, include_client_id: bool, send_if_empty: bool) -> Self {
|
||||
let name = name.into();
|
||||
let ffi_name = CString::new(name.clone()).unwrap();
|
||||
let handle = glean_ffi::ping_type::glean_new_ping_type(
|
||||
FfiStr::from_cstr(&ffi_name),
|
||||
include_client_id as u8,
|
||||
send_if_empty as u8,
|
||||
);
|
||||
Self { name, handle }
|
||||
}
|
||||
|
||||
/// Send the ping.
|
||||
///
|
||||
/// ## Return value
|
||||
///
|
||||
/// Returns true if a ping was assembled and queued, false otherwise.
|
||||
pub fn send(&self) -> bool {
|
||||
crate::send_ping(self)
|
||||
}
|
||||
}
|
|
@ -20,8 +20,8 @@ pub struct PingType {
|
|||
}
|
||||
|
||||
impl PingType {
|
||||
/// Create a new ping type for the given name and whether to include the client ID when
|
||||
/// sending.
|
||||
/// Create a new ping type for the given name, whether to include the client ID and whether to
|
||||
/// send this ping empty.
|
||||
///
|
||||
/// ## Arguments
|
||||
///
|
||||
|
|
Загрузка…
Ссылка в новой задаче