Skip to content

Commit

Permalink
feat(commands): add send-metric command
Browse files Browse the repository at this point in the history
Add CLI command that can emit metrics.

Fixes GH-2001
  • Loading branch information
Elias Ram committed May 14, 2024
1 parent 554f4fc commit b40f9ce
Show file tree
Hide file tree
Showing 67 changed files with 1,507 additions and 42 deletions.
107 changes: 83 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ bytecount = "0.6.3"
chardet = "0.2.4"
chrono = { version = "0.4.31", features = ["serde"] }
clap = { version = "4.1.6", default-features = false, features = [
"derive",
"std",
"suggestions",
"wrap_help",
Expand All @@ -26,6 +27,7 @@ clap = { version = "4.1.6", default-features = false, features = [
] }
clap_complete = "4.4.3"
console = "0.15.5"
crc32fast = "1.4.0"
curl = { version = "0.4.44", features = ["static-curl", "static-ssl"] }
dirs = "4.0.0"
dotenv = "0.15.0"
Expand Down Expand Up @@ -58,10 +60,11 @@ regex = "1.7.3"
runas = "1.0.0"
rust-ini = "0.18.0"
semver = "1.0.16"
sentry = { version = "0.32.2", default-features = false, features = [
sentry = { version = "0.32.3", default-features = false, features = [
"anyhow",
"curl",
"contexts",
"UNSTABLE_metrics",
] }
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.93"
Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sentry/cli",
"version": "2.31.2",
"version": "2.31.0",
"description": "A command line utility to work with Sentry. https://docs.sentry.io/hosted/learn/cli/",
"repository": "git://github.com/getsentry/sentry-cli.git",
"homepage": "https://docs.sentry.io/hosted/learn/cli/",
Expand Down Expand Up @@ -30,13 +30,13 @@
"prettier": "2.8.8"
},
"optionalDependencies": {
"@sentry/cli-darwin": "2.31.2",
"@sentry/cli-linux-arm": "2.31.2",
"@sentry/cli-linux-arm64": "2.31.2",
"@sentry/cli-linux-i686": "2.31.2",
"@sentry/cli-linux-x64": "2.31.2",
"@sentry/cli-win32-i686": "2.31.2",
"@sentry/cli-win32-x64": "2.31.2"
"@sentry/cli-darwin": "2.31.0",
"@sentry/cli-linux-arm": "2.31.0",
"@sentry/cli-linux-arm64": "2.31.0",
"@sentry/cli-linux-i686": "2.31.0",
"@sentry/cli-linux-x64": "2.31.0",
"@sentry/cli-win32-i686": "2.31.0",
"@sentry/cli-win32-x64": "2.31.0"
},
"scripts": {
"postinstall": "node ./scripts/install.js",
Expand Down
46 changes: 46 additions & 0 deletions src/api/envelopes_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use super::{
errors::{ApiErrorKind, ApiResult},
Api, Method,
};
use crate::constants::USER_AGENT;
use anyhow::{anyhow, Result};
use sentry::{protocol::EnvelopeItem, types::Dsn, Envelope};
use std::sync::Arc;

pub struct EnvelopesApi {
api: Arc<Api>,
dsn: Dsn,
}

impl EnvelopesApi {
pub fn try_new() -> ApiResult<EnvelopesApi> {
let api = Api::current();
match api.config.get_dsn() {
Ok(dsn) => Ok(EnvelopesApi { api, dsn }),
Err(_) => Err(ApiErrorKind::DsnMissing.into()),
}
}

pub fn send_item(&self, item: EnvelopeItem) -> Result<()> {
let mut envelope = Envelope::new();
envelope.add_item(item);
self.send_envelope(envelope)
}

pub fn send_envelope(&self, envelope: Envelope) -> Result<()> {
let mut body: Vec<u8> = Vec::new();
envelope.to_writer(&mut body)?;
let url = self.dsn.envelope_api_url();
let auth = self.dsn.to_auth(Some(USER_AGENT));
let response = self
.api
.request(Method::Post, url.as_str(), None)?
.with_header("X-Sentry-Auth", &auth.to_string())?
.with_body(body)?
.send()?;
match response.ok() {
true => Ok(()),
false => Err(anyhow!("Failed to send envelope.")),
}
}
}
2 changes: 2 additions & 0 deletions src/api/errors/api_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub(in crate::api) enum ApiErrorKind {
"Auth token is required for this request. Please run `sentry-cli login` and try again!"
)]
AuthMissing,
#[error("DSN not found. See: https://docs.sentry.io/product/crons/getting-started/cli/#configuration")]
DsnMissing,
}

impl fmt::Display for ApiError {
Expand Down
22 changes: 18 additions & 4 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
mod connection_manager;
mod encoding;
pub(super) mod envelopes_api;
mod errors;
mod pagination;

Expand All @@ -26,6 +27,7 @@ use brotli2::write::BrotliEncoder;
use chrono::Duration;
use chrono::{DateTime, FixedOffset, Utc};
use clap::ArgMatches;
use curl::easy::InfoType;
use flate2::write::GzEncoder;
use if_chain::if_chain;
use lazy_static::lazy_static;
Expand Down Expand Up @@ -1606,13 +1608,21 @@ fn handle_req<W: Write>(
})?;

handle.debug_function(move |info, data| match info {
curl::easy::InfoType::HeaderIn => {
InfoType::HeaderIn => {
log_headers(false, data);
}
curl::easy::InfoType::HeaderOut => {
InfoType::HeaderOut => {
log_headers(true, data);
}
_ => {}
InfoType::DataIn | InfoType::SslDataIn => {
debug!("< {}", String::from_utf8_lossy(data))
}
InfoType::DataOut | InfoType::SslDataOut => {
debug!(">\n{}", String::from_utf8_lossy(data))
}
_ => {
debug!("{}", String::from_utf8_lossy(data))
}
})?;

handle.header_function(move |data| {
Expand Down Expand Up @@ -1741,8 +1751,12 @@ impl ApiRequest {
serde_json::to_writer(&mut body_bytes, &body)
.map_err(|err| ApiError::with_source(ApiErrorKind::CannotSerializeAsJson, err))?;
debug!("json body: {}", String::from_utf8_lossy(&body_bytes));
self.body = Some(body_bytes);
self.headers.append("Content-Type: application/json")?;
self.with_body(body_bytes)
}

pub fn with_body(mut self, body: Vec<u8>) -> ApiResult<Self> {
self.body = Some(body);
Ok(self)
}

Expand Down
Loading

0 comments on commit b40f9ce

Please sign in to comment.