Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.fn.harness.logging;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.Preconditions.checkNotNull;
import static org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.Throwables.getStackTraceAsString;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import org.apache.beam.fn.harness.control.ExecutionStateSampler;
import org.apache.beam.model.fnexecution.v1.BeamFnApi;
import org.apache.beam.model.fnexecution.v1.BeamFnApi.LogEntry;
import org.apache.beam.model.fnexecution.v1.BeamFnLoggingGrpc;
import org.apache.beam.model.pipeline.v1.Endpoints;
import org.apache.beam.sdk.fn.stream.AdvancingPhaser;
import org.apache.beam.sdk.fn.stream.DirectStreamObserver;
import org.apache.beam.sdk.options.ExecutorOptions;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.options.SdkHarnessOptions;
import org.apache.beam.vendor.grpc.v1p60p1.com.google.protobuf.Struct;
import org.apache.beam.vendor.grpc.v1p60p1.com.google.protobuf.Timestamp;
import org.apache.beam.vendor.grpc.v1p60p1.com.google.protobuf.Value;
import org.apache.beam.vendor.grpc.v1p60p1.io.grpc.ManagedChannel;
import org.apache.beam.vendor.grpc.v1p60p1.io.grpc.stub.CallStreamObserver;
import org.apache.beam.vendor.grpc.v1p60p1.io.grpc.stub.ClientCallStreamObserver;
import org.apache.beam.vendor.grpc.v1p60p1.io.grpc.stub.ClientResponseObserver;
import org.apache.beam.vendor.grpc.v1p60p1.io.grpc.stub.StreamObserver;
import org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.MoreObjects;
import org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.collect.ImmutableMap;
import org.checkerframework.checker.initialization.qual.UnderInitialization;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
import org.slf4j.MDC;
/**
* Configures {@link java.util.logging} to send all {@link LogRecord}s via the Beam Fn Logging API.
*/
public class BeamFnLoggingClient implements AutoCloseable {
private static final String ROOT_LOGGER_NAME = "";
private static final ImmutableMap LOG_LEVEL_MAP =
ImmutableMap.builder()
.put(Level.SEVERE, BeamFnApi.LogEntry.Severity.Enum.ERROR)
.put(Level.WARNING, BeamFnApi.LogEntry.Severity.Enum.WARN)
.put(Level.INFO, BeamFnApi.LogEntry.Severity.Enum.INFO)
.put(Level.FINE, BeamFnApi.LogEntry.Severity.Enum.DEBUG)
.put(Level.FINEST, BeamFnApi.LogEntry.Severity.Enum.TRACE)
.build();
private static final ImmutableMap REVERSE_LOG_LEVEL_MAP =
ImmutableMap.builder()
.putAll(LOG_LEVEL_MAP.asMultimap().inverse().entries())
.build();
private static final Formatter DEFAULT_FORMATTER = new SimpleFormatter();
/**
* The number of log messages that will be buffered. Assuming log messages are at most 1 KiB, this
* represents a buffer of about 10 MiBs.
*/
private static final int MAX_BUFFERED_LOG_ENTRY_COUNT = 10_000;
private static final Object COMPLETED = new Object();
private final Endpoints.ApiServiceDescriptor apiServiceDescriptor;
private final StreamWriter streamWriter;
private final LogRecordHandler logRecordHandler;
/* We need to store a reference to the configured loggers so that they are not
* garbage collected. java.util.logging only has weak references to the loggers
* so if they are garbage collected, our hierarchical configuration will be lost. */
private final Collection configuredLoggers = new ArrayList<>();
private final BlockingQueue bufferedLogEntries =
new ArrayBlockingQueue<>(MAX_BUFFERED_LOG_ENTRY_COUNT);
/**
* Future that completes with the background thread consuming logs from bufferedLogEntries.
* Completes with COMPLETED or with exception.
*/
private final CompletableFuture> bufferedLogConsumer;
/**
* Safe object publishing is not required since we only care if the thread that set this field is
* equal to the thread also attempting to add a log entry.
*/
private @Nullable Thread logEntryHandlerThread = null;
public static BeamFnLoggingClient createAndStart(
PipelineOptions options,
Endpoints.ApiServiceDescriptor apiServiceDescriptor,
Function channelFactory) {
BeamFnLoggingClient client =
new BeamFnLoggingClient(
apiServiceDescriptor,
new StreamWriter(channelFactory.apply(apiServiceDescriptor)),
options.as(SdkHarnessOptions.class).getLogMdc(),
options.as(ExecutorOptions.class).getScheduledExecutorService(),
options.as(SdkHarnessOptions.class));
return client;
}
private BeamFnLoggingClient(
Endpoints.ApiServiceDescriptor apiServiceDescriptor,
StreamWriter streamWriter,
boolean logMdc,
ScheduledExecutorService executorService,
SdkHarnessOptions options) {
this.apiServiceDescriptor = apiServiceDescriptor;
this.streamWriter = streamWriter;
this.logRecordHandler = new LogRecordHandler(logMdc);
logRecordHandler.setLevel(Level.ALL);
logRecordHandler.setFormatter(DEFAULT_FORMATTER);
CompletableFuture