diff options
author | Wyatt Hepler <hepler@google.com> | 2022-01-25 10:43:06 -0800 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-04-04 17:24:18 +0000 |
commit | d14e858ca630583416b8c54b49868bc9e5b338c1 (patch) | |
tree | 05faccdcf30e33d4d79a84fd43a4866444f1c8ed | |
parent | 507dcae2bf64868ae2db9c14fe90b0607ddb96e3 (diff) | |
download | pigweed-d14e858ca630583416b8c54b49868bc9e5b338c1.tar.gz |
pw_rpc: Restore Java client logging
- Create dev.pigweed.pw_log.Logger to support logging to either a
FluentLogger or the Android logger.
- Restore the pw_rpc Java client logs using dev.pigweed.pw_log.Logger.
Change-Id: I73a658deed6c0da3c6d9c8157f798c56dfbf9f10
Fixed: 611
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/81420
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Reviewed-by: Ted Pudlik <tpudlik@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
-rw-r--r-- | pw_log/Android.bp | 10 | ||||
-rw-r--r-- | pw_log/docs.rst | 11 | ||||
-rw-r--r-- | pw_log/java/android_main/dev/pigweed/pw_log/Logger.java | 110 | ||||
-rw-r--r-- | pw_log/java/main/dev/pigweed/pw_log/BUILD.bazel | 25 | ||||
-rw-r--r-- | pw_log/java/main/dev/pigweed/pw_log/Logger.java | 71 | ||||
-rw-r--r-- | pw_rpc/Android.bp | 1 | ||||
-rw-r--r-- | pw_rpc/java/main/dev/pigweed/pw_rpc/BUILD.bazel | 2 | ||||
-rw-r--r-- | pw_rpc/java/main/dev/pigweed/pw_rpc/Client.java | 38 | ||||
-rw-r--r-- | pw_rpc/java/main/dev/pigweed/pw_rpc/RpcManager.java | 18 | ||||
-rw-r--r-- | pw_rpc/java/main/dev/pigweed/pw_rpc/StreamObserverCall.java | 9 |
10 files changed, 259 insertions, 36 deletions
diff --git a/pw_log/Android.bp b/pw_log/Android.bp index 64a602024..9b5bb34f9 100644 --- a/pw_log/Android.bp +++ b/pw_log/Android.bp @@ -19,4 +19,12 @@ cc_library { export_include_dirs: [ "public", ], -}
\ No newline at end of file +} + +java_library { + name: "pw_log_android_java", + host_supported: true, + srcs: ["java/android_main/dev/pigweed/pw_log/*.java"], + visibility: ["//visibility:public"], + sdk_version: "current", +} diff --git a/pw_log/docs.rst b/pw_log/docs.rst index 6c30cd8ab..b3eac4376 100644 --- a/pw_log/docs.rst +++ b/pw_log/docs.rst @@ -412,3 +412,14 @@ argument to each macro call seemed like too much. On the other hand, flags are something that are typically added on a per-log-statement basis, and is why the flags are added on a per-call basis (though hidden through the high-level macros). + +-------------- +pw_log in Java +-------------- +``pw_log`` provides a thin Java logging class that uses Google's `Flogger +<https://google.github.io/flogger/>`_ API. The purpose of this wrapper is to +support logging on platforms that do not support Flogger. The main +implementation in ``pw_log/java/main`` simply wraps a +``com.google.common.flogger.FluentLogger``. An implementation that logs to +Android's ``android.util.Log`` instead is provided in +``pw_log/java/android_main``. diff --git a/pw_log/java/android_main/dev/pigweed/pw_log/Logger.java b/pw_log/java/android_main/dev/pigweed/pw_log/Logger.java new file mode 100644 index 000000000..01d47aba2 --- /dev/null +++ b/pw_log/java/android_main/dev/pigweed/pw_log/Logger.java @@ -0,0 +1,110 @@ +// Copyright 2022 The Pigweed Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +package dev.pigweed.pw_log; + +import android.util.Log; +import java.util.logging.Level; + +/** + * Partial implementation of the com.google.common.flogger.FluentLogger API that + * logs to android.util.Log. + */ +public final class Logger { + private final String tag; + + public final class AndroidLogApi { + private final int level; + + private Throwable cause = null; + + private AndroidLogApi(Level level) { + switch (level) { + case Level.FINEST: + case Level.FINER: + this.level = Log.VERBOSE; + break; + case Level.FINE: + case Level.CONFIG: + this.level = Log.DEBUG; + break; + case Level.INFO: + this.level = Log.INFO; + break; + case Level.WARNING: + this.level = Log.WARN; + break; + case Level.SEVERE: + this.level = Log.ERROR; + break; + } + } + + public AndroidLogApi withCause(Throwable casue) { + this.cause = cause; + } + + public void log(String message) { + if (cause != null) { + message = String.format("%s: %s", cause, message); + } + + Log.println(level, tag, message); + } + + public void log(String message, Object... args) { + log(String.format(message, args)); + } + } + + public static Logger forClass(Class<?> enclosingClass) { + return new Logger(enclosingClass.getSimpleName()); + } + + private Logger(String tag) { + this.tag = tag; + } + + public AndroidLogApi at(Level level) { + return new AndroidLogApi(level); + } + + public AndroidLogApi atSevere() { + return at(Level.SEVERE); + } + + public AndroidLogApi atWarning() { + return at(Level.WARNING); + } + + public AndroidLogApi atInfo() { + return at(Level.INFO); + } + + public AndroidLogApi atConfig() { + return at(Level.CONFIG); + } + + public AndroidLogApi atFine() { + return at(Level.FINE); + } + + public AndroidLogApi atFiner() { + return at(Level.FINER); + } + + public AndroidLogApi atFinest() { + return at(Level.FINEST); + } +} diff --git a/pw_log/java/main/dev/pigweed/pw_log/BUILD.bazel b/pw_log/java/main/dev/pigweed/pw_log/BUILD.bazel new file mode 100644 index 000000000..8ebacb05a --- /dev/null +++ b/pw_log/java/main/dev/pigweed/pw_log/BUILD.bazel @@ -0,0 +1,25 @@ +# Copyright 2022 The Pigweed Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +# Logging API that maps to Google's Flogger (https://google.github.io/flogger/), +# or an alternate API if Flogger is not supported. + +java_library( + name = "pw_log", + srcs = ["Logger.java"], + visibility = ["//visibility:public"], + deps = [ + "@maven//:com_google_flogger_flogger", + ], +) diff --git a/pw_log/java/main/dev/pigweed/pw_log/Logger.java b/pw_log/java/main/dev/pigweed/pw_log/Logger.java new file mode 100644 index 000000000..f1ba7449c --- /dev/null +++ b/pw_log/java/main/dev/pigweed/pw_log/Logger.java @@ -0,0 +1,71 @@ +// Copyright 2022 The Pigweed Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +package dev.pigweed.pw_log; + +import com.google.common.flogger.FluentLogger; +import java.util.logging.Level; + +/** + * Partial implementation of the com.google.common.flogger.FluentLogger API that + * wraps a FluentLogger instance. + * + * This class is used instead of directly logging to FluentLogger to support + * swapping the implementation on systems that don't support FluentLogger (i.e. + * Android). + */ +@SuppressWarnings("FloggerSplitLogStatement") +public final class Logger { + private final FluentLogger wrappedLogger; + + public static Logger forClass(Class<?> enclosingClass) { + return new Logger(FluentLogger.forEnclosingClass()); + } + + private Logger(FluentLogger fluentLogger) { + this.wrappedLogger = fluentLogger; + } + + public FluentLogger.Api at(Level level) { + return wrappedLogger.at(level); + } + + public FluentLogger.Api atSevere() { + return at(Level.SEVERE); + } + + public FluentLogger.Api atWarning() { + return at(Level.WARNING); + } + + public FluentLogger.Api atInfo() { + return at(Level.INFO); + } + + public FluentLogger.Api atConfig() { + return at(Level.CONFIG); + } + + public FluentLogger.Api atFine() { + return at(Level.FINE); + } + + public FluentLogger.Api atFiner() { + return at(Level.FINER); + } + + public FluentLogger.Api atFinest() { + return at(Level.FINEST); + } +} diff --git a/pw_rpc/Android.bp b/pw_rpc/Android.bp index aeca94b0f..9bb863871 100644 --- a/pw_rpc/Android.bp +++ b/pw_rpc/Android.bp @@ -25,6 +25,7 @@ java_library { "guava", "jsr305", "libprotobuf-java-lite", + "pw_log_android_java", ], plugins: ["auto_value_plugin"], sdk_version: "current", diff --git a/pw_rpc/java/main/dev/pigweed/pw_rpc/BUILD.bazel b/pw_rpc/java/main/dev/pigweed/pw_rpc/BUILD.bazel index 5f834a029..4747b7f86 100644 --- a/pw_rpc/java/main/dev/pigweed/pw_rpc/BUILD.bazel +++ b/pw_rpc/java/main/dev/pigweed/pw_rpc/BUILD.bazel @@ -36,11 +36,11 @@ java_library( ], visibility = ["//visibility:public"], deps = [ + "//pw_log/java/main/dev/pigweed/pw_log", "//pw_rpc:packet_proto_java_lite", "//third_party/google_auto:value", "@com_google_protobuf//java/lite", "@maven//:com_google_code_findbugs_jsr305", - "@maven//:com_google_flogger_flogger", "@maven//:com_google_guava_guava", ], ) diff --git a/pw_rpc/java/main/dev/pigweed/pw_rpc/Client.java b/pw_rpc/java/main/dev/pigweed/pw_rpc/Client.java index ea3f7df9f..f4d187351 100644 --- a/pw_rpc/java/main/dev/pigweed/pw_rpc/Client.java +++ b/pw_rpc/java/main/dev/pigweed/pw_rpc/Client.java @@ -14,10 +14,10 @@ package dev.pigweed.pw_rpc; -// import com.google.common.flogger.FluentLogger; import com.google.protobuf.ExtensionRegistryLite; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageLite; +import dev.pigweed.pw_log.Logger; import dev.pigweed.pw_rpc.internal.Packet.PacketType; import dev.pigweed.pw_rpc.internal.Packet.RpcPacket; import java.nio.ByteBuffer; @@ -33,8 +33,7 @@ import javax.annotation.Nullable; * through the processPacket function. */ public class Client { - // TODO(pwbug/611): Restore logging without a mandatory Flogger dependency. - // private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private static final Logger logger = Logger.forClass(Client.class); private final Map<Integer, Channel> channels; private final Map<Integer, Service> services; @@ -81,17 +80,17 @@ public class Client { return create(channels, services, (rpc) -> new StreamObserver<MessageLite>() { @Override public void onNext(MessageLite value) { - // logger.atFine().log("%s received response: %s", rpc, value); + logger.atFine().log("%s received response: %s", rpc, value); } @Override public void onCompleted(Status status) { - // logger.atInfo().log("%s completed with status %s", rpc, status); + logger.atInfo().log("%s completed with status %s", rpc, status); } @Override public void onError(Status status) { - // logger.atWarning().log("%s terminated with error %s", rpc, status); + logger.atWarning().log("%s terminated with error %s", rpc, status); } }); } @@ -167,31 +166,30 @@ public class Client { try { packet = RpcPacket.parseFrom(data, ExtensionRegistryLite.getEmptyRegistry()); } catch (InvalidProtocolBufferException e) { - // logger.atWarning().withCause(e).log("Failed to decode packet"); + logger.atWarning().withCause(e).log("Failed to decode packet"); return false; } if (packet.getChannelId() == 0 || packet.getServiceId() == 0 || packet.getMethodId() == 0) { - // logger.atWarning().log("Received corrupt packet with unset IDs"); + logger.atWarning().log("Received corrupt packet with unset IDs"); return false; } // Packets for the server use even type values. if (packet.getTypeValue() % 2 == 0) { - // logger.atFine().log("Ignoring %s packet for server", packet.getType().name()); + logger.atFine().log("Ignoring %s packet for server", packet.getType().name()); return false; } Channel channel = channels.get(packet.getChannelId()); if (channel == null) { - // logger.atWarning().log( - // "Received packet for unrecognized channel %d", packet.getChannelId()); + logger.atWarning().log("Received packet for unrecognized channel %d", packet.getChannelId()); return false; } PendingRpc rpc = lookupRpc(channel, packet); if (rpc == null) { - // logger.atInfo().log("Ignoring packet for unknown service method"); + logger.atInfo().log("Ignoring packet for unknown service method"); sendError(channel, packet, Status.NOT_FOUND); return true; // true since the packet was handled, even though it was invalid. } @@ -200,8 +198,8 @@ public class Client { StreamObserverCall<?, ?> call = packet.getType().equals(PacketType.SERVER_STREAM) ? rpcs.getPending(rpc) : rpcs.clear(rpc); if (call == null) { - // logger.atInfo().log( - // "Ignoring packet for RPC (%s) that isn't pending. Pending RPCs are: %s", rpc, rpcs); + logger.atInfo().log( + "Ignoring packet for RPC (%s) that isn't pending. Pending RPCs are: %s", rpc, rpcs); sendError(channel, packet, Status.FAILED_PRECONDITION); return true; } @@ -209,7 +207,7 @@ public class Client { switch (packet.getType()) { case SERVER_ERROR: Status status = decodeStatus(packet); - // logger.atWarning().log("RPC %s failed with error %s", rpc, status); + logger.atWarning().log("RPC %s failed with error %s", rpc, status); call.onError(status); break; case RESPONSE: @@ -223,8 +221,8 @@ public class Client { call.onNext(packet.getPayload()); break; default: - // logger.atWarning().log( - // "Unexpected PacketType %d for RPC %s", packet.getType().getNumber(), rpc); + logger.atWarning().log( + "Unexpected PacketType %d for RPC %s", packet.getType().getNumber(), rpc); } return true; @@ -234,7 +232,7 @@ public class Client { try { channel.send(Packets.error(packet, status)); } catch (ChannelOutputException e) { - // logger.atWarning().withCause(e).log("Failed to send error packet"); + logger.atWarning().withCause(e).log("Failed to send error packet"); } } @@ -254,8 +252,8 @@ public class Client { private static Status decodeStatus(RpcPacket packet) { Status status = Status.fromCode(packet.getStatus()); if (status == null) { - // logger.atWarning().log( - // "Illegal status code %d in packet; using Status.UNKNOWN ", packet.getStatus()); + logger.atWarning().log( + "Illegal status code %d in packet; using Status.UNKNOWN ", packet.getStatus()); return Status.UNKNOWN; } return status; diff --git a/pw_rpc/java/main/dev/pigweed/pw_rpc/RpcManager.java b/pw_rpc/java/main/dev/pigweed/pw_rpc/RpcManager.java index 12e6db1a6..2f8b8699d 100644 --- a/pw_rpc/java/main/dev/pigweed/pw_rpc/RpcManager.java +++ b/pw_rpc/java/main/dev/pigweed/pw_rpc/RpcManager.java @@ -14,16 +14,16 @@ package dev.pigweed.pw_rpc; -// import com.google.common.flogger.FluentLogger; import com.google.protobuf.MessageLite; +import dev.pigweed.pw_log.Logger; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; /** Tracks the state of service method invocations. */ public class RpcManager { - // TODO(pwbug/611): Restore logging without a mandatory Flogger dependency. - // private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private static final Logger logger = Logger.forClass(RpcManager.class); + private final Map<PendingRpc, StreamObserverCall<?, ?>> pending = new HashMap<>(); /** @@ -37,7 +37,7 @@ public class RpcManager { public synchronized StreamObserverCall<?, ?> start( PendingRpc rpc, StreamObserverCall<?, ?> call, @Nullable MessageLite payload) throws ChannelOutputException { - // logger.atFine().log("Start %s", rpc); + logger.atFine().log("Start %s", rpc); rpc.channel().send(Packets.request(rpc, payload)); return pending.put(rpc, call); } @@ -51,12 +51,12 @@ public class RpcManager { @Nullable public synchronized StreamObserverCall<?, ?> open( PendingRpc rpc, StreamObserverCall<?, ?> call, @Nullable MessageLite payload) { - // logger.atFine().log("Open %s", rpc); + logger.atFine().log("Open %s", rpc); try { rpc.channel().send(Packets.request(rpc, payload)); } catch (ChannelOutputException e) { - // logger.atFine().withCause(e).log( - // "Ignoring error opening %s; listening for unrequested responses", rpc); + logger.atFine().withCause(e).log( + "Ignoring error opening %s; listening for unrequested responses", rpc); } return pending.put(rpc, call); } @@ -67,7 +67,7 @@ public class RpcManager { throws ChannelOutputException { StreamObserverCall<?, ?> call = pending.remove(rpc); if (call != null) { - // logger.atFine().log("Cancel %s", rpc); + logger.atFine().log("Cancel %s", rpc); rpc.channel().send(Packets.cancel(rpc)); } return call; @@ -97,7 +97,7 @@ public class RpcManager { public synchronized StreamObserverCall<?, ?> clear(PendingRpc rpc) { StreamObserverCall<?, ?> call = pending.remove(rpc); if (call != null) { - // logger.atFine().log("Clear %s", rpc); + logger.atFine().log("Clear %s", rpc); } return call; } diff --git a/pw_rpc/java/main/dev/pigweed/pw_rpc/StreamObserverCall.java b/pw_rpc/java/main/dev/pigweed/pw_rpc/StreamObserverCall.java index f59d1518b..537362c6c 100644 --- a/pw_rpc/java/main/dev/pigweed/pw_rpc/StreamObserverCall.java +++ b/pw_rpc/java/main/dev/pigweed/pw_rpc/StreamObserverCall.java @@ -14,11 +14,11 @@ package dev.pigweed.pw_rpc; -// import com.google.common.flogger.FluentLogger; import com.google.common.util.concurrent.AbstractFuture; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageLite; +import dev.pigweed.pw_log.Logger; import dev.pigweed.pw_rpc.Call.ClientStreaming; import java.util.function.Consumer; import javax.annotation.Nullable; @@ -35,8 +35,7 @@ import javax.annotation.Nullable; */ class StreamObserverCall<RequestT extends MessageLite, ResponseT extends MessageLite> implements ClientStreaming<RequestT> { - // TODO(pwbug/611): Restore logging without a mandatory Flogger dependency. - // private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + private static final Logger logger = Logger.forClass(StreamObserverCall.class); private final RpcManager rpcs; private final PendingRpc rpc; @@ -258,8 +257,8 @@ class StreamObserverCall<RequestT extends MessageLite, ResponseT extends Message try { return (ResponseT) rpc.method().decodeResponsePayload(payload); } catch (InvalidProtocolBufferException e) { - // logger.atWarning().withCause(e).log( - // "Failed to decode response for method %s; skipping packet", rpc.method().name()); + logger.atWarning().withCause(e).log( + "Failed to decode response for method %s; skipping packet", rpc.method().name()); return null; } } |