Add new performance logging

Add new performance logging to register events of type duration.
The proposed logging is similar to the performance logging
in OS Gerrit https://gerrit-review.googlesource.com/c/gerrit/+/225628:
a global Singleton (LoggingContext in Gerrit) is
collecting the performance logs in a thread-safe events list,
and at the end of the monitored command the list of events is
retrieved and written to a log, after which it is cleared.

What this patch does:
The main component is the Singleton (PerformanceLogContext), which
is used to collect the records (PerformanceLogRecord) in one place
(ThreadLocal eventsList) from anywhere using
PerformanceLogContext.getInstance().addEvent().

Reason why this change is needed:
The current monitoring in JGit has several issues:
1. git fetch and git push events are handled separately
(PackStatistics and ReceivedPackStatistics), with no unified way
of writing or reading the statistics.
2. PostUploadHook is only invoked on the event of sending the
pack, which means that the PackStatistics is not available for
the fetch requests that did not end with sending the pack
(negotiation requests).
3. The way the logs are created is different from the performance
log approach, so the long-running operations need to be collected
from both performance log (for JGit DFS overridden operations and
Gerrit operations) and gitlog (for JGit ones).

The proposed performance logging is going to solve the above
mentioned issues: it collects all of the performance logs in one
place, thus accounting for the commands that do not result in
sending a pack. The logs are compatible with the ones on Gerrit.
Moreover, the Singleton is accessible anywhere in the call stack,
which proved to be successful in other projects like Dapper
(https://research.google/pubs/pub36356/).

Signed-off-by: Alexa Panfil <alexapizza@google.com>
Change-Id: Iabfe667a3412d8a9db94aabb0f39b57f43469c41
This commit is contained in:
Alexa Panfil 2020-10-12 08:55:46 +00:00
parent a0d3680f49
commit a09e205176
3 changed files with 188 additions and 0 deletions

View File

@ -0,0 +1,66 @@
package org.eclipse.jgit.logging;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import java.util.List;
/**
* Tests for performance log context utilities.
*/
public class PerformanceLogContextTest {
@Test
public void testAddEvent() {
PerformanceLogRecord record = new PerformanceLogRecord("record", 0);
PerformanceLogContext.getInstance().addEvent(record);
List<PerformanceLogRecord> eventRecords = PerformanceLogContext
.getInstance().getEventRecords();
assertTrue(eventRecords.contains(record));
assertEquals(1, eventRecords.size());
}
@Test
public void testCleanEvents() {
PerformanceLogRecord record1 = new PerformanceLogRecord("record1", 0);
PerformanceLogContext.getInstance().addEvent(record1);
PerformanceLogRecord record2 = new PerformanceLogRecord("record2", 0);
PerformanceLogContext.getInstance().addEvent(record2);
PerformanceLogContext.getInstance().cleanEvents();
List<PerformanceLogRecord> eventRecords = PerformanceLogContext
.getInstance().getEventRecords();
assertEquals(0, eventRecords.size());
}
@Test
public void testAddEventsTwoThreads() {
TestRunnable thread1 = new TestRunnable("record1", 1);
TestRunnable thread2 = new TestRunnable("record2", 2);
new Thread(thread1).start();
new Thread(thread2).start();
}
private static class TestRunnable implements Runnable {
private String name;
private long durationMs;
public TestRunnable(String name, long durationMs) {
this.name = name;
this.durationMs = durationMs;
}
@Override
public void run() {
PerformanceLogRecord record = new PerformanceLogRecord(name,
durationMs);
PerformanceLogContext.getInstance().addEvent(record);
assertEquals(1, PerformanceLogContext.getInstance()
.getEventRecords().size());
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2020, Google LLC and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.logging;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Singleton that collects performance logs.
*
* @since 5.10
*/
public class PerformanceLogContext {
/** Singleton instance that stores the statistics. */
private static final PerformanceLogContext INSTANCE = new PerformanceLogContext();
/** List that stores events as performance logs. */
private final ThreadLocal<List<PerformanceLogRecord>> eventRecords = new ThreadLocal<>();
private PerformanceLogContext() {
eventRecords.set(new ArrayList<>());
}
/**
* Get the instance of the context.
*
* @return instance of performance log context.
*/
public static PerformanceLogContext getInstance() {
return INSTANCE;
}
/**
* Get the unmodifiable list of events as performance records.
*
* @return unmodifiable list of events as performance logs.
*/
public List<PerformanceLogRecord> getEventRecords() {
return Collections.unmodifiableList(eventRecords.get());
}
/**
* Adds a performance log record to the current list of events.
*
* @param record
* performance log record that is going to be added.
*/
public void addEvent(PerformanceLogRecord record) {
eventRecords.get().add(record);
}
/**
* Removes all of the existing records from the current list of events.
*/
public void cleanEvents() {
eventRecords.get().clear();
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2020, Google LLC and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.logging;
/**
* Class to register a performance log record.
*
* @since 5.10
*/
public class PerformanceLogRecord {
/** Name of the recorded event. */
private String name;
/** Duration of the recorded event in milliseconds. */
private long durationMs;
/**
* Create a new performance log record for an event.
*
* @param name
* name of the event.
* @param durationMs
* duration in milliseconds of the event.
*/
public PerformanceLogRecord(String name, long durationMs) {
this.name = name;
this.durationMs = durationMs;
}
/**
* Get the name of the recorded event.
*
* @return name of the recorded event.
*/
public String getName() {
return name;
}
/**
* Get the duration in milliseconds of the recorded event.
*
* @return duration in milliseconds of the recorded event.
*/
public long getDurationMs() {
return durationMs;
}
}