diff --git a/src/main/java/org/opentripplanner/framework/logging/Throttle.java b/src/main/java/org/opentripplanner/framework/logging/Throttle.java index 47417aa974a..4201570696c 100644 --- a/src/main/java/org/opentripplanner/framework/logging/Throttle.java +++ b/src/main/java/org/opentripplanner/framework/logging/Throttle.java @@ -1,5 +1,6 @@ package org.opentripplanner.framework.logging; +import java.time.Duration; import org.opentripplanner.framework.time.TimeUtils; /** @@ -26,13 +27,18 @@ public class Throttle { private long timeout = Long.MIN_VALUE; private final String setupInfo; - Throttle(int quietPeriodMilliseconds) { - this.quietPeriodMilliseconds = quietPeriodMilliseconds; + Throttle(Duration quietPeriod) { + this.quietPeriodMilliseconds = (int)quietPeriod.toMillis(); this.setupInfo = "(throttle " + TimeUtils.msToString(quietPeriodMilliseconds) + " interval)"; } + public static Throttle ofOneSecond() { - return new Throttle(1000); + return new Throttle(Duration.ofSeconds(1)); + } + + public static Throttle ofTenMinutes() { + return new Throttle(Duration.ofMinutes(10)); } public String setupInfo() { diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/grouppriority/TransitGroupPriorityReport.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/grouppriority/TransitGroupPriorityReport.java new file mode 100644 index 00000000000..fb9dae697b7 --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/grouppriority/TransitGroupPriorityReport.java @@ -0,0 +1,76 @@ +package org.opentripplanner.routing.algorithm.raptoradapter.transit.grouppriority; + +import java.util.List; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.stream.Collectors; +import org.opentripplanner.routing.algorithm.raptoradapter.transit.request.TripPatternForDates; + +public class TransitGroupPriorityReport { + + public static String buildReport(List patterns) { + var map = new TreeMap(); + for (var it : patterns) { + var pattern = it.getTripPattern().getPattern(); + var de = map.computeIfAbsent( + it.priorityGroupId(), + i -> new DebugEntity(it.priorityGroupId()) + ); + de.add( + it.route().getAgency().getId().toString(), + pattern.getMode().name(), + pattern.getNetexSubmode().name() + ); + } + return ( + "TRANSIT GROUPS PRIORITY" + + map.values().stream().map(DebugEntity::toString).sorted().collect(Collectors.joining("")) + ); + } + + private static class DebugEntity { + + private final int groupId; + private final TreeMap agencies = new TreeMap<>(); + + public DebugEntity(int groupId) { + this.groupId = groupId; + } + + void add(String agency, String mode, String submode) { + agencies.computeIfAbsent(agency, AgencyEntry::new).add(mode, submode); + } + + @Override + public String toString() { + var buf = new StringBuilder("\n %#010x".formatted(groupId)); + for (var it : agencies.values()) { + buf.append("\n ").append(it.toString()); + } + return buf.toString(); + } + } + + private record AgencyEntry(String agency, TreeMap> modes) { + private AgencyEntry(String agency) { + this(agency, new TreeMap<>()); + } + + void add(String mode, String submode) { + modes.computeIfAbsent(mode, m -> new TreeSet<>()).add(submode); + } + + @Override + public String toString() { + var buf = new StringBuilder(); + for (var it : modes.entrySet()) { + buf.append(", "); + buf.append(it.getKey()); + if (!it.getValue().isEmpty()) { + buf.append(" (").append(String.join(", ", it.getValue())).append(")"); + } + } + return agency + " ~ " + buf.substring(2); + } + } +} diff --git a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitData.java b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitData.java index 0d6b4497c1b..97bc8c3ae8e 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitData.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/raptoradapter/transit/request/RaptorRoutingRequestTransitData.java @@ -8,6 +8,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opentripplanner.framework.application.OTPFeature; +import org.opentripplanner.framework.logging.Throttle; import org.opentripplanner.framework.time.ServiceDateUtils; import org.opentripplanner.model.transfer.TransferService; import org.opentripplanner.raptor.api.model.RaptorConstrainedTransfer; @@ -30,9 +31,12 @@ import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.CostCalculatorFactory; import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.DefaultCostCalculator; import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.FactorStrategy; +import org.opentripplanner.routing.algorithm.raptoradapter.transit.grouppriority.TransitGroupPriorityReport; import org.opentripplanner.routing.algorithm.raptoradapter.transit.mappers.GeneralizedCostParametersMapper; import org.opentripplanner.routing.api.request.RouteRequest; import org.opentripplanner.transit.model.network.RoutingTripPattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This is the data provider for the Range Raptor search engine. It uses data from the TransitLayer, @@ -41,6 +45,9 @@ */ public class RaptorRoutingRequestTransitData implements RaptorTransitDataProvider { + private static final Logger LOG = LoggerFactory.getLogger(RaptorRoutingRequestTransitData.class); + private static final Throttle THROTTLE_TRANSIT_GROUP_PRIORITY = Throttle.ofTenMinutes(); + private final TransitLayer transitLayer; private final TransferService transferService; @@ -85,7 +92,7 @@ public RaptorRoutingRequestTransitData( this.transitSearchTimeZero = transitSearchTimeZero; // Delegate to the creator to construct the needed data structures. The code is messy so - // it is nice to NOT have it in the class. It isolate this code to only be available at + // it is nice to NOT have it in the class. It isolates this code to only be available at // the time of construction var transitDataCreator = new RaptorRoutingRequestTransitDataCreator( transitLayer, @@ -97,6 +104,8 @@ public RaptorRoutingRequestTransitData( filter, createTransitGroupPriorityConfigurator(request) ); + logTransitGroups(request, tripPatterns); + this.patternIndex = transitDataCreator.createPatternIndex(tripPatterns); this.activeTripPatternsPerStop = transitDataCreator.createTripPatternsPerStop(tripPatterns); this.transferIndex = transitLayer.getRaptorTransfersForRequest(request); @@ -257,6 +266,16 @@ private PriorityGroupConfigurator createTransitGroupPriorityConfigurator(RouteRe ); } + private void logTransitGroups(RouteRequest request, List patterns) { + if ( + request.preferences().transit().relaxTransitGroupPriority().isNormal() || + THROTTLE_TRANSIT_GROUP_PRIORITY.throttle() + ) { + return; + } + LOG.info(TransitGroupPriorityReport.buildReport(patterns)); + } + /*-- HACK SØRLANDSBANEN :: BEGIN --*/ private RaptorRoutingRequestTransitData( diff --git a/src/test/java/org/opentripplanner/framework/logging/ThrottleTest.java b/src/test/java/org/opentripplanner/framework/logging/ThrottleTest.java index 91f1667486d..c9155992daa 100644 --- a/src/test/java/org/opentripplanner/framework/logging/ThrottleTest.java +++ b/src/test/java/org/opentripplanner/framework/logging/ThrottleTest.java @@ -1,5 +1,6 @@ package org.opentripplanner.framework.logging; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -36,8 +37,8 @@ void smokeTest() { @Test @Disabled("Run this test manually") void manualTest() { - double quietPeriodMs = 50.0; - var subject = new Throttle((int) quietPeriodMs); + var quietPeriod = Duration.ofMillis(50); + var subject = new Throttle(quietPeriod); List events = createIntegerSequence(20_000_000); long start = System.currentTimeMillis();