App-Yath-Plugin-Utilization

 view release on metacpan or  search on metacpan

lib/App/Yath/Plugin/Utilization.pm  view on Meta::CPAN


    push @{$runner->resources} => THROTTLE_CLASS
        unless grep { $_ eq THROTTLE_CLASS } @{$runner->resources};
}

sub expand_auto_resources {
    my ($util, $runner) = @_;

    my @auto;
    if ($^O eq 'linux') {
        push @auto => (CPU_CLASS, MEMORY_CLASS, UNIXLIMITS_CLASS, PIPELIMITS_CLASS);
    }
    push @auto => THROTTLE_CLASS;

    if (eval { require Filesys::Df; 1 }) {
        seed_auto_disk_mounts($util);
        push @auto => DISK_CLASS if $util->disk_mounts && @{$util->disk_mounts};
    }

    my %present = map { $_ => 1 } @{$runner->resources};
    push @{$runner->resources} => grep { !$present{$_}++ } @auto;
}

sub seed_auto_disk_mounts {
    my ($util) = @_;

    my $mounts = $util->disk_mounts // [];

    my %have;
    for my $entry (@$mounts) {
        next unless defined $entry && $entry =~ m{^(/[^:]+):};
        $have{$1} = 1;
    }

    my $utilize = $util->utilize // 75;
    my $min_pct = 100 - $utilize;
    $min_pct = 1  if $min_pct < 1;
    $min_pct = 99 if $min_pct >= 100;

    my @candidates = ('/tmp', '/var/tmp');
    push @candidates => $ENV{TMPDIR} if defined $ENV{TMPDIR} && length $ENV{TMPDIR};

    my %seen;
    for my $path (@candidates) {
        next unless defined $path && length $path;
        next if $seen{$path}++;
        next if $have{$path};
        next unless -d $path;
        next unless _is_real_mount_point($path);
        push @$mounts => "$path:${min_pct}%";
        $have{$path} = 1;
    }

    $util->field(disk_mounts => $mounts);
}

sub _is_real_mount_point {
    my ($path) = @_;
    return 0 unless -d $path;
    return 1 if $path eq '/';
    my @s_self = stat($path)      or return 0;
    my @s_par  = stat("$path/..") or return 0;
    return $s_self[0] != $s_par[0] ? 1 : 0;
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

App::Yath::Plugin::Utilization - System-utilization gating for yath test runs.

=head1 SYNOPSIS

    # Enable the plugin (either via .yath.rc, or -pUtilization on the command line):
    $ yath test -pUtilization -Z=85

    # Or set it in .yath.rc:
    [test]
    -pUtilization

    $ yath test -Z=85
    $ yath test --utilization-utilize 80 -R +Test2::Harness::Resource::Utilization::CPU

=head1 DESCRIPTION

Adds resource modules that gate when new test launches are allowed,
based on CPU usage, free memory, free disk, per-user pipe budget,
process ulimits, and a spawn-rate window. All opt-in; combine freely.

The plugin registers the C<utilization> option group with these
flags:

=over 4

=item C<--utilization-utilize PCT> (also C<-U>)

Target saturation percentage for every utilizer (default 75). Each
resource applies this to its own monitored subsystem.

=item C<-Z>, C<-Z=PCT>

One-stop shortcut. Enables the full utilizer stack (CPU+Memory+
UnixLimits+PipeLimits+Throttle, plus Disk when L<Filesys::Df> is
installed and auto-seeded mount points exist). C<-Z=85> also sets
utilize to 85.

=item C<--utilization-throttle SPEC>

Spawn-rate window: CAP, CAP/DURATION, or
CAP/BASIS[,BASIS...]/DURATION. Bases C<core> or byte size (C<100mb>).

=item C<--utilization-auto-throttle>

Activate Throttle with the sane default spec C<1/core,100mb/1s>.

=item C<--utilization-memory-min-free THR>



( run in 2.472 seconds using v1.01-cache-2.11-cpan-600a1bdf6e4 )