Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ serde_json = "1.0"
sysinfo = "0.37"
ctrlc = "3"
chrono = "0.4"
prometheus-client = "0.24.1"

[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
portable-atomic = "1.4"
Expand Down
1 change: 1 addition & 0 deletions completions/_dust
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ m\:"last modified time"))' \
'(-D --only-dir)--only-file[Only files will be displayed. (Finds your largest files)]' \
'-j[Output the directory tree as json to the current directory]' \
'--output-json[Output the directory tree as json to the current directory]' \
'--output-metrics[Output the directory tree as OpenMetrics / prometheus metrics]' \
'-h[Print help (see more with '\''--help'\'')]' \
'--help[Print help (see more with '\''--help'\'')]' \
'-V[Print version]' \
Expand Down
1 change: 1 addition & 0 deletions completions/_dust.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Register-ArgumentCompleter -Native -CommandName 'dust' -ScriptBlock {
[CompletionResult]::new('--only-file', '--only-file', [CompletionResultType]::ParameterName, 'Only files will be displayed. (Finds your largest files)')
[CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'Output the directory tree as json to the current directory')
[CompletionResult]::new('--output-json', '--output-json', [CompletionResultType]::ParameterName, 'Output the directory tree as json to the current directory')
[CompletionResult]::new('--output-metrics', '--output-metrics', [CompletionResultType]::ParameterName, 'Output the directory tree as OpenMetrics / prometheus metrics')
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
[CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
Expand Down
2 changes: 1 addition & 1 deletion completions/dust.bash
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ _dust() {

case "${cmd}" in
dust)
opts="-d -T -n -p -X -I -L -x -s -r -c -C -b -B -z -R -f -i -v -e -t -w -P -D -F -o -S -j -M -A -y -m -h -V --depth --threads --config --number-of-lines --full-paths --ignore-directory --ignore-all-in-file --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --force-colors --no-percent-bars --bars-on-right --min-size --screen-reader --skip-total --filecount --ignore-hidden --invert-filter --filter --file-types --terminal-width --no-progress --print-errors --only-dir --only-file --output-format --stack-size --output-json --mtime --atime --ctime --files0-from --files-from --collapse --filetime --help --version [PATH]..."
opts="-d -T -n -p -X -I -L -x -s -r -c -C -b -B -z -R -f -i -v -e -t -w -P -D -F -o -S -j -M -A -y -m -h -V --depth --threads --config --number-of-lines --full-paths --ignore-directory --ignore-all-in-file --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --force-colors --no-percent-bars --bars-on-right --min-size --screen-reader --skip-total --filecount --ignore-hidden --invert-filter --filter --file-types --terminal-width --no-progress --print-errors --only-dir --only-file --output-format --stack-size --output-json --output-metrics --mtime --atime --ctime --files0-from --files-from --collapse --filetime --help --version [PATH]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down
1 change: 1 addition & 0 deletions completions/dust.elv
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ set edit:completion:arg-completer[dust] = {|@words|
cand --only-file 'Only files will be displayed. (Finds your largest files)'
cand -j 'Output the directory tree as json to the current directory'
cand --output-json 'Output the directory tree as json to the current directory'
cand --output-metrics 'Output the directory tree as OpenMetrics / prometheus metrics'
cand -h 'Print help (see more with ''--help'')'
cand --help 'Print help (see more with ''--help'')'
cand -V 'Print version'
Expand Down
1 change: 1 addition & 0 deletions completions/dust.fish
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,6 @@ complete -c dust -l print-errors -d 'Print path with errors'
complete -c dust -s D -l only-dir -d 'Only directories will be displayed'
complete -c dust -s F -l only-file -d 'Only files will be displayed. (Finds your largest files)'
complete -c dust -s j -l output-json -d 'Output the directory tree as json to the current directory'
complete -c dust -l output-metrics -d 'Output the directory tree as OpenMetrics / prometheus metrics'
complete -c dust -s h -l help -d 'Print help (see more with \'--help\')'
complete -c dust -s V -l version -d 'Print version'
5 changes: 4 additions & 1 deletion man-page/dust.1
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
.SH NAME
Dust \- Like du but more intuitive
.SH SYNOPSIS
\fBdust\fR [\fB\-d\fR|\fB\-\-depth\fR] [\fB\-T\fR|\fB\-\-threads\fR] [\fB\-\-config\fR] [\fB\-n\fR|\fB\-\-number\-of\-lines\fR] [\fB\-p\fR|\fB\-\-full\-paths\fR] [\fB\-X\fR|\fB\-\-ignore\-directory\fR] [\fB\-I\fR|\fB\-\-ignore\-all\-in\-file\fR] [\fB\-L\fR|\fB\-\-dereference\-links\fR] [\fB\-x\fR|\fB\-\-limit\-filesystem\fR] [\fB\-s\fR|\fB\-\-apparent\-size\fR] [\fB\-r\fR|\fB\-\-reverse\fR] [\fB\-c\fR|\fB\-\-no\-colors\fR] [\fB\-C\fR|\fB\-\-force\-colors\fR] [\fB\-b\fR|\fB\-\-no\-percent\-bars\fR] [\fB\-B\fR|\fB\-\-bars\-on\-right\fR] [\fB\-z\fR|\fB\-\-min\-size\fR] [\fB\-R\fR|\fB\-\-screen\-reader\fR] [\fB\-\-skip\-total\fR] [\fB\-f\fR|\fB\-\-filecount\fR] [\fB\-i\fR|\fB\-\-ignore\-hidden\fR] [\fB\-v\fR|\fB\-\-invert\-filter\fR] [\fB\-e\fR|\fB\-\-filter\fR] [\fB\-t\fR|\fB\-\-file\-types\fR] [\fB\-w\fR|\fB\-\-terminal\-width\fR] [\fB\-P\fR|\fB\-\-no\-progress\fR] [\fB\-\-print\-errors\fR] [\fB\-D\fR|\fB\-\-only\-dir\fR] [\fB\-F\fR|\fB\-\-only\-file\fR] [\fB\-o\fR|\fB\-\-output\-format\fR] [\fB\-S\fR|\fB\-\-stack\-size\fR] [\fB\-j\fR|\fB\-\-output\-json\fR] [\fB\-M\fR|\fB\-\-mtime\fR] [\fB\-A\fR|\fB\-\-atime\fR] [\fB\-y\fR|\fB\-\-ctime\fR] [\fB\-\-files0\-from\fR] [\fB\-\-files\-from\fR] [\fB\-\-collapse\fR] [\fB\-m\fR|\fB\-\-filetime\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIPATH\fR]
\fBdust\fR [\fB\-d\fR|\fB\-\-depth\fR] [\fB\-T\fR|\fB\-\-threads\fR] [\fB\-\-config\fR] [\fB\-n\fR|\fB\-\-number\-of\-lines\fR] [\fB\-p\fR|\fB\-\-full\-paths\fR] [\fB\-X\fR|\fB\-\-ignore\-directory\fR] [\fB\-I\fR|\fB\-\-ignore\-all\-in\-file\fR] [\fB\-L\fR|\fB\-\-dereference\-links\fR] [\fB\-x\fR|\fB\-\-limit\-filesystem\fR] [\fB\-s\fR|\fB\-\-apparent\-size\fR] [\fB\-r\fR|\fB\-\-reverse\fR] [\fB\-c\fR|\fB\-\-no\-colors\fR] [\fB\-C\fR|\fB\-\-force\-colors\fR] [\fB\-b\fR|\fB\-\-no\-percent\-bars\fR] [\fB\-B\fR|\fB\-\-bars\-on\-right\fR] [\fB\-z\fR|\fB\-\-min\-size\fR] [\fB\-R\fR|\fB\-\-screen\-reader\fR] [\fB\-\-skip\-total\fR] [\fB\-f\fR|\fB\-\-filecount\fR] [\fB\-i\fR|\fB\-\-ignore\-hidden\fR] [\fB\-v\fR|\fB\-\-invert\-filter\fR] [\fB\-e\fR|\fB\-\-filter\fR] [\fB\-t\fR|\fB\-\-file\-types\fR] [\fB\-w\fR|\fB\-\-terminal\-width\fR] [\fB\-P\fR|\fB\-\-no\-progress\fR] [\fB\-\-print\-errors\fR] [\fB\-D\fR|\fB\-\-only\-dir\fR] [\fB\-F\fR|\fB\-\-only\-file\fR] [\fB\-o\fR|\fB\-\-output\-format\fR] [\fB\-S\fR|\fB\-\-stack\-size\fR] [\fB\-j\fR|\fB\-\-output\-json\fR] [\fB\-\-output\-metrics\fR] [\fB\-M\fR|\fB\-\-mtime\fR] [\fB\-A\fR|\fB\-\-atime\fR] [\fB\-y\fR|\fB\-\-ctime\fR] [\fB\-\-files0\-from\fR] [\fB\-\-files\-from\fR] [\fB\-\-collapse\fR] [\fB\-m\fR|\fB\-\-filetime\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIPATH\fR]
.SH DESCRIPTION
Like du but more intuitive
.SH OPTIONS
Expand Down Expand Up @@ -128,6 +128,9 @@ Specify memory to use as stack size \- use if you see: \*(Aqfatal runtime error:
\fB\-j\fR, \fB\-\-output\-json\fR
Output the directory tree as json to the current directory
.TP
\fB\-\-output\-metrics\fR
Output the directory tree as OpenMetrics / prometheus metrics
.TP
\fB\-M\fR, \fB\-\-mtime\fR \fI<MTIME>\fR
+/\-n matches files modified more/less than n days ago , and n matches files modified exactly n days ago, days are rounded down.That is +n => (−∞, curr−(n+1)), n => [curr−(n+1), curr−n), and \-n => (𝑐𝑢𝑟𝑟−𝑛, +∞)
.TP
Expand Down
4 changes: 4 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ pub struct Cli {
#[arg(short('j'), long)]
pub output_json: bool,

/// Output the directory tree as OpenMetrics / prometheus metrics
#[arg(long)]
pub output_metrics: bool,

/// +/-n matches files modified more/less than n days ago , and n matches
/// files modified exactly n days ago, days are rounded down.That is +n =>
/// (−∞, curr−(n+1)), n => [curr−(n+1), curr−n), and -n => (𝑐𝑢𝑟𝑟−𝑛, +∞)
Expand Down
4 changes: 4 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub struct Config {
pub stack_size: Option<usize>,
pub threads: Option<usize>,
pub output_json: Option<bool>,
pub output_metrics: Option<bool>,
pub print_errors: Option<bool>,
pub files0_from: Option<String>,
pub number_of_lines: Option<usize>,
Expand Down Expand Up @@ -157,6 +158,9 @@ impl Config {
pub fn get_output_json(&self, options: &Cli) -> bool {
Some(true) == self.output_json || options.output_json
}
pub fn get_output_metrics(&self, options: &Cli) -> bool {
Some(true) == self.output_metrics || options.output_metrics
}

pub fn get_number_of_lines(&self, options: &Cli) -> Option<usize> {
let from_cmd_line = options.number_of_lines;
Expand Down
89 changes: 88 additions & 1 deletion src/display_node.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
use std::borrow::Cow;
use std::cell::RefCell;
use std::path::PathBuf;

use prometheus_client::collector::Collector;
use prometheus_client::encoding::{EncodeMetric as _, MetricEncoder};
use prometheus_client::metrics::MetricType;
use prometheus_client::metrics::gauge::ConstGauge;
use prometheus_client::registry::{Registry, Unit};
use serde::ser::SerializeStruct;
use serde::{Serialize, Serializer};

use crate::display::human_readable_number;
use crate::display::{get_printable_name, human_readable_number};

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct DisplayNode {
Expand All @@ -28,6 +34,87 @@ impl DisplayNode {
};
out
}

pub fn into_metrics(
self,
cli_params: Option<Vec<String>>,
by_filecount: bool,
skip_total: bool,
) -> String {
#[derive(Debug)]
struct DustExporter {
root_node: DisplayNode,
by_filecount: bool,
skip_total: bool,
}
impl Collector for DustExporter {
fn encode(
&self,
mut enc: prometheus_client::encoding::DescriptorEncoder,
) -> Result<(), std::fmt::Error> {
let mut metric_encoder = match self.by_filecount {
false => enc.encode_descriptor(
"dust_file_size",
"Total size of files in this folder / size of this file.",
Some(&Unit::Bytes),
MetricType::Gauge,
)?,
true => enc.encode_descriptor(
"dust_file_count",
"Total number of files in this folder / '1' for files.",
None,
MetricType::Gauge,
)?,
};
self.root_node
.encode_metrics(&mut metric_encoder, self.skip_total)?;
Ok(())
}
}

let global_labels = cli_params_to_label(cli_params.as_ref());

let mut registry = Registry::with_labels(global_labels.into_iter());
registry.register_collector(Box::new(DustExporter {
root_node: self,
by_filecount,
skip_total,
}));

let mut out = String::new();
prometheus_client::encoding::text::encode(&mut out, &registry)
.expect("String's Write impl never fails");
out
}
fn encode_metrics(
&self,
metric_encoder: &mut MetricEncoder,
skip_self: bool,
) -> Result<(), std::fmt::Error> {
if !skip_self {
let g = ConstGauge::new(self.size);
let labels = [("path", get_printable_name(&self.name, false))];
let labeled = metric_encoder.encode_family(&labels)?;
g.encode(labeled)?;
}
for child in self.children.iter() {
child.encode_metrics(metric_encoder, false)?;
}
Ok(())
}
}

fn cli_params_to_label(
cli_params: Option<&Vec<String>>,
) -> Option<(Cow<'static, str>, Cow<'static, str>)> {
let params = cli_params?;

let value = params.iter().fold(None, |acc, param| match acc {
Some(acc) => Some(acc + " " + param.as_str()),
None => Some(param.to_string()),
})?;

Some((Cow::Borrowed("paths"), Cow::Owned(value)))
}

// Only used for -j 'json' flag combined with -o 'output_type' flag
Expand Down
9 changes: 9 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,15 @@ fn print_output(
}
});
println!("{}", serde_json::to_string(&tree).unwrap());
} else if config.get_output_metrics(&options) {
print!(
"{}",
tree.into_metrics(
options.params.clone(),
by_filecount,
config.get_skip_total(&options)
)
);
} else {
let idd = InitialDisplayData {
short_paths: !config.get_full_paths(&options),
Expand Down