/* * Copyright (c) 2015 Spotify AB. * * 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 com.spotify.heroic.metric.bigtable; import static java.util.Optional.empty; import static java.util.Optional.of; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.spotify.heroic.ExtraParameters; import com.spotify.heroic.common.DynamicModuleId; import com.spotify.heroic.common.Groups; import com.spotify.heroic.common.ModuleId; import com.spotify.heroic.dagger.PrimaryComponent; import com.spotify.heroic.lifecycle.LifeCycle; import com.spotify.heroic.lifecycle.LifeCycleManager; import com.spotify.heroic.metric.MetricModule; import com.spotify.heroic.metric.bigtable.api.FakeBigtableConnection; import com.spotify.heroic.metric.bigtable.credentials.ComputeEngineCredentialsBuilder; import dagger.Component; import dagger.Lazy; import dagger.Module; import dagger.Provides; import eu.toolchain.async.AsyncFramework; import eu.toolchain.async.AsyncFuture; import eu.toolchain.async.Managed; import eu.toolchain.async.ManagedSetup; import eu.toolchain.serializer.Serializer; import java.util.Optional; import java.util.concurrent.ExecutorService; import javax.inject.Named; import lombok.Data; @Data @ModuleId("bigtable") public final class BigtableMetricModule implements MetricModule, DynamicModuleId { public static final String BIGTABLE_CONFIGURE_PARAM = "bigtable.configure"; public static final String DEFAULT_GROUP = "bigtable"; public static final String DEFAULT_INSTANCE = "heroic"; public static final String DEFAULT_TABLE = "metrics"; public static final CredentialsBuilder DEFAULT_CREDENTIALS = new ComputeEngineCredentialsBuilder(); public static final boolean DEFAULT_CONFIGURE = false; public static final boolean DEFAULT_DISABLE_BULK_MUTATIONS = false; public static final int DEFAULT_FLUSH_INTERVAL_SECONDS = 2; public static final boolean DEFAULT_FAKE = false; private final Optional<String> id; private final Groups groups; private final String project; private final String instance; private final String table; private final CredentialsBuilder credentials; private final boolean configure; private final boolean disableBulkMutations; private final int flushIntervalSeconds; private final Optional<Integer> batchSize; private final boolean fake; @JsonCreator public BigtableMetricModule( @JsonProperty("id") Optional<String> id, @JsonProperty("groups") Optional<Groups> groups, @JsonProperty("project") Optional<String> project, @JsonProperty("instance") Optional<String> instance, @JsonProperty("table") Optional<String> table, @JsonProperty("credentials") Optional<CredentialsBuilder> credentials, @JsonProperty("configure") Optional<Boolean> configure, @JsonProperty("disableBulkMutations") Optional<Boolean> disableBulkMutations, @JsonProperty("flushIntervalSeconds") Optional<Integer> flushIntervalSeconds, @JsonProperty("batchSize") Optional<Integer> batchSize, @JsonProperty("fake") Optional<Boolean> fake ) { this.id = id; this.groups = groups.orElseGet(Groups::empty).or(DEFAULT_GROUP); this.project = project.orElseThrow(() -> new NullPointerException("project")); this.instance = instance.orElse(DEFAULT_INSTANCE); this.table = table.orElse(DEFAULT_TABLE); this.credentials = credentials.orElse(DEFAULT_CREDENTIALS); this.configure = configure.orElse(DEFAULT_CONFIGURE); this.disableBulkMutations = disableBulkMutations.orElse(DEFAULT_DISABLE_BULK_MUTATIONS); this.flushIntervalSeconds = flushIntervalSeconds.orElse(DEFAULT_FLUSH_INTERVAL_SECONDS); this.batchSize = batchSize; this.fake = fake.orElse(DEFAULT_FAKE); } @Override public Exposed module(PrimaryComponent primary, Depends depends, String id) { return DaggerBigtableMetricModule_C .builder() .primaryComponent(primary) .depends(depends) .m(new M()) .build(); } @BigtableScope @Component(modules = M.class, dependencies = {PrimaryComponent.class, Depends.class}) interface C extends Exposed { @Override BigtableBackend backend(); @Override LifeCycle life(); } @Module class M { @Provides @BigtableScope public Managed<BigtableConnection> connection( final AsyncFramework async, final ExecutorService executorService, final Lazy<FakeBigtableConnection> fakeBigtableConnection ) { if (fake) { return async.managed(new ManagedSetup<BigtableConnection>() { @Override public AsyncFuture<BigtableConnection> construct() throws Exception { return async.resolved(fakeBigtableConnection.get()); } @Override public AsyncFuture<Void> destruct(final BigtableConnection value) throws Exception { return value.close(); } }); } return async.managed(new ManagedSetup<BigtableConnection>() { @Override public AsyncFuture<BigtableConnection> construct() throws Exception { return async.call( new BigtableConnectionBuilder(project, instance, credentials, async, executorService, disableBulkMutations, flushIntervalSeconds, batchSize)); } @Override public AsyncFuture<Void> destruct(final BigtableConnection value) throws Exception { return async.call(() -> { value.close(); return null; }); } }); } @Provides @BigtableScope @Named("table") public String table() { return table; } @Provides @BigtableScope @Named("configure") public boolean configure(final ExtraParameters params) { return params.contains(ExtraParameters.CONFIGURE) || params.contains(BIGTABLE_CONFIGURE_PARAM) || configure; } @Provides @BigtableScope public Serializer<RowKey> rowKeySerializer() { return new MetricsRowKeySerializer(); } @Provides @BigtableScope public Groups groups() { return groups; } @Provides @BigtableScope public LifeCycle life(LifeCycleManager manager, BigtableBackend backend) { return manager.build(backend); } } @Override public Optional<String> id() { return id; } public static Builder builder() { return new Builder(); } public static class Builder { private Optional<String> id = empty(); private Optional<Groups> groups = empty(); private Optional<String> project = empty(); private Optional<String> instance = empty(); private Optional<String> table = empty(); private Optional<CredentialsBuilder> credentials = empty(); private Optional<Boolean> configure = empty(); private Optional<Boolean> disableBulkMutations = empty(); private Optional<Integer> flushIntervalSeconds = empty(); private Optional<Integer> batchSize = empty(); private Optional<Boolean> fake = empty(); public Builder id(String id) { this.id = of(id); return this; } public Builder groups(Groups groups) { this.groups = of(groups); return this; } public Builder project(String project) { this.project = of(project); return this; } public Builder instance(String instance) { this.instance = of(instance); return this; } public Builder credentials(CredentialsBuilder credentials) { this.credentials = of(credentials); return this; } public Builder configure(boolean configure) { this.configure = of(configure); return this; } public Builder disableBulkMutations(boolean disableBulkMutations) { this.disableBulkMutations = of(disableBulkMutations); return this; } public Builder flushIntervalSeconds(int flushIntervalSeconds) { this.flushIntervalSeconds = of(flushIntervalSeconds); return this; } public Builder batchSize(int batchSize) { this.batchSize = of(batchSize); return this; } public Builder table(final String table) { this.table = of(table); return this; } public Builder fake(final boolean fake) { this.fake = of(fake); return this; } public BigtableMetricModule build() { return new BigtableMetricModule(id, groups, project, instance, table, credentials, configure, disableBulkMutations, flushIntervalSeconds, batchSize, fake); } } }