All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.cloud.logging.LoggingImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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 com.google.cloud.logging;

import static com.google.api.client.util.Preconditions.checkArgument;
import static com.google.cloud.logging.Logging.EntryListOption.OptionType.FILTER;
import static com.google.cloud.logging.Logging.EntryListOption.OptionType.ORDER_BY;
import static com.google.cloud.logging.Logging.ListOption.OptionType.PAGE_SIZE;
import static com.google.cloud.logging.Logging.ListOption.OptionType.PAGE_TOKEN;
import static com.google.cloud.logging.Logging.WriteOption.OptionType.LABELS;
import static com.google.cloud.logging.Logging.WriteOption.OptionType.LOG_NAME;
import static com.google.cloud.logging.Logging.WriteOption.OptionType.RESOURCE;

import com.google.cloud.AsyncPage;
import com.google.cloud.AsyncPageImpl;
import com.google.cloud.BaseService;
import com.google.cloud.MonitoredResource;
import com.google.cloud.MonitoredResourceDescriptor;
import com.google.cloud.Page;
import com.google.cloud.PageImpl;
import com.google.cloud.logging.spi.LoggingRpc;
import com.google.cloud.logging.spi.v2.ConfigServiceV2Api;
import com.google.cloud.logging.spi.v2.LoggingServiceV2Api;
import com.google.cloud.logging.spi.v2.MetricsServiceV2Api;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.logging.v2.CreateLogMetricRequest;
import com.google.logging.v2.CreateSinkRequest;
import com.google.logging.v2.DeleteLogMetricRequest;
import com.google.logging.v2.DeleteLogRequest;
import com.google.logging.v2.DeleteSinkRequest;
import com.google.logging.v2.GetLogMetricRequest;
import com.google.logging.v2.GetSinkRequest;
import com.google.logging.v2.ListLogEntriesRequest;
import com.google.logging.v2.ListLogEntriesResponse;
import com.google.logging.v2.ListLogMetricsRequest;
import com.google.logging.v2.ListLogMetricsResponse;
import com.google.logging.v2.ListMonitoredResourceDescriptorsRequest;
import com.google.logging.v2.ListMonitoredResourceDescriptorsResponse;
import com.google.logging.v2.ListSinksRequest;
import com.google.logging.v2.ListSinksResponse;
import com.google.logging.v2.UpdateLogMetricRequest;
import com.google.logging.v2.UpdateSinkRequest;
import com.google.logging.v2.WriteLogEntriesRequest;
import com.google.logging.v2.WriteLogEntriesResponse;
import com.google.protobuf.Empty;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

class LoggingImpl extends BaseService implements Logging {

  private final LoggingRpc rpc;
  private boolean closed;

  private static final Function EMPTY_TO_BOOLEAN_FUNCTION =
      new Function() {
        @Override
        public Boolean apply(Empty input) {
          return input != null;
        }
      };
  private static final Function WRITE_RESPONSE_TO_VOID_FUNCTION =
      new Function() {
        @Override
        public Void apply(WriteLogEntriesResponse input) {
          return null;
        }
      };

  LoggingImpl(LoggingOptions options) {
    super(options);
    rpc = options.rpc();
  }

  private static  V get(Future future) {
    try {
      return Uninterruptibles.getUninterruptibly(future);
    } catch (ExecutionException ex) {
      throw Throwables.propagate(ex.getCause());
    }
  }

  private static  Future transform(Future future,
      Function function) {
    if (future instanceof ListenableFuture) {
      return Futures.transform((ListenableFuture) future, function);
    }
    return Futures.lazyTransform(future, function);
  }

  private abstract static class BasePageFetcher implements AsyncPageImpl.NextPageFetcher {

    private static final long serialVersionUID = 5095123855547444030L;

    private final LoggingOptions serviceOptions;
    private final Map requestOptions;

    private BasePageFetcher(LoggingOptions serviceOptions, String cursor,
        Map requestOptions) {
      this.serviceOptions = serviceOptions;
      this.requestOptions =
          PageImpl.nextRequestOptions(PAGE_TOKEN, cursor, requestOptions);
    }

    LoggingOptions serviceOptions() {
      return serviceOptions;
    }

    Map requestOptions() {
      return requestOptions;
    }
  }

  private static class SinkPageFetcher extends BasePageFetcher {

    private static final long serialVersionUID = 4879364260060886875L;

    SinkPageFetcher(LoggingOptions serviceOptions, String cursor,
        Map requestOptions) {
      super(serviceOptions, cursor, requestOptions);
    }

    @Override
    public Future> nextPage() {
      return listSinksAsync(serviceOptions(), requestOptions());
    }
  }

  private static class MonitoredResourceDescriptorPageFetcher
      extends BasePageFetcher {

    private static final long serialVersionUID = -2346495771766629195L;

    MonitoredResourceDescriptorPageFetcher(LoggingOptions serviceOptions, String cursor,
        Map requestOptions) {
      super(serviceOptions, cursor, requestOptions);
    }

    @Override
    public Future> nextPage() {
      return listMonitoredResourceDescriptorsAsync(serviceOptions(), requestOptions());
    }
  }

  private static class MetricPageFetcher extends BasePageFetcher {

    private static final long serialVersionUID = -316783549651771553L;

    MetricPageFetcher(LoggingOptions serviceOptions, String cursor,
        Map requestOptions) {
      super(serviceOptions, cursor, requestOptions);
    }

    @Override
    public Future> nextPage() {
      return listMetricsAsync(serviceOptions(), requestOptions());
    }
  }

  private static class LogEntryPageFetcher extends BasePageFetcher {

    private static final long serialVersionUID = 4001239712280747734L;

    LogEntryPageFetcher(LoggingOptions serviceOptions, String cursor,
        Map requestOptions) {
      super(serviceOptions, cursor, requestOptions);
    }

    @Override
    public Future> nextPage() {
      return listLogEntriesAsync(serviceOptions(), requestOptions());
    }
  }

  @Override
  public Sink create(SinkInfo sink) {
    return get(createAsync(sink));
  }

  @Override
  public Future createAsync(SinkInfo sink) {
    CreateSinkRequest request = CreateSinkRequest.newBuilder()
        .setParent(ConfigServiceV2Api.formatParentName(options().projectId()))
        .setSink(sink.toPb(options().projectId()))
        .build();
    return transform(rpc.create(request), Sink.fromPbFunction(this));
  }

  @Override
  public Sink update(SinkInfo sink) {
    return get(updateAsync(sink));
  }

  @Override
  public Future updateAsync(SinkInfo sink) {
    UpdateSinkRequest request = UpdateSinkRequest.newBuilder()
        .setSinkName(ConfigServiceV2Api.formatSinkName(options().projectId(), sink.name()))
        .setSink(sink.toPb(options().projectId()))
        .build();
    return transform(rpc.update(request), Sink.fromPbFunction(this));
  }

  @Override
  public Sink getSink(String sink) {
    return get(getSinkAsync(sink));
  }

  @Override
  public Future getSinkAsync(String sink) {
    GetSinkRequest request = GetSinkRequest.newBuilder()
        .setSinkName(ConfigServiceV2Api.formatSinkName(options().projectId(), sink))
        .build();
    return transform(rpc.get(request), Sink.fromPbFunction(this));
  }

  private static ListSinksRequest listSinksRequest(LoggingOptions serviceOptions,
      Map options) {
    ListSinksRequest.Builder builder = ListSinksRequest.newBuilder();
    builder.setParent(ConfigServiceV2Api.formatParentName(serviceOptions.projectId()));
    Integer pageSize = PAGE_SIZE.get(options);
    String pageToken = PAGE_TOKEN.get(options);
    if (pageSize != null) {
      builder.setPageSize(pageSize);
    }
    if (pageToken != null) {
      builder.setPageToken(pageToken);
    }
    return builder.build();
  }

  private static Future> listSinksAsync(final LoggingOptions serviceOptions,
      final Map options) {
    final ListSinksRequest request = listSinksRequest(serviceOptions, options);
    Future list = serviceOptions.rpc().list(request);
    return transform(list, new Function>() {
      @Override
      public AsyncPage apply(ListSinksResponse listSinksResponse) {
        List sinks = listSinksResponse.getSinksList() == null ? ImmutableList.of()
            : Lists.transform(listSinksResponse.getSinksList(),
            Sink.fromPbFunction(serviceOptions.service()));
        String cursor = listSinksResponse.getNextPageToken().equals("") ? null
            : listSinksResponse.getNextPageToken();
        return new AsyncPageImpl<>(
            new SinkPageFetcher(serviceOptions, cursor, options), cursor, sinks);
      }
    });
  }

  @Override
  public Page listSinks(ListOption... options) {
    return get(listSinksAsync(options));
  }

  @Override
  public Future> listSinksAsync(ListOption... options) {
    return listSinksAsync(options(), optionMap(options));
  }

  @Override
  public boolean deleteSink(String sink) {
    return get(deleteSinkAsync(sink));
  }

  @Override
  public Future deleteSinkAsync(String sink) {
    DeleteSinkRequest request = DeleteSinkRequest.newBuilder()
        .setSinkName(ConfigServiceV2Api.formatSinkName(options().projectId(), sink))
        .build();
    return transform(rpc.delete(request), EMPTY_TO_BOOLEAN_FUNCTION);
  }

  public boolean deleteLog(String log) {
    return get(deleteLogAsync(log));
  }

  public Future deleteLogAsync(String log) {
    DeleteLogRequest request = DeleteLogRequest.newBuilder()
        .setLogName(LoggingServiceV2Api.formatLogName(options().projectId(), log))
        .build();
    return transform(rpc.delete(request), EMPTY_TO_BOOLEAN_FUNCTION);
  }

  private static ListMonitoredResourceDescriptorsRequest listMonitoredResourceDescriptorsRequest(
      Map options) {
    ListMonitoredResourceDescriptorsRequest.Builder builder =
        ListMonitoredResourceDescriptorsRequest.newBuilder();
    Integer pageSize = PAGE_SIZE.get(options);
    String pageToken = PAGE_TOKEN.get(options);
    if (pageSize != null) {
      builder.setPageSize(pageSize);
    }
    if (pageToken != null) {
      builder.setPageToken(pageToken);
    }
    return builder.build();
  }

  private static Future>
      listMonitoredResourceDescriptorsAsync(final LoggingOptions serviceOptions,
          final Map options) {
    final ListMonitoredResourceDescriptorsRequest request =
        listMonitoredResourceDescriptorsRequest(options);
    Future list = serviceOptions.rpc().list(request);
    return transform(list, new Function>() {
          @Override
          public AsyncPage apply(
              ListMonitoredResourceDescriptorsResponse listDescriptorsResponse) {
            List descriptors =
                listDescriptorsResponse.getResourceDescriptorsList() == null
                    ? ImmutableList.of()
                    : Lists.transform(listDescriptorsResponse.getResourceDescriptorsList(),
                MonitoredResourceDescriptor.FROM_PB_FUNCTION);
            String cursor = listDescriptorsResponse.getNextPageToken().equals("") ? null
                : listDescriptorsResponse.getNextPageToken();
            return new AsyncPageImpl<>(
                new MonitoredResourceDescriptorPageFetcher(serviceOptions, cursor, options), cursor,
                descriptors);
          }
        });
  }

  public Page listMonitoredResourceDescriptors(ListOption... options) {
    return get(listMonitoredResourceDescriptorsAsync(options));
  }

  public Future> listMonitoredResourceDescriptorsAsync(
      ListOption... options) {
    return listMonitoredResourceDescriptorsAsync(options(), optionMap(options));
  }

  @Override
  public Metric create(MetricInfo metric) {
    return get(createAsync(metric));
  }

  @Override
  public Future createAsync(MetricInfo metric) {
    CreateLogMetricRequest request = CreateLogMetricRequest.newBuilder()
        .setParent(MetricsServiceV2Api.formatParentName(options().projectId()))
        .setMetric(metric.toPb())
        .build();
    return transform(rpc.create(request), Metric.fromPbFunction(this));
  }

  @Override
  public Metric update(MetricInfo metric) {
    return get(updateAsync(metric));
  }

  @Override
  public Future updateAsync(MetricInfo metric) {
    UpdateLogMetricRequest request = UpdateLogMetricRequest.newBuilder()
        .setMetricName(MetricsServiceV2Api.formatMetricName(options().projectId(), metric.name()))
        .setMetric(metric.toPb())
        .build();
    return transform(rpc.update(request), Metric.fromPbFunction(this));
  }

  @Override
  public Metric getMetric(String metric) {
    return get(getMetricAsync(metric));
  }

  @Override
  public Future getMetricAsync(String metric) {
    GetLogMetricRequest request = GetLogMetricRequest.newBuilder()
        .setMetricName(MetricsServiceV2Api.formatMetricName(options().projectId(), metric))
        .build();
    return transform(rpc.get(request), Metric.fromPbFunction(this));
  }

  private static ListLogMetricsRequest listMetricsRequest(LoggingOptions serviceOptions,
      Map options) {
    ListLogMetricsRequest.Builder builder = ListLogMetricsRequest.newBuilder();
    builder.setParent(MetricsServiceV2Api.formatParentName(serviceOptions.projectId()));
    Integer pageSize = PAGE_SIZE.get(options);
    String pageToken = PAGE_TOKEN.get(options);
    if (pageSize != null) {
      builder.setPageSize(pageSize);
    }
    if (pageToken != null) {
      builder.setPageToken(pageToken);
    }
    return builder.build();
  }

  private static Future> listMetricsAsync(final LoggingOptions serviceOptions,
      final Map options) {
    final ListLogMetricsRequest request = listMetricsRequest(serviceOptions, options);
    Future list = serviceOptions.rpc().list(request);
    return transform(list, new Function>() {
      @Override
      public AsyncPage apply(ListLogMetricsResponse listMetricsResponse) {
        List metrics = listMetricsResponse.getMetricsList() == null
            ? ImmutableList.of() : Lists.transform(listMetricsResponse.getMetricsList(),
                Metric.fromPbFunction(serviceOptions.service()));
        String cursor = listMetricsResponse.getNextPageToken().equals("") ? null
            : listMetricsResponse.getNextPageToken();
        return new AsyncPageImpl<>(new MetricPageFetcher(serviceOptions, cursor, options), cursor,
            metrics);
      }
    });
  }

  @Override
  public Page listMetrics(ListOption... options) {
    return get(listMetricsAsync(options));
  }

  @Override
  public Future> listMetricsAsync(ListOption... options) {
    return listMetricsAsync(options(), optionMap(options));
  }

  @Override
  public boolean deleteMetric(String metric) {
    return get(deleteMetricAsync(metric));
  }

  @Override
  public Future deleteMetricAsync(String metric) {
    DeleteLogMetricRequest request = DeleteLogMetricRequest.newBuilder()
        .setMetricName(MetricsServiceV2Api.formatMetricName(options().projectId(), metric))
        .build();
    return transform(rpc.delete(request), EMPTY_TO_BOOLEAN_FUNCTION);
  }

  private static WriteLogEntriesRequest writeLogEntriesRequest(LoggingOptions serviceOptions,
      Iterable logEntries, Map options) {
    String projectId = serviceOptions.projectId();
    WriteLogEntriesRequest.Builder builder = WriteLogEntriesRequest.newBuilder();
    String logName = LOG_NAME.get(options);
    if (logName != null) {
      builder.setLogName(LoggingServiceV2Api.formatLogName(projectId, logName));
    }
    MonitoredResource resource = RESOURCE.get(options);
    if (resource != null) {
      builder.setResource(resource.toPb());
    }
    Map labels = LABELS.get(options);
    if (labels != null) {
      builder.putAllLabels(labels);
    }
    builder.addAllEntries(Iterables.transform(logEntries, LogEntry.toPbFunction(projectId)));
    return builder.build();
  }

  public void write(Iterable logEntries, WriteOption... options) {
    get(writeAsync(logEntries, options));
  }

  public Future writeAsync(Iterable logEntries, WriteOption... options) {
    return transform(rpc.write(writeLogEntriesRequest(options(), logEntries, optionMap(options))),
        WRITE_RESPONSE_TO_VOID_FUNCTION);
  }

  private static ListLogEntriesRequest listLogEntriesRequest(LoggingOptions serviceOptions,
      Map options) {
    ListLogEntriesRequest.Builder builder = ListLogEntriesRequest.newBuilder();
    builder.addProjectIds(serviceOptions.projectId());
    Integer pageSize = PAGE_SIZE.get(options);
    if (pageSize != null) {
      builder.setPageSize(pageSize);
    }
    String pageToken = PAGE_TOKEN.get(options);
    if (pageToken != null) {
      builder.setPageToken(pageToken);
    }
    String orderBy = ORDER_BY.get(options);
    if (orderBy != null) {
      builder.setOrderBy(orderBy);
    }
    String filter = FILTER.get(options);
    if (filter != null) {
      builder.setFilter(filter);
    }
    return builder.build();
  }

  private static Future> listLogEntriesAsync(
      final LoggingOptions serviceOptions, final Map options) {
    final ListLogEntriesRequest request = listLogEntriesRequest(serviceOptions, options);
    Future list = serviceOptions.rpc().list(request);
    return transform(list, new Function>() {
      @Override
      public AsyncPage apply(ListLogEntriesResponse listLogEntrysResponse) {
        List entries = listLogEntrysResponse.getEntriesList() == null
            ? ImmutableList.of() : Lists.transform(listLogEntrysResponse.getEntriesList(),
            LogEntry.FROM_PB_FUNCTION);
        String cursor = listLogEntrysResponse.getNextPageToken().equals("") ? null
            : listLogEntrysResponse.getNextPageToken();
        return new AsyncPageImpl<>(new LogEntryPageFetcher(serviceOptions, cursor, options), cursor,
            entries);
      }
    });
  }

  @Override
  public Page listLogEntries(EntryListOption... options) {
    return get(listLogEntriesAsync(options));
  }

  @Override
  public Future> listLogEntriesAsync(EntryListOption... options) {
    return listLogEntriesAsync(options(), optionMap(options));
  }

  @Override
  public void close() throws Exception {
    if (closed) {
      return;
    }
    closed = true;
    rpc.close();
  }

  static  Map optionMap(Option... options) {
    Map optionMap = Maps.newHashMap();
    for (Option option : options) {
      Object prev = optionMap.put(option.optionType(), option.value());
      checkArgument(prev == null, "Duplicate option %s", option);
    }
    return optionMap;
  }
}