mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2026-07-07 11:52:45 +00:00
Rewrite the metrics system
- Remove TrackingField and replace it with a Metric abstract class. This has two concrete subclasses - Counter and Event. Events carry an additional piece of data each time it is observed, such as HTTP response size. - Computers now accept a MetricsObserver, which tracks metrics for this particular computer. This allows us to decouple Computer classes and metrics information. The concrete MetricsObserver class we use within Minecraft exposes the ServerComputer directly, so we no longer need to do the awkward mapping and lookups! - The /computercraft command can now do aggregates (count, avg, max) over all Event metrics. This removes the need for special handling of computer and server time. There's also a small number of changes in removing the coupling between Computer and some of its dependencies (ILuaMachine, MainThreadExecutor). This makes some future refactorings easier, I promise!
This commit is contained in:
@@ -9,17 +9,17 @@ import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.computer.Computer;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.tracking.ComputerTracker;
|
||||
import dan200.computercraft.core.tracking.Tracking;
|
||||
import dan200.computercraft.core.tracking.TrackingContext;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.core.metrics.Metrics;
|
||||
import dan200.computercraft.shared.command.text.TableBuilder;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.computer.metrics.basic.Aggregate;
|
||||
import dan200.computercraft.shared.computer.metrics.basic.AggregatedMetric;
|
||||
import dan200.computercraft.shared.computer.metrics.basic.BasicComputerMetricsObserver;
|
||||
import dan200.computercraft.shared.computer.metrics.basic.ComputerMetrics;
|
||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -46,7 +46,7 @@ import static dan200.computercraft.shared.command.Exceptions.*;
|
||||
import static dan200.computercraft.shared.command.arguments.ComputerArgumentType.getComputerArgument;
|
||||
import static dan200.computercraft.shared.command.arguments.ComputerArgumentType.oneComputer;
|
||||
import static dan200.computercraft.shared.command.arguments.ComputersArgumentType.*;
|
||||
import static dan200.computercraft.shared.command.arguments.TrackingFieldArgumentType.trackingField;
|
||||
import static dan200.computercraft.shared.command.arguments.TrackingFieldArgumentType.metric;
|
||||
import static dan200.computercraft.shared.command.builder.CommandBuilder.args;
|
||||
import static dan200.computercraft.shared.command.builder.CommandBuilder.command;
|
||||
import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.choice;
|
||||
@@ -248,7 +248,7 @@ public final class CommandComputerCraft
|
||||
.then( command( "start" )
|
||||
.requires( UserLevel.OWNER_OP )
|
||||
.executes( context -> {
|
||||
getTimingContext( context.getSource() ).start();
|
||||
getMetricsInstance( context.getSource() ).start();
|
||||
|
||||
String stopCommand = "/computercraft track stop";
|
||||
context.getSource().sendSuccess( translate( "commands.computercraft.track.start.stop",
|
||||
@@ -259,17 +259,17 @@ public final class CommandComputerCraft
|
||||
.then( command( "stop" )
|
||||
.requires( UserLevel.OWNER_OP )
|
||||
.executes( context -> {
|
||||
TrackingContext timings = getTimingContext( context.getSource() );
|
||||
BasicComputerMetricsObserver timings = getMetricsInstance( context.getSource() );
|
||||
if( !timings.stop() ) throw NOT_TRACKING_EXCEPTION.create();
|
||||
displayTimings( context.getSource(), timings.getImmutableTimings(), TrackingField.AVERAGE_TIME, DEFAULT_FIELDS );
|
||||
displayTimings( context.getSource(), timings.getSnapshot(), new AggregatedMetric( Metrics.COMPUTER_TASKS, Aggregate.AVG ), DEFAULT_FIELDS );
|
||||
return 1;
|
||||
} ) )
|
||||
|
||||
.then( command( "dump" )
|
||||
.requires( UserLevel.OWNER_OP )
|
||||
.argManyValue( "fields", trackingField(), DEFAULT_FIELDS )
|
||||
.argManyValue( "fields", metric(), DEFAULT_FIELDS )
|
||||
.executes( ( context, fields ) -> {
|
||||
TrackingField sort;
|
||||
AggregatedMetric sort;
|
||||
if( fields.size() == 1 && DEFAULT_FIELDS.contains( fields.get( 0 ) ) )
|
||||
{
|
||||
sort = fields.get( 0 );
|
||||
@@ -362,50 +362,48 @@ public final class CommandComputerCraft
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static TrackingContext getTimingContext( CommandSource source )
|
||||
private static BasicComputerMetricsObserver getMetricsInstance( CommandSource source )
|
||||
{
|
||||
Entity entity = source.getEntity();
|
||||
return entity instanceof PlayerEntity ? Tracking.getContext( entity.getUUID() ) : Tracking.getContext( SYSTEM_UUID );
|
||||
return ServerContext.get( source.getServer() ).metrics().getMetricsInstance( entity instanceof PlayerEntity ? entity.getUUID() : SYSTEM_UUID );
|
||||
}
|
||||
|
||||
private static final List<TrackingField> DEFAULT_FIELDS = Arrays.asList( TrackingField.TASKS, TrackingField.TOTAL_TIME, TrackingField.AVERAGE_TIME, TrackingField.MAX_TIME );
|
||||
private static final List<AggregatedMetric> DEFAULT_FIELDS = Arrays.asList(
|
||||
new AggregatedMetric( Metrics.COMPUTER_TASKS, Aggregate.COUNT ),
|
||||
new AggregatedMetric( Metrics.COMPUTER_TASKS, Aggregate.NONE ),
|
||||
new AggregatedMetric( Metrics.COMPUTER_TASKS, Aggregate.AVG ),
|
||||
new AggregatedMetric( Metrics.COMPUTER_TASKS, Aggregate.MAX )
|
||||
);
|
||||
|
||||
private static int displayTimings( CommandSource source, TrackingField sortField, List<TrackingField> fields ) throws CommandSyntaxException
|
||||
private static int displayTimings( CommandSource source, AggregatedMetric sortField, List<AggregatedMetric> fields ) throws CommandSyntaxException
|
||||
{
|
||||
return displayTimings( source, getTimingContext( source ).getTimings(), sortField, fields );
|
||||
return displayTimings( source, getMetricsInstance( source ).getTimings(), sortField, fields );
|
||||
}
|
||||
|
||||
private static int displayTimings( CommandSource source, @Nonnull List<ComputerTracker> timings, @Nonnull TrackingField sortField, @Nonnull List<TrackingField> fields ) throws CommandSyntaxException
|
||||
private static int displayTimings( CommandSource source, List<ComputerMetrics> timings, AggregatedMetric sortField, List<AggregatedMetric> fields ) throws CommandSyntaxException
|
||||
{
|
||||
if( timings.isEmpty() ) throw NO_TIMINGS_EXCEPTION.create();
|
||||
|
||||
Map<Computer, ServerComputer> lookup = new HashMap<>();
|
||||
int maxId = 0, maxInstance = 0;
|
||||
for( ServerComputer server : ServerContext.get( source.getServer() ).registry().getComputers() )
|
||||
{
|
||||
lookup.put( server.getComputer(), server );
|
||||
|
||||
if( server.getInstanceID() > maxInstance ) maxInstance = server.getInstanceID();
|
||||
if( server.getID() > maxId ) maxId = server.getID();
|
||||
}
|
||||
|
||||
timings.sort( Comparator.<ComputerTracker, Long>comparing( x -> x.get( sortField ) ).reversed() );
|
||||
timings.sort( Comparator.<ComputerMetrics, Long>comparing( x -> x.get( sortField.metric(), sortField.aggregate() ) ).reversed() );
|
||||
|
||||
ITextComponent[] headers = new ITextComponent[1 + fields.size()];
|
||||
headers[0] = translate( "commands.computercraft.track.dump.computer" );
|
||||
for( int i = 0; i < fields.size(); i++ ) headers[i + 1] = translate( fields.get( i ).translationKey() );
|
||||
for( int i = 0; i < fields.size(); i++ ) headers[i + 1] = fields.get( i ).displayName();
|
||||
TableBuilder table = new TableBuilder( TRACK_ID, headers );
|
||||
|
||||
for( ComputerTracker entry : timings )
|
||||
for( ComputerMetrics entry : timings )
|
||||
{
|
||||
Computer computer = entry.getComputer();
|
||||
ServerComputer serverComputer = computer == null ? null : lookup.get( computer );
|
||||
ServerComputer serverComputer = entry.computer();
|
||||
|
||||
ITextComponent computerComponent = linkComputer( source, serverComputer, entry.getComputerId() );
|
||||
ITextComponent computerComponent = linkComputer( source, serverComputer, entry.computerId() );
|
||||
|
||||
ITextComponent[] row = new ITextComponent[1 + fields.size()];
|
||||
row[0] = computerComponent;
|
||||
for( int i = 0; i < fields.size(); i++ ) row[i + 1] = text( entry.getFormatted( fields.get( i ) ) );
|
||||
for( int i = 0; i < fields.size(); i++ )
|
||||
{
|
||||
AggregatedMetric metric = fields.get( i );
|
||||
row[i + 1] = text( entry.getFormatted( metric.metric(), metric.aggregate() ) );
|
||||
}
|
||||
table.row( row );
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user