From 83738a3a564374e88ff8967534dabdfae4c4b184 Mon Sep 17 00:00:00 2001 From: emeroad Date: Thu, 13 Oct 2022 19:26:08 +0900 Subject: [PATCH] [#9267] Add Clock with millisecond precision --- .../pinpoint/common/profiler/clock/Clock.java | 49 +++++++++++++++++++ .../common/profiler/clock/TickClock.java | 30 ++++++++++++ .../bo/serializer/stat/AgentStatUtils.java | 6 ++- .../flowcontrol/DefaultIdleTimeout.java | 2 +- .../flowcontrol/DefaultIdleTimeoutTest.java | 6 +-- .../storage/AsyncQueueingUriStatStorage.java | 17 +++---- 6 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/clock/Clock.java create mode 100644 commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/clock/TickClock.java diff --git a/commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/clock/Clock.java b/commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/clock/Clock.java new file mode 100644 index 0000000000000..dc1d8c7914e61 --- /dev/null +++ b/commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/clock/Clock.java @@ -0,0 +1,49 @@ +package com.navercorp.pinpoint.common.profiler.clock; + +/** + * millisecond precision clock + * @author Woonduk Kang(emeroad) + */ +public interface Clock { + + long millis(); + + static Clock systemUTC() { + return SystemClock.UTC; + } + + static Clock fixed(long timestamp) { + return new FixedClock(timestamp); + } + + static Clock tick(long tick) { + return new TickClock(Clock.systemUTC(), tick); + } + + static Clock tick(Clock clock, long tick) { + return new TickClock(clock, tick); + } + + class SystemClock implements Clock { + static final SystemClock UTC = new SystemClock(); + + @Override + public long millis() { + return System.currentTimeMillis(); + } + } + + class FixedClock implements Clock { + private final long timestamp; + + public FixedClock(long timestamp) { + this.timestamp = timestamp; + } + + @Override + public long millis() { + return timestamp; + } + } + +} diff --git a/commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/clock/TickClock.java b/commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/clock/TickClock.java new file mode 100644 index 0000000000000..06029a2a972b4 --- /dev/null +++ b/commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/clock/TickClock.java @@ -0,0 +1,30 @@ +package com.navercorp.pinpoint.common.profiler.clock; + +import java.util.Objects; + +/** + * @author Woonduk Kang(emeroad) + */ +public class TickClock implements Clock { + private final Clock baseClock; + private final long tick; + + public TickClock(Clock baseClock, long tick) { + this.baseClock = Objects.requireNonNull(baseClock, "baseClock"); + if (tick < 0) { + throw new IllegalArgumentException("negative tick"); + } + this.tick = tick; + } + + public long millis() { + long millis = baseClock.millis(); + return tick(millis); + } + + public long tick(long millis) { + return millis - (millis % tick); + } + +} + diff --git a/commons-server/src/main/java/com/navercorp/pinpoint/common/server/bo/serializer/stat/AgentStatUtils.java b/commons-server/src/main/java/com/navercorp/pinpoint/common/server/bo/serializer/stat/AgentStatUtils.java index d6db743848240..22022fe6500fd 100644 --- a/commons-server/src/main/java/com/navercorp/pinpoint/common/server/bo/serializer/stat/AgentStatUtils.java +++ b/commons-server/src/main/java/com/navercorp/pinpoint/common/server/bo/serializer/stat/AgentStatUtils.java @@ -16,6 +16,8 @@ package com.navercorp.pinpoint.common.server.bo.serializer.stat; +import com.navercorp.pinpoint.common.profiler.clock.Clock; +import com.navercorp.pinpoint.common.profiler.clock.TickClock; import org.apache.commons.math3.util.Precision; import static com.navercorp.pinpoint.common.hbase.HbaseColumnFamily.AGENT_STAT_STATISTICS; @@ -28,6 +30,8 @@ public class AgentStatUtils { public static final int NUM_DECIMALS = 4; public static final long CONVERT_VALUE = (long) Math.pow(10, NUM_DECIMALS); + private static final TickClock CLOCK = new TickClock(Clock.systemUTC(), AGENT_STAT_STATISTICS.TIMESPAN_MS); + public static long convertDoubleToLong(double value) { long convertedValue = (long) (value * CONVERT_VALUE); return convertedValue; @@ -49,6 +53,6 @@ public static double calculateRate(long count, long timeMs, int numDecimals, dou } public static long getBaseTimestamp(long timestamp) { - return timestamp - (timestamp % AGENT_STAT_STATISTICS.TIMESPAN_MS); + return CLOCK.tick(timestamp); } } diff --git a/grpc/src/main/java/com/navercorp/pinpoint/grpc/server/flowcontrol/DefaultIdleTimeout.java b/grpc/src/main/java/com/navercorp/pinpoint/grpc/server/flowcontrol/DefaultIdleTimeout.java index 18d04d366d19d..fd00760a82199 100644 --- a/grpc/src/main/java/com/navercorp/pinpoint/grpc/server/flowcontrol/DefaultIdleTimeout.java +++ b/grpc/src/main/java/com/navercorp/pinpoint/grpc/server/flowcontrol/DefaultIdleTimeout.java @@ -1,8 +1,8 @@ package com.navercorp.pinpoint.grpc.server.flowcontrol; +import com.navercorp.pinpoint.common.profiler.clock.Clock; import com.navercorp.pinpoint.common.util.Assert; -import java.time.Clock; import java.util.Objects; public class DefaultIdleTimeout implements IdleTimeout { diff --git a/grpc/src/test/java/com/navercorp/pinpoint/grpc/server/flowcontrol/DefaultIdleTimeoutTest.java b/grpc/src/test/java/com/navercorp/pinpoint/grpc/server/flowcontrol/DefaultIdleTimeoutTest.java index 64f68a78a98f2..11b51722455a0 100644 --- a/grpc/src/test/java/com/navercorp/pinpoint/grpc/server/flowcontrol/DefaultIdleTimeoutTest.java +++ b/grpc/src/test/java/com/navercorp/pinpoint/grpc/server/flowcontrol/DefaultIdleTimeoutTest.java @@ -1,10 +1,9 @@ package com.navercorp.pinpoint.grpc.server.flowcontrol; +import com.navercorp.pinpoint.common.profiler.clock.Clock; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.time.Clock; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -26,8 +25,7 @@ public void isExpired_init_state() { @Test public void isExpired_expired() { - Clock clock = mock(Clock.class); - when(clock.millis()).thenReturn(1L); + Clock clock = Clock.fixed(1L); IdleTimeout idleTimeout = new DefaultIdleTimeout(0, clock); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/storage/AsyncQueueingUriStatStorage.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/storage/AsyncQueueingUriStatStorage.java index f08604d7b3278..4a92189502b46 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/storage/AsyncQueueingUriStatStorage.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/storage/AsyncQueueingUriStatStorage.java @@ -18,6 +18,7 @@ import java.util.Objects; +import com.navercorp.pinpoint.common.profiler.clock.Clock; import com.navercorp.pinpoint.common.util.Assert; import com.navercorp.pinpoint.common.util.CollectionUtils; import com.navercorp.pinpoint.profiler.monitor.metric.uri.AgentUriStatData; @@ -82,9 +83,10 @@ private static class ExecutorListener implements AsyncQueueingExecutorListener completedUriStatDataList; + private AgentUriStatData currentAgentUriStatData; public ExecutorListener(int uriStatDataLimitSize) { @@ -96,14 +98,14 @@ public ExecutorListener(int uriStatDataLimitSize, int collectInterval) { this.uriStatDataLimitSize = uriStatDataLimitSize; Assert.isTrue(collectInterval > 0, "collectInterval must be ' > 0'"); - this.collectInterval = collectInterval; + this.clock = Clock.tick(collectInterval); this.completedUriStatDataList = new LinkedList<>(); } @Override public void execute(Collection messageList) { - final long currentBaseTimestamp = getBaseTimestamp(); + final long currentBaseTimestamp = clock.millis(); checkAndFlushOldData(currentBaseTimestamp); AgentUriStatData agentUriStatData = getCurrent(currentBaseTimestamp); @@ -120,7 +122,7 @@ public void execute(Collection messageList) { @Override public void execute(UriStatInfo message) { - long currentBaseTimestamp = getBaseTimestamp(); + long currentBaseTimestamp = clock.millis(); checkAndFlushOldData(currentBaseTimestamp); AgentUriStatData agentUriStatData = getCurrent(currentBaseTimestamp); @@ -128,15 +130,10 @@ public void execute(UriStatInfo message) { } public void executePollTimeout() { - long currentBaseTimestamp = getBaseTimestamp(); + long currentBaseTimestamp = clock.millis(); checkAndFlushOldData(currentBaseTimestamp); } - private long getBaseTimestamp() { - long currentTimeMillis = System.currentTimeMillis(); - long timestamp = currentTimeMillis - (currentTimeMillis % collectInterval); - return timestamp; - } private boolean checkAndFlushOldData(long currentBaseTimestamp) { if (currentAgentUriStatData == null) {