Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify logging interface & add RPC method #121

Merged
merged 23 commits into from
Mar 22, 2017

Conversation

ben-clayton
Copy link
Contributor

@ben-clayton ben-clayton commented Mar 20, 2017

Instead of log.Context, now use context.Context.

To log something use:

log.I(ctx, "cat says %v", "meow")
log.W(ctx, "dog says %v", "woof")
log.E(ctx, "fox says %v", "???")

Values are added to the context with:

ctx := log.V{"key": value}.Bind(ctx)

GAPII and GAPIR log messages are parsed into the structured form so they can be filtered.

New streaming RPC GetLogStream() monitors all log messages from GAPIS and all subprocesses interleaved. Can be used by GAPIC to display all logs across all processes.

AddPathStart("VK_DEVICE_LAYERS", "VkGraphicsSpy").
AddPathStart("VK_LAYER_PATH", libVkLayerGraphicsSpy.Parent().System()).
Set("LD_PRELOAD", libgapii.System()),
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's related. There's new logic to handle stdout and stderr, which adds more options to the start function. Given the number of parameters we're passing in, I opted for a struct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I noticed that later. Sorry, I didn't realize it sends out comments right away. Is there no draft comment mode like Critique/Gerrit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Next to the single line comment button there should be a "Start Review" green button.

@ben-clayton
Copy link
Contributor Author

Now also contains GAPIC changes to display the merged logs across GAPIC, GAPIS and GAPIR.

@ben-clayton
Copy link
Contributor Author

I'm following up with a final CL that avoids the tree.removeAll()

Copy link
Member

@pmuetschard pmuetschard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: i've checked in a .settings folder which enables a lot of warnings in Eclipse.

dirty.set(false);
}

private String formatTime(Timestamp time) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be static

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

case Fatal:
return theme.fatalBackground();
}
return theme.infoBackground();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this into a default case to make the behavior more explicit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

case Fatal:
return theme.fatalForeground();
}
return theme.infoForeground();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this into a default case to make the behavior more explicit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

private Color severityBackgroundColor(Log.Severity severity) {
switch (severity) {
case Verbose:
return theme.verboseBackground();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: since the case statements are so simple, I'd prefer them to be on one line:

      case Verbose: return theme.verboseBackground();
      case Debug: return theme.debugBackground();
      ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -15,54 +15,64 @@
*/
package com.google.gapid.util;

import com.google.gapid.proto.log.Log;
import com.google.gapid.rpclib.schema.Method;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not actually needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


static LogLevel fromLevel(Level level) {
for (LogLevel logLevel : LogLevel.values()) {
if (logLevel.level == level) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be range based as it was before.
java.util.logging.Level is not an enum, so you also should not use '==', but .equals.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

/**
* Adds a {@link Log.Message} to the buffer, bypassing the Java {@link LogManager}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this needs to be {@link com.google.gapid.proto.log.Log.Message}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this Eclipse telling you this? IntelliJ seems fine with it as-is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and no. Eclipse does give me the warning, but it comes straight from javadoc:
src/main/com/google/gapid/util/Logging.java:145: warning - Tag @link: reference not found: Log.Message

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

private static final String GAPID_PREFIX = "com.google.gapid.";
private static final String GOOG_PREFIX = "com.google.";

private static String shorten(String className) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this protected, as you are using it from multiple inner classes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure I've asked this before, but why is this an issue?
Done anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JVM has no concept (almost) of inner classes. To the JVM, an inner class and its container outer class are simply two different classes. You cannot call private methods of another class. The compiler adds synthetic methods to make it look like you can call private methods from inner/outer classes. These synthetic methods add unnecessary overhead and pollute stack traces. If you're going to allow access via these synthetic methods, why not give access directly?

public Runnable listener;
private final StringBuilder buffer = new StringBuilder();
private final LinkedList<Log.Message> buffer = new LinkedList<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buffer is shadowing Logging.buffer. I suggest renaming Logging.buffer to Logging.messageBuffer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed in later CL.

byte[] data = ByteStreams.toByteArray(in);
SearchingInputStream is = new SearchingInputStream(in);
if (!is.search(PACKAGE_DATA_MARKER.getBytes())) {
throw new RuntimeException("The gapit command didn't produce the data marker.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resource leak: 'is' is not closed at this location.

I'd suggest making the search method static and avoid the wrapping in another input stream. The SearchingInputStream class has no additional state, so it's not needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SearchingInputStream class has no additional state, so it's not needed.

Well, it has the buffered reader state. I've wrapped it with a try-with-resources,

@ben-clayton
Copy link
Contributor Author

FYI: i've checked in a .settings folder which enables a lot of warnings in Eclipse.

Thanks, but I use IntelliJ. :)

import java.util.logging.Logger;
import java.util.logging.StreamHandler;
import java.util.LinkedList;
import java.util.logging.*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please no * imports. I've been following the Google style for Java, and I'd like to continue to do so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Another IntelliJ default that I continually battle.


/**
* Logging setup and utilities.
*/
public class Logging {
/**
* Possible log level flag values.
* Possible logMessage level flag values.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Search replace?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor gone crazy. Fixed.

}

public static final Flag<LogLevel> logLevel = Flags.value(
"logLevel", LogLevel.INFO, "Logging level [OFF, ERROR, WARNING, INFO, DEBUG, ALL].");
public static final Flag<String> logDir = Flags.value(
"logDir", System.getProperty("java.io.tmpdir"), "Directory for log files.");
"logDir", System.getProperty("java.io.tmpdir"), "Directory for logMessage files.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Search replace?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -83,7 +93,7 @@ public static void init() {

if (!logDir.get().isEmpty()) {
try {
FileHandler fileHandler = new FileHandler(logDir.get() + File.separator + "gapic.log");
FileHandler fileHandler = new FileHandler(logDir.get() + File.separator + "gapic.logMessage");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Search replace?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

/**
* Adds a {@link Log.Message} to the buffer, bypassing the Java {@link LogManager}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and no. Eclipse does give me the warning, but it comes straight from javadoc:
src/main/com/google/gapid/util/Logging.java:145: warning - Tag @link: reference not found: Log.Message

}

public static void setListener(Runnable listener) {
buffer.listener = (listener == null) ? () -> { /* empty */ } : listener;
public static void setListener(Listener listener_) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name shadowing is acceptable on setters, if you're shadowing the variable you're setting.

If you don't like to do that, please use new instead of _.

@@ -123,6 +135,7 @@ public static void setListener(Runnable listener) {
*/
public static void logMessage(Log.Message message) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now very much round-about: Buffer.publish calls Logging.logMessage, which calls Buffer.add and then fires the event.

Better to keep it they way it was:
logMessage and Buffer.publish call Buffer.add
Buffer.add fires the event

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've separated Buffer and Handler. The inner class was doing too much - hence the extraction of the event logic. Hopefully this is now cleaner and would be nice and simple to make the classes public if needed in the future.

* new messages.
*/
private static class MessageIterator implements Iterator<Log.Message> {
private final Buffer buffer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shadows Logging.buffer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the class is static, does it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because so is Logging.buffer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (thrown != null) {
for (StackTraceElement el : thrown.getStackTrace()) {
builder.addCallstack(Log.SourceLocation.newBuilder()
.setFile(el.getFileName())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

el.getFileName can return null (protos don't like nulls).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Service.GetLogStreamRequest request = Service.GetLogStreamRequest.newBuilder().build();
Iterator<Log.Message> it = GapidGrpc.newBlockingStub(channel).getLogStream(request);
while (it.hasNext()) {
monitor.onLogMessage(it.next());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now causes an exception on clean shutdown. Before closing the connection to gapis, the logger thread should be stopped.

I think you'd be better off using a StreamObserver and the async case rather than the blocking case with an extra thread.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT, streamed RPCs aren't exposed in the FutureStub (if that's what you're referring to).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now unbinds the LogMonitor on close(). Added warning for unexpected StatusRuntimeExceptions that are thrown by the thread.

ben-clayton and others added 18 commits March 22, 2017 13:27
Replace all uses of log.Context with context.Context.
Squash the functionality of jot, memo, severity, fault into log.
Change-Id: I39df2ad33a3f780216fcbcbdcecbfd905252796e
Change-Id: I8ca1d2b11143352dfb6b8802f17c128d5dc49ee8
Change-Id: I4532f987e77b84b976a4d10adce39b75f1ce6d8e
Turn them into log.Messages.

Change-Id: I95153e2a860c6db46e9a78ebc047599685239b0c
Let's you control them on the command line.

Change-Id: Ib8b12a830a5a22b9f8c1c2fe2cbe00b7a451f1b0
Change-Id: I486fb73fed83100734fcb21d2bf391d44a862d51
Fixes the package picker when also logging to stdout.
Change-Id: Ic64e73cdf4d9b913594c7d02242c9c5dd06e1980
Change-Id: Ice567770dd74c9b2093c732f80be001a6e9d23c7
Change-Id: Ib103d8f824a7e0d7226584ad73127ad291dc763d
func (ctx logContext) Alert() Logger {
return ctx.At(severity.Alert)
func (s Severity) String() string {
switch s {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle Verbose...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return ctx.At(severity.Critical)
// Short returns the severity string with a single character.
func (s Severity) Short() string {
switch s {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle Verbose...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Change-Id: I15a47ec97283efdce403b87af8491295ee9c15f9
@dsrbecky
Copy link
Contributor

+1

Change-Id: If1619af5063c4e98268a8f0dcf33678970b251dd
Change-Id: I428d36fd26c984a7ffcadc50eeb948378d7b935a
import io.grpc.okhttp.OkHttpChannelProvider;

/**
* A connection to a running Graphics API Server (GAPIS).
*/
public abstract class GapisConnection implements Closeable {
private static final Logger LOG = Logger.getLogger(Client.class.getName());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Client.class -> GapisConnection.class

@@ -23,7 +23,8 @@
import com.google.gapid.proto.pkginfo.PkgInfo;
import com.google.gapid.proto.pkginfo.PkgInfo.PackageList;

import java.io.File;
import java.io.*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another .* import.

I think you can tell intellij not to do this by setting the minimum number of classes needed before it collapses imports to some very high number.


private static final RingBuffer buffer = new RingBuffer(BUFFER_SIZE);

private static final Handler handler = new Handler() {{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You no longer need to hang on to this reference, so just create the handler in the init() method and add it to the root logger.

* {@link Handler} that handles {@link LogRecord}s converting them to
* {@link com.google.gapid.proto.log.Log.Message}s and then broadcasting them to listeners.
*/
protected static class Handler extends java.util.logging.Handler {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe name this class ProtoHandler, or ProtoConverter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They both sound like the Proto is the source when it's the target. Opted for LogToMessageHandler.

}
Log.Severity severity = message.getSeverity();
TreeItem item = newItem(tree, severity);
String[] lines = message.getText().split("(\n)|(\r\n)");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split("\r?\n")

Change-Id: I1f8ac3259cf5b528feedf0a2077c4d966f53e375
@ben-clayton ben-clayton merged commit 4b31e32 into google:master Mar 22, 2017
@ben-clayton ben-clayton deleted the logs branch March 22, 2017 19:33
pmuetschard pushed a commit that referenced this pull request Jun 11, 2020
 - Add drag-selection to the Process Panel.
 - Change CPU slices' color after drag-selecting in Thread Panel.
 - Bug: http://b/147922469. #2 and #3.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants