| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.beam.runners.dataflow.worker.counters; |
| |
| import static org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Preconditions.checkNotNull; |
| |
| import com.google.auto.value.AutoValue; |
| import javax.annotation.Nullable; |
| import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.MoreObjects; |
| import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.MoreObjects.ToStringHelper; |
| |
| /** |
| * The name of a counter identifies the user-specified name, as well as the origin, the step the |
| * counter is associated with, and a prefix to add to the name. |
| * |
| * <p>For backwards compatibility, the {@link CounterName} will be converted to a flat name (string) |
| * during the migration. |
| */ |
| @AutoValue |
| public abstract class CounterName { |
| |
| /** Returns a {@link CounterName} with the given name. */ |
| public static CounterName named(String name) { |
| return create( |
| name, |
| "" /* origin */, |
| "" /* stepName */, |
| "" /* prefix */, |
| null /* contextOriginalName */, |
| null /* contextSystemName */, |
| null /* originalRequestingStepName */, |
| null /* inputIndex */); |
| } |
| |
| /** Returns a msecs {@link CounterName}. */ |
| public static CounterName msecs(String name) { |
| return named(name + "-msecs"); |
| } |
| |
| /** Returns a {@link CounterName} identical to this, but with the given origin. */ |
| public CounterName withOrigin(String origin) { |
| return create( |
| name(), |
| origin, |
| stepName(), |
| prefix(), |
| contextOriginalName(), |
| contextSystemName(), |
| originalRequestingStepName(), |
| inputIndex()); |
| } |
| |
| /** Returns a {@link CounterName} identical to this, but with the given step name. */ |
| public CounterName withStepName(String stepName) { |
| return create( |
| name(), |
| origin(), |
| stepName, |
| prefix(), |
| contextOriginalName(), |
| contextSystemName(), |
| originalRequestingStepName(), |
| inputIndex()); |
| } |
| |
| /** Returns a {@link CounterName} identical to this, but with the given prefix. */ |
| public CounterName withPrefix(String prefix) { |
| return create( |
| name(), |
| origin(), |
| stepName(), |
| prefix, |
| contextOriginalName(), |
| contextSystemName(), |
| originalRequestingStepName(), |
| inputIndex()); |
| } |
| |
| /** |
| * Returns a {@link CounterName} identical to this, but with the {@code originalName} from a |
| * {@link NameContext}. |
| */ |
| public CounterName withOriginalName(NameContext context) { |
| return create( |
| name(), |
| origin(), |
| stepName(), |
| prefix(), |
| checkNotNull(context.originalName(), "Expected original name in context %s", context), |
| contextSystemName(), |
| originalRequestingStepName(), |
| inputIndex()); |
| } |
| |
| /** |
| * Returns a {@link CounterName} identical to this, but with the {@code originalName} from a |
| * {@link String}. |
| */ |
| public CounterName withOriginalName(String originalName) { |
| return create( |
| name(), |
| origin(), |
| stepName(), |
| prefix(), |
| checkNotNull(originalName, "Expected original name in string %s", originalName), |
| contextSystemName(), |
| originalRequestingStepName(), |
| inputIndex()); |
| } |
| |
| /** |
| * Returns a {@link CounterName} identical to this, but with the {@code systemName} from a {@link |
| * NameContext}. |
| */ |
| public CounterName withSystemName(NameContext context) { |
| return create( |
| name(), |
| origin(), |
| stepName(), |
| prefix(), |
| contextOriginalName(), |
| checkNotNull(context.systemName(), "Expected system name in context %s", context), |
| originalRequestingStepName(), |
| inputIndex()); |
| } |
| |
| /** |
| * Returns a {@link CounterName} identical to this, but with the {@code |
| * originalRequestingStepName} |
| */ |
| public CounterName withOriginalRequestingStepName(String originalRequestingStepName) { |
| return create( |
| name(), |
| origin(), |
| stepName(), |
| prefix(), |
| contextOriginalName(), |
| contextSystemName(), |
| checkNotNull(originalRequestingStepName, "Expected a requesting step name"), |
| inputIndex()); |
| } |
| |
| public CounterName withInputIndex(Integer inputIndex) { |
| return create( |
| name(), |
| origin(), |
| stepName(), |
| prefix(), |
| contextOriginalName(), |
| contextSystemName(), |
| originalRequestingStepName(), |
| checkNotNull(inputIndex, "Expected an input index")); |
| } |
| |
| static CounterName create( |
| String name, |
| String origin, |
| String stepName, |
| String prefix, |
| String contextOriginalName, |
| String contextSystemName, |
| String originalRequestingStepName, |
| Integer inputIndex) { |
| return new AutoValue_CounterName( |
| checkNotNull(name, "Name is required for CounterName"), |
| checkNotNull(origin, "Origin is required for CounterName"), |
| checkNotNull(stepName, "StepName is required for CounterName"), |
| checkNotNull(prefix, "Prefix is required for CounterName"), |
| contextOriginalName, |
| contextSystemName, |
| originalRequestingStepName, |
| inputIndex); |
| } |
| |
| /** |
| * Name of the counter. |
| * |
| * <p>For example, process-msecs, ElementCount. |
| */ |
| public abstract String name(); |
| |
| /** |
| * Origin (namespace) of counter name. |
| * |
| * <p>For example, "user" for user-defined counters. It is empty for counters defined by the SDK |
| * or the runner. |
| */ |
| public abstract String origin(); |
| |
| /** |
| * System defined step name or the named-output of a step. |
| * |
| * <p>For example, {@code s1} or {@code s2.out}. It may be empty when counters don't associate |
| * with step names. |
| */ |
| public abstract String stepName(); |
| |
| /** |
| * Prefix of group of counters. |
| * |
| * <p>It is empty when counters don't have general prefixes. |
| */ |
| public abstract String prefix(); |
| |
| /** An optional {@code contextOriginalName}. */ |
| @Nullable |
| public abstract String contextOriginalName(); |
| |
| /** An optional {@code contextSystemName}. */ |
| @Nullable |
| public abstract String contextSystemName(); |
| |
| /** An optional {@code originalRequestingStepName}. */ |
| @Nullable |
| public abstract String originalRequestingStepName(); |
| |
| /** |
| * An optional identifier of a PCollection by index in input list received by step. |
| * |
| * <p>A CounterName with inputIndex set to 1, and stepName set to 's1' would declare a counter |
| * associated to s1's first side input. |
| */ |
| @Nullable |
| public abstract Integer inputIndex(); |
| |
| /** |
| * Flat name is suitable only for hashing. |
| * |
| * <p>It is null before {@link #getFlatName()} is called. TODO: this can be replaced |
| * with @Memoized when v1.4 auto.value is released |
| */ |
| private volatile String flatName; |
| |
| public String getFlatName() { |
| if (flatName == null) { |
| synchronized (this) { |
| if (flatName == null) { |
| flatName = toString(); |
| } |
| } |
| } |
| return flatName; |
| } |
| |
| public String toPrettyString() { |
| ToStringHelper helper = MoreObjects.toStringHelper(this); |
| helper.omitNullValues(); |
| helper.add("name", name()); |
| helper.add("origin", origin()); |
| helper.add("prefix", prefix()); |
| helper.add("stepName", stepName()); |
| helper.add("contextOriginalName", contextOriginalName()); |
| helper.add("contextSystemName", contextSystemName()); |
| helper.add("originalRequestingStepName", originalRequestingStepName()); |
| helper.add("inputIndex", inputIndex()); |
| return helper.toString(); |
| } |
| |
| /** |
| * Pretty name is the equivalent unstructured name. |
| * |
| * <p>It is null before {@link #getPrettyName()} is called. TODO: this can be replaced |
| * with @Memoized when v1.4 auto.value is released |
| */ |
| private volatile String prettyName; |
| |
| public String getPrettyName() { |
| if (prettyName == null) { |
| synchronized (this) { |
| if (prettyName == null) { |
| prettyName = toPrettyString(); |
| } |
| } |
| } |
| return prettyName; |
| } |
| |
| public boolean usesContextOriginalName() { |
| return contextOriginalName() != null; |
| } |
| |
| public boolean usesContextSystemName() { |
| return contextSystemName() != null; |
| } |
| |
| public boolean usesOriginalRequestingStepName() { |
| return originalRequestingStepName() != null; |
| } |
| |
| public boolean isStructured() { |
| return usesContextOriginalName() || usesContextSystemName() || usesOriginalRequestingStepName(); |
| } |
| } |