@Override
    public void onExit(Context context, ResourceWrapper rw, int acquireCount, Object... args) {
        Entry curEntry = context.getCurEntry();
        if (curEntry == null) {
            return;
        }
        for (MetricExtension m : MetricExtensionProvider.getMetricExtensions()) {
            if (curEntry.getBlockError() != null) {
                continue;
            }
            String resource = rw.getName();
            Throwable ex = curEntry.getError();
            long completeTime = curEntry.getCompleteTimestamp();
            if (completeTime <= 0) {
                completeTime = TimeUtil.currentTimeMillis();
            }
            long rt = completeTime - curEntry.getCreateTimestamp();

            if (m instanceof AdvancedMetricExtension) {
                // Since 1.8.0 (as a temporary workaround for compatibility)
                ((AdvancedMetricExtension) m).onComplete(rw, rt, acquireCount, args);
                if (ex != null) {
                    ((AdvancedMetricExtension) m).onError(rw, ex, acquireCount, args);
                }
            } else {
                m.addRt(resource, rt, args);
                m.addSuccess(resource, acquireCount, args);
                m.decreaseThreadNum(resource, args);
                if (null != ex) {
                    m.addException(resource, acquireCount, ex);
                }
            }
        }
    }
@Test
    public void advancedExtensionOnExit() {
        try (MockedStatic<TimeUtil> mocked = super.mockTimeUtil()) {
            FakeAdvancedMetricExtension extension = new FakeAdvancedMetricExtension();
            MetricExtensionProvider.addMetricExtension(extension);

            MetricExitCallback exitCallback = new MetricExitCallback();
            StringResourceWrapper resourceWrapper = new StringResourceWrapper("resource", EntryType.OUT);
            int count = 2;
            Object[] args = {"args1", "args2"};
            long prevRt = 20;
            extension.rt = prevRt;
            extension.complete = 6;
            extension.concurrency = 10;
            Context context = mock(Context.class);
            Entry entry = mock(Entry.class);

            // Mock current time
            long curMillis = System.currentTimeMillis();
            setCurrentMillis(mocked, curMillis);

            int deltaMs = 100;
            when(entry.getError()).thenReturn(null);
            when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs);
            when(context.getCurEntry()).thenReturn(entry);
            exitCallback.onExit(context, resourceWrapper, count, args);
            Assert.assertEquals(prevRt + deltaMs, extension.rt);
            Assert.assertEquals(extension.complete, 6 + count);
            Assert.assertEquals(extension.concurrency, 10 - 1);
        }
    }