Skip to content

Commit

Permalink
feat: init instrumentation (#10)
Browse files Browse the repository at this point in the history
* it works

* feat: add audio back

* feat: add more error report

* feat: finish basic instrumentation

* chore: update yt-dlp

* chore: bump to 0.0.3
  • Loading branch information
ajaxbits authored Apr 24, 2024
1 parent 5e73c69 commit fdc0998
Show file tree
Hide file tree
Showing 14 changed files with 954 additions and 729 deletions.
1,451 changes: 843 additions & 608 deletions Cargo.lock

Large diffs are not rendered by default.

20 changes: 12 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
[package]
name = "vpod"
version = "0.1.1"
version = "0.0.3"
edition = "2021"
license = "Unlicense"

[profile.release]
strip = true
lto = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
axum = { version = "0.5.17", features = ["axum-macros", "query"] }
axum = { version = "0.7.5", features = ["tokio", "query", "macros"] }
chrono = { version = "0.4.22", features = ["serde"] }
clap = { version = "4.5.4", features = ["derive", "env"] }
color-eyre = "0.6.3"
color-eyre = { version = "0.6.3", features = [
"issue-url",
"tracing-error",
"capture-spantrace",
"color-spantrace",
] }
fs_extra = "1.3.0"
futures = "0.3.25"
html-escape = "0.2.11"
Expand All @@ -33,12 +36,13 @@ serde_path_to_error = "0.1.8"
thiserror = "1.0.59"
tokio = { version = "1.21.2", features = ["full"] }
tokio-util = "0.7.4"
tower = "0.4.13"
tower-http = { version = "0.3.4", features = ["fs", "trace"] }
tracing = "0.1.40"
tower = { version = "0.4.13", features = ["util"] }
tower-http = { version = "0.5", features = ["fs", "trace"] }
tracing = { version = "0.1.40", features = ["attributes"] }
tracing-error = "0.2.0"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json"] }
url = "2.5.0"
valuable = { version = "0.1.0", features = ["derive"] }
youtube_dl = { version = "0.7.0", default-features = false, features = [
"yt-dlp",
"tokio",
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

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

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
system = "x86_64-linux";

name = "vpod";
version = "0.1.1";
version = "0.0.3";

eachSystem = f: nixpkgs.lib.genAttrs (import systems) (system: f nixpkgs.legacyPackages.${system});
treefmtEval = eachSystem (pkgs: treefmt-nix.lib.evalModule pkgs ./treefmt.nix);
Expand Down
42 changes: 0 additions & 42 deletions fly.staging.toml

This file was deleted.

1 change: 1 addition & 0 deletions fly.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ processes = []

[env]
EPISODE_URL = "https://vpod.fly.dev"
VERBOSITY = 2

[build]
image = "registry.fly.io/vpod:0.1.0"
Expand Down
36 changes: 18 additions & 18 deletions src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ use std::{
path::{Path, PathBuf},
};

use axum::{response::IntoResponse, routing::get_service};
use color_eyre::eyre::eyre;
use crate::error::{Result, VpodError};
use axum::response::IntoResponse;
use tower::ServiceExt;
use ytd_rs::Arg;

// #[axum::debug_handler]
#[tracing::instrument]
#[tracing::instrument(fields(feed_id=feed_id, episode_id=ep_id))]
pub async fn return_audio(
axum::extract::Path((feed_id, ep_id)): axum::extract::Path<(String, String)>,
) -> crate::error::Result<impl IntoResponse> {
tracing::info!("serving episode");
request: axum::extract::Request,
) -> Result<impl IntoResponse> {
let url = format!("https://www.youtube.com/watch?v={ep_id}");
let path = format!("{feed_id}/{ep_id}.m4a");
let path = std::path::Path::new(&path);
if !path.exists() {
// eprintln!("got here");
let args = vec![
// TODO: Implement an enum allowing users to safely
// add their own options to this list
Expand All @@ -29,32 +29,32 @@ pub async fn return_audio(
Arg::new_with_arg("--sponsorblock-mark", "sponsor,selfpromo"),
Arg::new_with_arg("--output", "%(id)s.m4a"),
];
let _ytd = ytd_rs::YoutubeDL::new(&PathBuf::from(&path.parent().unwrap()), args, &url)
.unwrap()
let channel_dir = &PathBuf::from(&path.parent().unwrap());
// eprintln!("{channel_dir:?}");
let _ytd = ytd_rs::YoutubeDL::new(channel_dir, args, &url)
.map_err(|_| VpodError::YoutubeDLError)?
.download();

let target_dir_size = env::var("TARGET_DIR_SIZE").unwrap_or("100000".to_string());
let target_dir_size: u64 = target_dir_size.parse::<u64>().unwrap();
let dir = path.parent().unwrap();

if let Err(e) = reduce_dir_size(dir, target_dir_size) {
return Err(eyre!("Failed to reduce directory size: {:?}", e))?;
// Call to the new function
match reduce_dir_size(dir, target_dir_size) {
Err(e) => eprintln!("Failed to reduce directory size: {:?}", e),
_ => (),
}
}

let req = hyper::Request::builder()
.uri(ep_id)
.body(axum::body::Body::empty())?;

let service =
get_service(tower_http::services::ServeFile::new(path)).handle_error(crate::handle_error);
let service = tower_http::services::ServeFile::new(path);

let result = service.oneshot(req).await;
let result = service.oneshot(request).await;

Ok(result)
}

fn reduce_dir_size(dir: &Path, target_dir_size: u64) -> std::io::Result<()> {
#[tracing::instrument]
fn reduce_dir_size(dir: &Path, target_dir_size: u64) -> Result<()> {
let dir_size: u64 = fs_extra::dir::get_size(dir)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?
/ 1000; //Kb
Expand Down
4 changes: 2 additions & 2 deletions src/cli/instrumentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ pub(crate) struct Instrumentation {
pub(crate) logger: Logger,

#[clap(
long = "log-filters",
env = "LOG_FILTERS",
long = "log-directive",
env = "LOG_DIRECTIVES",
value_delimiter = ',',
num_args = 0..,
global = true
Expand Down
3 changes: 3 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ pub(crate) struct Cli {

#[clap(long, env = "EPISODE_URL")]
pub(crate) episode_url: Url,

#[clap(flatten)]
pub(crate) instrumentation: instrumentation::Instrumentation,
}
16 changes: 13 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,24 @@ impl IntoResponse for Report {

#[derive(thiserror::Error, Debug)]
pub(crate) enum VpodError {
#[error("A spooky thing happened")]
Spooky,
#[error("could not find channel ID")]
ChannelNotFound,
#[error("playlist ID not found in url")]
PlaylistIdNotFound,
#[error("error running youtube-dlp")]
YoutubeDLError,
}

impl VpodError {
fn response(&self) -> Response {
match self {
Self::Spooky => (StatusCode::IM_A_TEAPOT, "This is a test error").into_response(),
Self::ChannelNotFound => (StatusCode::NOT_FOUND, "Channel not found").into_response(),
Self::PlaylistIdNotFound => {
(StatusCode::NOT_FOUND, "Channel not found").into_response()
}
Self::YoutubeDLError => {
(StatusCode::INTERNAL_SERVER_ERROR, "Error getting audio").into_response()
}
}
}
}
40 changes: 23 additions & 17 deletions src/feed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::{
use axum::{
extract::{Path, Query},
response::IntoResponse,
routing::get_service,
};
use futures::StreamExt;
use hyper::body;
Expand All @@ -18,10 +17,14 @@ mod episode;
mod utils;
use episode::Episode;

use crate::error::{Result, VpodError};

#[tracing::instrument]
pub async fn serve_feed(
Path(YtPath { path_type, val }): Path<YtPath>,
Query(query): Query<HashMap<String, String>>,
) -> impl IntoResponse {
_request: axum::extract::Request,
) -> Result<impl IntoResponse> {
let yt_url = match path_type.clone() {
YtPathType::Handle(handle) => format!("https://www.youtube.com/{handle}"),
YtPathType::Abbrev(type_string)
Expand All @@ -39,30 +42,29 @@ pub async fn serve_feed(
YtPathType::Playlist(_) => {
let pl_id = query
.get("list")
.expect("playlists need to have an id in the list query string")
.ok_or(VpodError::PlaylistIdNotFound)?
.to_owned();
gen_rss(&pl_id, FeedType::Playlist).await
Ok(gen_rss(&pl_id, FeedType::Playlist, _request).await?)
}
_ => {
let channel_id = utils::get_channel_id(&yt_url)
.await
.expect("could not get channel_id");

gen_rss(&channel_id, FeedType::Channel).await
.map_err(|_| VpodError::ChannelNotFound)?;
Ok(gen_rss(&channel_id, FeedType::Channel, _request).await?)
}
}
}

async fn gen_rss(feed_id: &str, feed_type: FeedType) -> impl IntoResponse {
#[tracing::instrument(fields(feed_id=feed_id, feed_type=format!("{feed_type}")))]
async fn gen_rss(
feed_id: &str,
feed_type: FeedType,
request: axum::extract::Request,
) -> Result<impl IntoResponse> {
let path = format!("{feed_id}/{feed_type}-{feed_id}.xml");
let path = std::path::Path::new(&path);

let req = hyper::Request::builder()
.body(axum::body::Body::empty())
.unwrap();

let service =
get_service(tower_http::services::ServeFile::new(&path)).handle_error(crate::handle_error);
let service = tower_http::services::ServeFile::new(&path);

let feed = match &path.exists() {
true => {
Expand Down Expand Up @@ -90,9 +92,9 @@ async fn gen_rss(feed_id: &str, feed_type: FeedType) -> impl IntoResponse {
std::fs::File::create(&path).unwrap_or_else(|_| panic!("could not create {feed_id}.xml"));
channel.write_to(file).unwrap();

let result = service.oneshot(req).await;
let result = service.oneshot(request).await;

result
Ok(result)
}

#[derive(Deserialize)]
Expand Down Expand Up @@ -148,6 +150,7 @@ struct Feed {
episodes: Option<Vec<Episode>>,
}

#[tracing::instrument]
async fn add_episode_length(eps: Vec<Episode>) -> Vec<Episode> {
let https = hyper_tls::HttpsConnector::new();
let client = hyper::Client::builder().build::<_, hyper::Body>(https);
Expand All @@ -167,7 +170,8 @@ async fn add_episode_length(eps: Vec<Episode>) -> Vec<Episode> {
body::to_bytes(res).await.expect("err reading body!")
})
.then(|body| async {
tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
// TODO: I don't know why this is here?
// tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
let body = String::from_utf8(body.into_iter().collect()).unwrap();
let length = body.find("lengthSeconds");
match length {
Expand All @@ -190,6 +194,7 @@ async fn add_episode_length(eps: Vec<Episode>) -> Vec<Episode> {
.collect()
}

#[tracing::instrument]
async fn update_feed(new_feed: Feed, old_feed: Feed) -> Feed {
let old_eps = old_feed.episodes.unwrap();
let mut new_eps = new_feed.episodes.as_ref().unwrap().to_owned();
Expand Down Expand Up @@ -225,6 +230,7 @@ async fn update_feed(new_feed: Feed, old_feed: Feed) -> Feed {
}
}

#[derive(Debug)]
enum FeedType {
Channel,
Playlist,
Expand Down
Loading

0 comments on commit fdc0998

Please sign in to comment.