diff --git a/core/build.gradle b/core/build.gradle index a6a3752133..2bf0678742 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -45,6 +45,9 @@ javadoc { // We want io.grpc.Internal, but not io.grpc.Internal* exclude 'io/grpc/Internal?*.java' exclude 'io/grpc/internal/**' + + // Disabled until kinda stable. + exclude 'io/grpc/perfmark/**' } animalsniffer { diff --git a/core/src/main/java/io/grpc/perfmark/PerfMark.java b/core/src/main/java/io/grpc/perfmark/PerfMark.java new file mode 100644 index 0000000000..66936e0feb --- /dev/null +++ b/core/src/main/java/io/grpc/perfmark/PerfMark.java @@ -0,0 +1,445 @@ +/* + * Copyright 2019 The gRPC 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 + * + * http://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 io.grpc.perfmark; + +import com.google.errorprone.annotations.CompileTimeConstant; +import javax.annotation.concurrent.ThreadSafe; + +/** + * PerfMark is a collection of stub methods for marking key points in the RPC lifecycle. This + * class is {@link io.grpc.Internal} and {@link io.grpc.ExperimentalApi}. Do not use this yet. + */ +@ThreadSafe +public final class PerfMark { + private PerfMark() { + throw new AssertionError("nope"); + } + + /** + * Start a Task with a Tag to identify it; a task represents some work that spans some time, and + * you are interested in both its start time and end time. + * + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #taskStart(String)} or {@link PerfTag#create(String)}. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static void taskStart(PerfTag tag, @CompileTimeConstant String taskName) {} + + /** + * Start a Task with a Tag to identify it; a task represents some work that spans some time, and + * you are interested in both its start time and end time. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #taskStart(String)} or {@link PerfTag#create(String)}. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static void taskStart( + long scopeId, String scopeName, PerfTag tag, @CompileTimeConstant String taskName) {} + + /** + * Start a Task; a task represents some work that spans some time, and you are interested in both + * its start time and end time. + * + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static void taskStart(@CompileTimeConstant String taskName) {} + + /** + * Start a Task; a task represents some work that spans some time, and you are interested in both + * its start time and end time. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static void taskStart( + long scopeId, String scopeName, @CompileTimeConstant String taskName) {} + + /** + * Start a Task with a Tag to identify it and with a time threshold; a task represents some work + * that spans some time, and you are interested in both its start time and end time. + * + *

Sometimes, you may be interested in only events that take more than a certain time + * threshold. In such cases, you can use this method. A Task that takes less than the specified + * threshold, along with all its sub-tasks, events, and additional tags will be discarded. + * + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #taskStartWithMinPeriod(long, String)} or {@link PerfTag#create(String)}. + * @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will + * be discarded, along with its sub-tasks, events, and additional tags. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static void taskStartWithMinPeriod( + PerfTag tag, long minPeriodNanos, @CompileTimeConstant String taskName) {} + + /** + * Start a Task with a Tag to identify it and with a time threshold; a task represents some work + * that spans some time, and you are interested in both its start time and end time. + * + *

Sometimes, you may be interested in only events that take more than a certain time + * threshold. In such cases, you can use this method. A Task that takes less than the specified + * threshold, along with all its sub-tasks, events, and additional tags will be discarded. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #taskStartWithMinPeriod(long, String)} or {@link PerfTag#create(String)}. + * @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will + * be discarded, along with its sub-tasks, events, and additional tags. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static void taskStartWithMinPeriod( + long scopeId, + String scopeName, + PerfTag tag, + long minPeriodNanos, + @CompileTimeConstant String taskName) {} + + /** + * Start a Task with time threshold. A task represents some work that spans some time, and you are + * interested in both its start time and end time. + * + *

Sometimes, you may be interested in only events that take more than a certain time + * threshold. In such cases, you can use this method. A task that takes less than the specified + * threshold, along with all its sub-tasks, events, and additional tags will be discarded. + * + * @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will + * be discarded, along with its sub-tasks, events, and additional tags. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static void taskStartWithMinPeriod( + long minPeriodNanos, @CompileTimeConstant String taskName) {} + + /** + * Start a Task with time threshold. A task represents some work that spans some time, and you are + * interested in both its start time and end time. + * + *

Sometimes, you may be interested in only events that take more than a certain time + * threshold. In such cases, you can use this method. A task that takes less than the specified + * threshold, along with all its sub-tasks, events, and additional tags will be discarded. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will + * be discarded, along with its sub-tasks, events, and additional tags. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static void taskStartWithMinPeriod( + long scopeId, String scopeName, long minPeriodNanos, @CompileTimeConstant String taskName) {} + + /** End a Task. See {@link #taskStart(PerfTag, String)}. */ + public static void taskEnd() {} + + /** + * End a Task. See {@link #taskStart(PerfTag, String)}. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + */ + public static void taskEnd(long scopeId, String scopeName) {} + + /** + * Start a Task with a Tag to identify it in a try-with-resource statement; a task represents some + * work that spans some time, and you are interested in both its start time and end time. + * + *

Use this in a try-with-resource statement so that task will end automatically. + * + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #task(String)} or {@link PerfTag#create(String)}. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static PerfMarkTask task(PerfTag tag, @CompileTimeConstant String taskName) { + return AUTO_DO_NOTHING; + } + + /** + * Start a Task with a Tag to identify it in a try-with-resource statement; a task represents some + * work that spans some time, and you are interested in both its start time and end time. + * + *

Use this in a try-with-resource statement so that task will end automatically. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #task(String)} or {@link PerfTag#create(String)}. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static PerfMarkTask task( + long scopeId, String scopeName, PerfTag tag, @CompileTimeConstant String taskName) { + return AUTO_DO_NOTHING; + } + + /** + * Start a Task it in a try-with-resource statement; a task represents some work that spans some + * time, and you are interested in both its start time and end time. + * + *

Use this in a try-with-resource statement so that task will end automatically. + * + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static PerfMarkTask task(@CompileTimeConstant String taskName) { + return AUTO_DO_NOTHING; + } + + /** + * Start a Task it in a try-with-resource statement; a task represents some work that spans some + * time, and you are interested in both its start time and end time. + * + *

Use this in a try-with-resource statement so that task will end automatically. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static PerfMarkTask task( + long scopeId, String scopeName, @CompileTimeConstant String taskName) { + return AUTO_DO_NOTHING; + } + + /** + * Start a Task with a Tag to identify it, and with time threshold, in a try-with-resource + * statement; a task represents some work that spans some time, and you are interested in both its + * start time and end time. + * + *

Use this in a try-with-resource statement so that task will end automatically. + * + *

Sometimes, you may be interested in only events that take more than a certain time + * threshold. In such cases, you can use this method. A task that takes less than the specified + * threshold, along with all its sub-tasks, events, and additional tags will be discarded. + * + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #taskWithMinPeriod(long, String)} or {@link PerfTag#create(String)}. + * @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will + * be discarded, along with its sub-tasks, events, and additional tags. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static PerfMarkTask taskWithMinPeriod( + PerfTag tag, long minPeriodNanos, @CompileTimeConstant String taskName) { + return AUTO_DO_NOTHING; + } + + /** + * Start a Task with a Tag to identify it, and with time threshold, in a try-with-resource + * statement; a task represents some work that spans some time, and you are interested in both its + * start time and end time. + * + *

Use this in a try-with-resource statement so that task will end automatically. + * + *

Sometimes, you may be interested in only events that take more than a certain time + * threshold. In such cases, you can use this method. A task that takes less than the specified + * threshold, along with all its sub-tasks, events, and additional tags will be discarded. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #taskWithMinPeriod(long, String)} or {@link PerfTag#create(String)}. + * @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will + * be discarded, along with its sub-tasks, events, and additional tags. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static PerfMarkTask taskWithMinPeriod( + long scopeId, + String scopeName, + PerfTag tag, + long minPeriodNanos, + @CompileTimeConstant String taskName) { + return AUTO_DO_NOTHING; + } + + /** + * Start a Task with time threshold in a try-with-resource statement; a task represents some work + * that spans some time, and you are interested in both its start time and end time. + * + *

Use this in a try-with-resource statement so that task will end automatically. + * + *

Sometimes, you may be interested in only events that take more than a certain time + * threshold. In such cases, you can use this method. A task that takes less than the specified + * threshold, along with all its sub-tasks, events, and additional tags will be discarded. + * + * @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will + * be discarded, along with its sub-tasks, events, and additional tags. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static PerfMarkTask taskWithMinPeriod( + long minPeriodNanos, @CompileTimeConstant String taskName) { + return AUTO_DO_NOTHING; + } + + /** + * Start a Task with time threshold in a try-with-resource statement; a task represents some work + * that spans some time, and you are interested in both its start time and end time. + * + *

Use this in a try-with-resource statement so that task will end automatically. + * + *

Sometimes, you may be interested in only events that take more than a certain time + * threshold. In such cases, you can use this method. A task that takes less than the specified + * threshold, along with all its sub-tasks, events, and additional tags will be discarded. + * + * @param scopeId The scope of the task. The scope id is used to join task starting and ending + * across threads. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will + * be discarded, along with its sub-tasks, events, and additional tags. + * @param taskName The name of the task. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this task. + */ + public static PerfMarkTask taskWithMinPeriod( + long scopeId, String scopeName, long minPeriodNanos, @CompileTimeConstant String taskName) { + return AUTO_DO_NOTHING; + } + + static final PerfMarkTask AUTO_DO_NOTHING = new PerfMarkTask() { + @Override + public void close() {} + }; + + /** + * Records an Event with a Tag to identify it. + * + *

An Event is different from a Task in that you don't care how much time it spanned. You are + * interested in only the time it happened. + * + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #event(String)} or {@link PerfTag#create(String)}. + * @param eventName The name of the event. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this event. + */ + public static void event(PerfTag tag, @CompileTimeConstant String eventName) {} + + /** + * Records an Event with a Tag to identify it. + * + *

An Event is different from a Task in that you don't care how much time it spanned. You are + * interested in only the time it happened. + * + * @param scopeId The scope of the event. The scope id is used to associated the event with a + * particular scope. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * #event(String)} or {@link PerfTag#create(String)}. + * @param eventName The name of the event. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this event. + */ + public static void event( + long scopeId, String scopeName, PerfTag tag, @CompileTimeConstant String eventName) {} + + /** + * Records an Event. + * + *

An Event is different from a Task in that you don't care how much time it spanned. You are + * interested in only the time it happened. + * + * @param eventName The name of the event. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this event. + */ + public static void event(@CompileTimeConstant String eventName) {} + + /** + * Records an Event. + * + *

An Event is different from a Task in that you don't care how much time it spanned. You are + * interested in only the time it happened. + * + * @param scopeId The scope of the event. The scope id is used to associate the event with a + * particular scope. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param eventName The name of the event. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this event. + */ + public static void event(long scopeId, String scopeName, @CompileTimeConstant String eventName) {} + + /** + * Add an additional tag to the last task that was started. + * + *

A tag is different from an Event or a task in that clients don't care about the time at + * which this tag is added. Instead, it allows clients to associate an additional tag to the + * current Task. + * + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * PerfTag#create(String)}. + * @param tagName The name of the tag. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this tag. + */ + public static void tag(PerfTag tag, @CompileTimeConstant String tagName) {} + + /** + * Add an additional tag to the last task that was started. + * + *

A tag is different from an Event or a task in that clients don't care about the time at + * which this tag is added. Instead, it allows clients to associate an additional tag to the + * current Task. + * + * @param scopeId The scope of the tag. The scope id is used to associate a tag with a particular + * scope. The scope id must be a positive number. + * @param scopeName The name of the scope. + * @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't + * use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task + * does not have a numeric tag associated. In this case, you are encouraged to use {@link + * PerfTag#create(String)}. + * @param tagName The name of the tag. This parameter must be a compile-time constant! + * Otherwise, instrumentation result will show "(invalid name)" for this tag. + */ + public static void tag( + long scopeId, String scopeName, PerfTag tag, @CompileTimeConstant String tagName) {} +} diff --git a/core/src/main/java/io/grpc/perfmark/PerfMarkTask.java b/core/src/main/java/io/grpc/perfmark/PerfMarkTask.java new file mode 100644 index 0000000000..4a689d8ab1 --- /dev/null +++ b/core/src/main/java/io/grpc/perfmark/PerfMarkTask.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 The gRPC 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 + * + * http://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 io.grpc.perfmark; + +import java.io.Closeable; + +/** + * This class exists to make it easier for users to use the try-with-resource shorthand for + * starting and ending a PerfMark Task. This class is {@link io.grpc.Internal} and + * {@link io.grpc.ExperimentalApi}. Do not use this yet. + */ +public abstract class PerfMarkTask implements Closeable { + @Override + public abstract void close(); + + PerfMarkTask() {} +} diff --git a/core/src/main/java/io/grpc/perfmark/PerfMarker.java b/core/src/main/java/io/grpc/perfmark/PerfMarker.java new file mode 100644 index 0000000000..b39b85f526 --- /dev/null +++ b/core/src/main/java/io/grpc/perfmark/PerfMarker.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 The gRPC 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 + * + * http://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 io.grpc.perfmark; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to add PerfMark instrumentation points surrounding method invocation. + * + *

This class is {@link io.grpc.Internal} and {@link io.grpc.ExperimentalApi}. Do not use this + * yet. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +// TODO(carl-mastrangelo): Add this line back in and make it okay on Android +//@IncompatibleModifiers(value = {Modifier.ABSTRACT, Modifier.NATIVE}) +public @interface PerfMarker { + + /** + * The name of the task; e.g. `parseHeaders`. + */ + String taskName(); + + /** + * An optional computed tag. + * + *

There are 3 supported references that can be used + *

+ * + *

In general you should reference either {@code "this"} or {@code final} fields since + * in these cases we can cache the operations to decrease the cost of computing the tags. A side + * effect of this is that for such references we will not have their tags recalculated after the + * first time. Thus it is best to use immutable objects for tags. + */ + String computedTag() default ""; + + /** + * True if class with annotation is immutable and instrumentation must adhere to this restriction. + * If enableSampling is passed as argument to the agent, instrumentation points with + * immutable = true are ignored. + */ + boolean immutable() default false; +} + diff --git a/core/src/main/java/io/grpc/perfmark/PerfTag.java b/core/src/main/java/io/grpc/perfmark/PerfTag.java new file mode 100644 index 0000000000..e75682d445 --- /dev/null +++ b/core/src/main/java/io/grpc/perfmark/PerfTag.java @@ -0,0 +1,158 @@ +/* + * Copyright 2019 The gRPC 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 + * + * http://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 io.grpc.perfmark; + +/** + * A Tag is used to provide additional information to identify a task and consists of a 64-bit + * integer value and a string. + * + *

Both the {@code numericTag} and the {@code stringTag} are optional. The {@code numericTag} + * value can be used to identify the specific task being worked on (e.g. the id of the rpc call). + * The {@code stringTag} can be used to store any value that is not a compile-time constant (a + * restriction imposed for the name passed to PerfMark tasks and events). A value of 0 for the + * {@code numericTag} is considered null. Don't use 0 for the {@code numericTag} unless you intend + * to specify null. In that case you are encouraged to use {@link #create(String)}. + * + *

Invocations to {@code create} methods in this class are a no-op unless PerfMark + * instrumentation is enabled. If so, calls to {@code create} methods to this class are replaced for + * calls to {@link TagFactory} create methods. + * + *

This class is {@link io.grpc.Internal} and {@link io.grpc.ExperimentalApi}. Do not use this + * yet. + */ +public final class PerfTag { + + private static final long NULL_NUMERIC_TAG = 0; + private static final String NULL_STRING_TAG = ""; + + private static final PerfTag NULL_PERF_TAG = TagFactory.create(NULL_NUMERIC_TAG, NULL_STRING_TAG); + + /** + * If PerfMark instrumentation is not enabled, returns a Tag with numericTag = 0L. Replacement + * for {@link TagFactory#create(long, String)} if PerfMark agent is enabled. + */ + public static PerfTag create( + @SuppressWarnings("unused") long numericTag, @SuppressWarnings("unused") String stringTag) { + // Warning suppression is safe as this method returns by default the NULL_TAG + return NULL_PERF_TAG; + } + + /** + * If PerfMark instrumentation is not enabled returns a Tag with numericTag = 0L. Replacement + * for {@link TagFactory#create(String)} if PerfMark agent is enabled. + */ + public static PerfTag create(@SuppressWarnings("unused") String stringTag) { + // Warning suppression is safe as this method returns by default the NULL_TAG + return NULL_PERF_TAG; + } + + /** + * If PerfMark instrumentation is not enabled returns a Tag with numericTag = 0L. Replacement + * for {@link TagFactory#create(long)} if PerfMark agent is enabled. + */ + public static PerfTag create(@SuppressWarnings("unused") long numericTag) { + // Warning suppression is safe as this method returns by default the NULL_TAG + return NULL_PERF_TAG; + } + + /** + * Returns the null tag. + */ + public static PerfTag create() { + return NULL_PERF_TAG; + } + + /** + * Allocates a unique, mostly sequential unique id for Tags. This method will be replaced with + * a call to a real implementation if instrumentation is enabled. + */ + public static final long allocateNumericId() { + return NULL_NUMERIC_TAG; + } + + private final long numericTag; + private final String stringTag; + + private PerfTag(long numericTag, String stringTag) { + this.numericTag = numericTag; + if (stringTag == null) { + throw new NullPointerException("stringTag"); + } + this.stringTag = stringTag; + } + + /** Returns the numeric tag if set, or {@link Constants#NULL_NUMERIC_TAG} instead. */ + public long getNumericTag() { + return numericTag; + } + + /** Returns the string tag if set, or {@link Constants#NULL_STRING_TAG} instead. */ + public String getStringTag() { + return stringTag; + } + + @Override + public String toString() { + return "Tag(numericTag=" + numericTag + ",stringTag='" + stringTag + "')"; + } + + @Override + public int hashCode() { + int longHashCode = (int)(numericTag ^ (numericTag >>> 32)); + return longHashCode + (stringTag != null ? stringTag.hashCode() : 31); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof PerfTag)) { + return false; + } + PerfTag other = (PerfTag) obj; + return this.numericTag == other.numericTag && this.stringTag.equals(other.stringTag); + } + + /** + * Provides methods that create Tag instances which should not be directly invoked by clients. + * + *

Warning: Clients should not call methods from this class directly because of the + * overhead involved in the creation of Tag objects when PerfMark instrumentation is not + * enabled. + * + *

Calls to {@link PerfTag#create(long)}, {@link PerfTag#create(long, String)} and {@link + * PerfTag#create(String)} are replaced with calls to the methods in this class using bytecode + * rewriting, if enabled. + */ + static final class TagFactory { + /** + * This class should not be instantiated. + */ + private TagFactory() {} + + public static PerfTag create(long numericTag, String stringTag) { + return new PerfTag(numericTag, stringTag); + } + + public static PerfTag create(String stringTag) { + return new PerfTag(NULL_NUMERIC_TAG, stringTag); + } + + public static PerfTag create(long numericTag) { + return new PerfTag(numericTag, NULL_STRING_TAG); + } + } +} + diff --git a/core/src/main/java/io/grpc/perfmark/package-info.java b/core/src/main/java/io/grpc/perfmark/package-info.java new file mode 100644 index 0000000000..dd9cfdd071 --- /dev/null +++ b/core/src/main/java/io/grpc/perfmark/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2019 The gRPC 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 + * + * http://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. + */ + +/** + * This is an internal, experimental API and not subject to the normal compatibility guarantees. + */ +@io.grpc.Internal +package io.grpc.perfmark;