Renames application insights keys to be more clear (#587)

* renames `telemetry_key` to `microsoft_telemetry_key`
* renames `instrumentation_key` to `instance_telemetry_key`
* renames `can_share` to `can_share_with_microsoft`
* renames the `applicationinsights-rs` instances to `internal` and `microsoft` respective of the keys used during construction.

This clarifies the underlying use of Application Insights keys and uses struct tuple to ensure the keys are used correctly via rust's type checker.
This commit is contained in:
bmc-msft
2021-02-26 12:04:49 -05:00
committed by GitHub
parent 8600a44f1f
commit 6a049db3a3
12 changed files with 121 additions and 57 deletions

View File

@ -35,8 +35,8 @@ nodes and the service API running in the Azure Functions instance.
1. The rust library [onefuzz::telemetry](../src/agent/onefuzz-telemetry/src/lib.rs) 1. The rust library [onefuzz::telemetry](../src/agent/onefuzz-telemetry/src/lib.rs)
provides a detailed set of telemetry types, as well as the function provides a detailed set of telemetry types, as well as the function
`can_share`, which gates if a given telemetry field should be sent to the `can_share_with_microsoft`, which gates if a given telemetry field should be
Microsoft central telemetry instance. sent to the Microsoft central telemetry instance.
1. The Python library 1. The Python library
[onefuzzlib.telemetry](../src/api-service/__app__/onefuzzlib/telemetry.py) [onefuzzlib.telemetry](../src/api-service/__app__/onefuzzlib/telemetry.py)
provides a filtering mechanism to identify a per-object set of filtering provides a filtering mechanism to identify a per-object set of filtering

1
src/agent/Cargo.lock generated
View File

@ -1643,6 +1643,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"appinsights", "appinsights",
"log", "log",
"serde",
"tokio", "tokio",
"uuid", "uuid",
] ]

View File

@ -166,13 +166,11 @@ pub fn build_common_config(args: &ArgMatches<'_>) -> Result<CommonConfig> {
}; };
let config = CommonConfig { let config = CommonConfig {
heartbeat_queue: None,
instrumentation_key: None,
telemetry_key: None,
job_id, job_id,
task_id, task_id,
instance_id, instance_id,
setup_dir, setup_dir,
..Default::default()
}; };
Ok(config) Ok(config)
} }

View File

@ -23,7 +23,10 @@ pub async fn run(args: &clap::ArgMatches<'_>) -> Result<()> {
} }
fn init_telemetry(config: &CommonConfig) { fn init_telemetry(config: &CommonConfig) {
onefuzz_telemetry::set_appinsights_clients(config.instrumentation_key, config.telemetry_key); onefuzz_telemetry::set_appinsights_clients(
config.instance_telemetry_key.clone(),
config.microsoft_telemetry_key.clone(),
);
} }
pub fn args(name: &str) -> App<'static, 'static> { pub fn args(name: &str) -> App<'static, 'static> {

View File

@ -5,7 +5,10 @@
use crate::tasks::{analysis, coverage, fuzz, heartbeat::*, merge, report}; use crate::tasks::{analysis, coverage, fuzz, heartbeat::*, merge, report};
use anyhow::Result; use anyhow::Result;
use onefuzz::machine_id::{get_machine_id, get_scaleset_name}; use onefuzz::machine_id::{get_machine_id, get_scaleset_name};
use onefuzz_telemetry::{self as telemetry, Event::task_start, EventData, Role}; use onefuzz_telemetry::{
self as telemetry, Event::task_start, EventData, InstanceTelemetryKey, MicrosoftTelemetryKey,
Role,
};
use reqwest::Url; use reqwest::Url;
use serde::{self, Deserialize}; use serde::{self, Deserialize};
use std::path::PathBuf; use std::path::PathBuf;
@ -26,11 +29,15 @@ pub struct CommonConfig {
pub instance_id: Uuid, pub instance_id: Uuid,
pub instrumentation_key: Option<Uuid>,
pub heartbeat_queue: Option<Url>, pub heartbeat_queue: Option<Url>,
pub telemetry_key: Option<Uuid>, // TODO: remove the alias once the service has been updated to match
#[serde(alias = "instrumentation_key")]
pub instance_telemetry_key: Option<InstanceTelemetryKey>,
// TODO: remove the alias once the service has been updated to match
#[serde(alias = "telemetry_key")]
pub microsoft_telemetry_key: Option<MicrosoftTelemetryKey>,
#[serde(default)] #[serde(default)]
pub setup_dir: PathBuf, pub setup_dir: PathBuf,

View File

@ -6,6 +6,7 @@ use onefuzz::{
http::{is_auth_error_code, ResponseExt}, http::{is_auth_error_code, ResponseExt},
jitter::delay_with_jitter, jitter::delay_with_jitter,
}; };
use onefuzz_telemetry::{InstanceTelemetryKey, MicrosoftTelemetryKey};
use reqwest_retry::SendRetry; use reqwest_retry::SendRetry;
use std::{ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
@ -25,9 +26,13 @@ pub struct StaticConfig {
pub onefuzz_url: Url, pub onefuzz_url: Url,
pub instrumentation_key: Option<Uuid>, // TODO: remove the alias once the service has been updated to match
#[serde(alias = "instrumentation_key")]
pub instance_telemetry_key: Option<InstanceTelemetryKey>,
pub telemetry_key: Option<Uuid>, // TODO: remove the alias once the service has been updated to match
#[serde(alias = "telemetry_key")]
pub microsoft_telemetry_key: Option<MicrosoftTelemetryKey>,
pub heartbeat_queue: Option<Url>, pub heartbeat_queue: Option<Url>,
@ -43,9 +48,13 @@ struct RawStaticConfig {
pub onefuzz_url: Url, pub onefuzz_url: Url,
pub instrumentation_key: Option<Uuid>, // TODO: remove the alias once the service has been updated to match
#[serde(alias = "instrumentation_key")]
pub instance_telemetry_key: Option<InstanceTelemetryKey>,
pub telemetry_key: Option<Uuid>, // TODO: remove the alias once the service has been updated to match
#[serde(alias = "telemetry_key")]
pub microsoft_telemetry_key: Option<MicrosoftTelemetryKey>,
pub heartbeat_queue: Option<Url>, pub heartbeat_queue: Option<Url>,
@ -73,8 +82,8 @@ impl StaticConfig {
credentials, credentials,
pool_name: config.pool_name, pool_name: config.pool_name,
onefuzz_url: config.onefuzz_url, onefuzz_url: config.onefuzz_url,
instrumentation_key: config.instrumentation_key, microsoft_telemetry_key: config.microsoft_telemetry_key,
telemetry_key: config.telemetry_key, instance_telemetry_key: config.instance_telemetry_key,
heartbeat_queue: config.heartbeat_queue, heartbeat_queue: config.heartbeat_queue,
instance_id: config.instance_id, instance_id: config.instance_id,
}; };
@ -103,17 +112,19 @@ impl StaticConfig {
None None
}; };
let instrumentation_key = if let Ok(key) = std::env::var("ONEFUZZ_INSTRUMENTATION_KEY") { let instance_telemetry_key =
Some(Uuid::parse_str(&key)?) if let Ok(key) = std::env::var("ONEFUZZ_INSTANCE_TELEMETRY_KEY") {
} else { Some(InstanceTelemetryKey::new(Uuid::parse_str(&key)?))
None } else {
}; None
};
let telemetry_key = if let Ok(key) = std::env::var("ONEFUZZ_TELEMETRY_KEY") { let microsoft_telemetry_key =
Some(Uuid::parse_str(&key)?) if let Ok(key) = std::env::var("ONEFUZZ_MICROSOFT_TELEMETRY_KEY") {
} else { Some(MicrosoftTelemetryKey::new(Uuid::parse_str(&key)?))
None } else {
}; None
};
let credentials = let credentials =
ClientCredentials::new(client_id, client_secret, onefuzz_url.to_string(), tenant) ClientCredentials::new(client_id, client_secret, onefuzz_url.to_string(), tenant)
@ -124,8 +135,8 @@ impl StaticConfig {
credentials, credentials,
pool_name, pool_name,
onefuzz_url, onefuzz_url,
instrumentation_key, instance_telemetry_key,
telemetry_key, microsoft_telemetry_key,
heartbeat_queue, heartbeat_queue,
}) })
} }

View File

@ -6,8 +6,6 @@ extern crate async_trait;
#[macro_use] #[macro_use]
extern crate downcast_rs; extern crate downcast_rs;
#[macro_use] #[macro_use]
extern crate serde;
#[macro_use]
extern crate clap; extern crate clap;
#[macro_use] #[macro_use]
extern crate anyhow; extern crate anyhow;
@ -226,7 +224,8 @@ async fn run_agent(config: StaticConfig) -> Result<()> {
} }
fn init_telemetry(config: &StaticConfig) { fn init_telemetry(config: &StaticConfig) {
let inst_key = config.instrumentation_key; telemetry::set_appinsights_clients(
let tele_key = config.telemetry_key; config.instance_telemetry_key.clone(),
telemetry::set_appinsights_clients(inst_key, tele_key); config.microsoft_telemetry_key.clone(),
);
} }

View File

@ -9,6 +9,7 @@ license = "MIT"
appinsights = "0.1" appinsights = "0.1"
log = "0.4" log = "0.4"
uuid = { version = "0.8", features = ["serde", "v4"] } uuid = { version = "0.8", features = ["serde", "v4"] }
serde = { version = "1.0", features = ["derive"] }
[dev-dependencies] [dev-dependencies]
tokio = { version = "0.2" } tokio = { version = "0.2" }

View File

@ -1,15 +1,46 @@
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT License. // Licensed under the MIT License.
use serde::{Deserialize, Serialize};
use std::fmt;
use std::sync::{LockResult, RwLockReadGuard, RwLockWriteGuard}; use std::sync::{LockResult, RwLockReadGuard, RwLockWriteGuard};
use uuid::Uuid; use uuid::Uuid;
pub use appinsights::telemetry::SeverityLevel::{Critical, Error, Information, Verbose, Warning}; pub use appinsights::telemetry::SeverityLevel::{Critical, Error, Information, Verbose, Warning};
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct MicrosoftTelemetryKey(Uuid);
impl MicrosoftTelemetryKey {
pub fn new(value: Uuid) -> Self {
Self(value)
}
}
impl fmt::Display for MicrosoftTelemetryKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct InstanceTelemetryKey(Uuid);
impl InstanceTelemetryKey {
pub fn new(value: Uuid) -> Self {
Self(value)
}
}
impl fmt::Display for InstanceTelemetryKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
pub type TelemetryClient = appinsights::TelemetryClient<appinsights::InMemoryChannel>; pub type TelemetryClient = appinsights::TelemetryClient<appinsights::InMemoryChannel>;
pub enum ClientType { pub enum ClientType {
Instance, Instance,
Shared, Microsoft,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@ -133,7 +164,7 @@ impl EventData {
} }
} }
pub fn can_share(&self) -> bool { pub fn can_share_with_microsoft(&self) -> bool {
match self { match self {
// TODO: Request CELA review of Version, as having this for central stats // TODO: Request CELA review of Version, as having this for central stats
// would be useful to track uptake of new releases // would be useful to track uptake of new releases
@ -184,12 +215,12 @@ mod global {
#[derive(Default)] #[derive(Default)]
pub struct Clients { pub struct Clients {
instance: Option<RwLock<TelemetryClient>>, instance: Option<RwLock<TelemetryClient>>,
shared: Option<RwLock<TelemetryClient>>, microsoft: Option<RwLock<TelemetryClient>>,
} }
pub static mut CLIENTS: Clients = Clients { pub static mut CLIENTS: Clients = Clients {
instance: None, instance: None,
shared: None, microsoft: None,
}; };
const UNSET: usize = 0; const UNSET: usize = 0;
const SETTING: usize = 1; const SETTING: usize = 1;
@ -197,7 +228,7 @@ mod global {
static STATE: AtomicUsize = AtomicUsize::new(UNSET); static STATE: AtomicUsize = AtomicUsize::new(UNSET);
pub fn set_clients(instance: Option<TelemetryClient>, shared: Option<TelemetryClient>) { pub fn set_clients(instance: Option<TelemetryClient>, microsoft: Option<TelemetryClient>) {
use Ordering::SeqCst; use Ordering::SeqCst;
let result = STATE.compare_exchange(UNSET, SETTING, SeqCst, SeqCst); let result = STATE.compare_exchange(UNSET, SETTING, SeqCst, SeqCst);
@ -212,7 +243,7 @@ mod global {
unsafe { unsafe {
CLIENTS.instance = instance.map(RwLock::new); CLIENTS.instance = instance.map(RwLock::new);
CLIENTS.shared = shared.map(RwLock::new); CLIENTS.microsoft = microsoft.map(RwLock::new);
} }
STATE.store(SET, SeqCst); STATE.store(SET, SeqCst);
@ -221,7 +252,7 @@ mod global {
pub fn client_lock(client_type: ClientType) -> Option<&'static RwLock<TelemetryClient>> { pub fn client_lock(client_type: ClientType) -> Option<&'static RwLock<TelemetryClient>> {
match client_type { match client_type {
ClientType::Instance => unsafe { CLIENTS.instance.as_ref() }, ClientType::Instance => unsafe { CLIENTS.instance.as_ref() },
ClientType::Shared => unsafe { CLIENTS.shared.as_ref() }, ClientType::Microsoft => unsafe { CLIENTS.microsoft.as_ref() },
} }
} }
@ -239,13 +270,13 @@ mod global {
} }
let instance = unsafe { CLIENTS.instance.take() }; let instance = unsafe { CLIENTS.instance.take() };
let shared = unsafe { CLIENTS.shared.take() }; let microsoft = unsafe { CLIENTS.microsoft.take() };
STATE.store(UNSET, SeqCst); STATE.store(UNSET, SeqCst);
let mut clients = Vec::new(); let mut clients = Vec::new();
for client in vec![instance, shared] { for client in vec![instance, microsoft] {
if let Some(client) = client { if let Some(client) = client {
match client.into_inner() { match client.into_inner() {
Ok(c) => clients.push(c), Ok(c) => clients.push(c),
@ -257,10 +288,13 @@ mod global {
} }
} }
pub fn set_appinsights_clients(ikey: Option<Uuid>, tkey: Option<Uuid>) { pub fn set_appinsights_clients(
let instance_client = ikey.map(|k| TelemetryClient::new(k.to_string())); instance_key: Option<InstanceTelemetryKey>,
let shared_client = tkey.map(|k| TelemetryClient::new(k.to_string())); microsoft_key: Option<MicrosoftTelemetryKey>,
global::set_clients(instance_client, shared_client); ) {
let instance_client = instance_key.map(|k| TelemetryClient::new(k.to_string()));
let microsoft_client = microsoft_key.map(|k| TelemetryClient::new(k.to_string()));
global::set_clients(instance_client, microsoft_client);
} }
/// Try to submit any pending telemetry with a blocking call. /// Try to submit any pending telemetry with a blocking call.
@ -313,8 +347,8 @@ pub fn property(client_type: ClientType, key: impl AsRef<str>) -> Option<String>
pub fn set_property(entry: EventData) { pub fn set_property(entry: EventData) {
let (key, value) = entry.as_values(); let (key, value) = entry.as_values();
if entry.can_share() { if entry.can_share_with_microsoft() {
if let Some(mut client) = client_mut(ClientType::Shared) { if let Some(mut client) = client_mut(ClientType::Microsoft) {
client client
.context_mut() .context_mut()
.properties_mut() .properties_mut()
@ -353,12 +387,12 @@ pub fn track_event(event: Event, properties: Vec<EventData>) {
client.track(evt); client.track(evt);
} }
if let Some(client) = client(ClientType::Shared) { if let Some(client) = client(ClientType::Microsoft) {
let mut evt = appinsights::telemetry::EventTelemetry::new(event.as_str()); let mut evt = appinsights::telemetry::EventTelemetry::new(event.as_str());
let props = evt.properties_mut(); let props = evt.properties_mut();
for property in &properties { for property in &properties {
if property.can_share() { if property.can_share_with_microsoft() {
let (name, val) = property.as_values(); let (name, val) = property.as_values();
props.insert(name.to_string(), val); props.insert(name.to_string(), val);
} }

View File

@ -7,9 +7,6 @@ extern crate anyhow;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
#[macro_use]
extern crate serde;
#[macro_use] #[macro_use]
extern crate onefuzz_telemetry; extern crate onefuzz_telemetry;

View File

@ -1021,6 +1021,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"appinsights", "appinsights",
"log", "log",
"serde",
"uuid", "uuid",
] ]

View File

@ -3,7 +3,9 @@
use crate::proxy; use crate::proxy;
use anyhow::Result; use anyhow::Result;
use onefuzz_telemetry::{set_appinsights_clients, EventData, Role}; use onefuzz_telemetry::{
set_appinsights_clients, EventData, InstanceTelemetryKey, MicrosoftTelemetryKey, Role,
};
use reqwest_retry::SendRetry; use reqwest_retry::SendRetry;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{fs::File, io::BufReader, path::PathBuf}; use std::{fs::File, io::BufReader, path::PathBuf};
@ -43,8 +45,15 @@ pub struct Forward {
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)] #[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
pub struct ConfigData { pub struct ConfigData {
pub instance_id: Uuid, pub instance_id: Uuid,
pub instrumentation_key: Option<Uuid>,
pub telemetry_key: Option<Uuid>, // TODO: remove the alias once the service has been updated to match
#[serde(alias = "instrumentation_key")]
pub instance_telemetry_key: Option<InstanceTelemetryKey>,
// TODO: remove the alias once the service has been updated to match
#[serde(alias = "telemetry_key")]
pub microsoft_telemetry_key: Option<MicrosoftTelemetryKey>,
pub region: String, pub region: String,
pub url: Url, pub url: Url,
pub notification: Url, pub notification: Url,
@ -73,7 +82,10 @@ impl Config {
let data: ConfigData = let data: ConfigData =
serde_json::from_reader(r).map_err(|source| ProxyError::ParseError { source })?; serde_json::from_reader(r).map_err(|source| ProxyError::ParseError { source })?;
set_appinsights_clients(data.instrumentation_key, data.telemetry_key); set_appinsights_clients(
data.instance_telemetry_key.clone(),
data.microsoft_telemetry_key.clone(),
);
onefuzz_telemetry::set_property(EventData::Region(data.region.to_owned())); onefuzz_telemetry::set_property(EventData::Region(data.region.to_owned()));
onefuzz_telemetry::set_property(EventData::Version(env!("ONEFUZZ_VERSION").to_string())); onefuzz_telemetry::set_property(EventData::Version(env!("ONEFUZZ_VERSION").to_string()));