That does sound like a good idea.  We can probably replace all of the calls
to APR for the time with their C++ standard equivalents as well to allow
for easy mocking.

-Robert Middleton

On Mon, Jul 5, 2021 at 3:26 AM Volkan Yazıcı <volkan.yaz...@gmail.com>
wrote:

> I totally agree with Matt on this. Once the code starts changing behaviour
> via the system time, it becomes practically impossible to decently test it.
> If you can mock the clock, testing becomes tractable. To the best of my
> knowledge, that is what we mostly do in Log4j too.
>
> On Sun, Jul 4, 2021 at 8:37 PM Matt Sicker <boa...@gmail.com> wrote:
>
> > When testing the passage of time, you can always try mocking the clock
> > itself to simulate things like that. In some cases, use of count down
> > latches or cyclic barriers can coordinate the various async actions
> rather
> > than relying on clocks. Once you start testing and modeling these things
> > like that, I think the scheduling bugs and any other weird interactions
> > will become far easier to discover and fix.
> >
> > On Thu, Jul 1, 2021 at 19:09 Robert Middleton <osfan6...@gmail.com>
> wrote:
> >
> > > Firing events at a certain rate.  The test configures the rolling file
> > > appender to roll over once a second.
> > >
> > > Specifically, the test ensures that the following works:
> > > * Write log line 1 <-- second 1
> > > * Write log line 2 <-- second 1
> > > * Write log line 3, causes rollover <-- second 2
> > > * Write log line 4 <-- second 2
> > > * Write log line 5, causes rollover  <-- second 3
> > > ....etc...
> > >
> > > Under certain conditions(mostly when running under Github actions on
> > > OSX) this can result in the file having 1 or 3 log messages in it,
> > > instead of exactly 2.  So it almost certainly has to do with the
> > > particular scheduling and sleep interaction.
> > >
> > > I'm thinking that the best thing to do is to change up the algorithm
> > > slightly so that it does
> > > * write log line 1
> > > * write log line 2
> > > * wait until the next second
> > > * write log line 3, causing rollover
> > > ....etc...
> > >
> > > -Robert Middleton
> > >
> > > On Thu, Jul 1, 2021 at 3:22 PM Volkan Yazıcı <volkan.yaz...@gmail.com>
> > > wrote:
> > > >
> > > > What do you exactly mean by "ensuring"? Checking if the event rate
> was
> > > > correct? Or rather firing events at a certain rate? For the former,
> you
> > > can
> > > > collect all the events, split the collection into buckets of seconds,
> > and
> > > > count the number of events in each bucket. For the latter, did you
> try
> > > busy
> > > > spinning rather than apr_sleep to avoid context switch costs? If I
> > would
> > > > want to implement this in Java, I would use a stock rate limiter, and
> > > shoot
> > > > using that. That is,
> > > >
> > > > RateLimiter rateLimiter = RateLimiter.ofPermitsPerSecond(10);
> > > > for (int i = 0; i < l; i++) {
> > > >     rateLimiter.acquire(); // This will block if the permit is not
> > > > available.
> > > >     // You might want to sleep here some random amount of time, just
> to
> > > > fluctuate the rate over time.
> > > >     logger.debug("event {}", i);
> > > > }
> > > >
> > > > For RateLimiter, I would either use Guava or Resilience4j. I actually
> > > have a
> > > > single-class rate limiter implementation
> > > > <https://gist.github.com/vy/2f1ff259e0814c4bf32ee89f3a26dfff> that I
> > > stole
> > > > from Resilience4j:
> > > >
> > > > On Tue, Jun 29, 2021 at 3:17 AM Robert Middleton <
> > rmiddle...@apache.org>
> > > > wrote:
> > > >
> > > > > Is there a reliable way to ensure that X number of log messages get
> > > > > written out per second?  I ask because one of the problems that we
> > > > > have with log4cxx is that the TimeBasedRollingTest randomly
> fails(on
> > > > > OSX).  I've narrowed it down to the following function:
> > > > >
> > > > > void logMsgAndSleep(Pool & pool,
> > > > > size_t howOften,
> > > > > std::string srcFunc,
> > > > > size_t srcLine,
> > > > > size_t startWith = 0,
> > > > > float waitFactor = 0.5)
> > > > > {
> > > > >
> > > > > for (size_t i = startWith; i < startWith + howOften; ++i)
> > > > > {
> > > > > std::string message("Hello---");
> > > > > message.append(pool.itoa(i));
> > > > >
> > > > > LOG4CXX_DEBUG(logger, message);
> > > > > apr_sleep(APR_USEC_PER_SEC * waitFactor);
> > > > > }
> > > > >
> > > > > }
> > > > >
> > > > > The issue seems to be that due to various scheduling whims, we may
> > not
> > > > > always get the correct number of messages printed out per second,
> so
> > > > > the test will fail.  Is there a better way to do this, perhaps
> > > > > something in log4j?
> > > > >
> > > > > -Robert Middleton
> > > > >
> > >
> >
>

Reply via email to