/*
* Copyright 2015-present Facebook, Inc.
*
* 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.facebook.buck.artifact_cache;
import com.facebook.buck.event.AbstractBuckEvent;
import com.facebook.buck.event.EventKey;
import com.facebook.buck.model.BuildId;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import java.util.Optional;
import org.immutables.value.Value;
/** Event produced for HttpArtifactCache operations containing different stats. */
public abstract class HttpArtifactCacheEvent extends ArtifactCacheEvent {
public static final ArtifactCacheEvent.CacheMode CACHE_MODE = ArtifactCacheEvent.CacheMode.http;
protected HttpArtifactCacheEvent(
EventKey eventKey,
ArtifactCacheEvent.Operation operation,
Optional<String> target,
ImmutableSet<RuleKey> ruleKeys,
ArtifactCacheEvent.InvocationType invocationType) {
super(eventKey, CACHE_MODE, operation, target, ruleKeys, invocationType);
}
public static Started newFetchStartedEvent(RuleKey ruleKey) {
return new Started(ArtifactCacheEvent.Operation.FETCH, ImmutableSet.of(ruleKey));
}
public static Started newStoreStartedEvent(Scheduled scheduled) {
return new Started(scheduled);
}
public static Scheduled newStoreScheduledEvent(
Optional<String> target, ImmutableSet<RuleKey> ruleKeys) {
return new Scheduled(ArtifactCacheEvent.Operation.STORE, target, ruleKeys);
}
public static Shutdown newShutdownEvent() {
return new Shutdown();
}
public static Finished.Builder newFinishedEventBuilder(Started event) {
return new Finished.Builder(event);
}
public static class Scheduled extends HttpArtifactCacheEvent {
public Scheduled(
ArtifactCacheEvent.Operation operation,
Optional<String> target,
ImmutableSet<RuleKey> ruleKeys) {
super(
EventKey.unique(),
operation,
target,
ruleKeys,
ArtifactCacheEvent.InvocationType.ASYNCHRONOUS);
}
@Override
public String getEventName() {
return "HttpArtifactCacheEvent.Scheduled";
}
}
public static class Started extends ArtifactCacheEvent.Started {
public Started(Scheduled event) {
super(
event.getEventKey(),
CACHE_MODE,
event.getOperation(),
event.getTarget(),
event.getRuleKeys(),
event.getInvocationType());
}
public Started(ArtifactCacheEvent.Operation operation, ImmutableSet<RuleKey> ruleKeys) {
super(
EventKey.unique(),
CACHE_MODE,
operation,
Optional.empty(),
ruleKeys,
ArtifactCacheEvent.InvocationType.SYNCHRONOUS);
}
@Override
public String getEventName() {
return "HttpArtifactCacheEvent.Started";
}
}
public static class Shutdown extends AbstractBuckEvent {
public Shutdown() {
super(EventKey.unique());
}
@Override
public String getEventName() {
return "HttpArtifactCacheEvent.Shutdown";
}
@Override
protected String getValueString() {
return getEventName() + getEventKey().toString();
}
}
public static class Finished extends ArtifactCacheEvent.Finished {
@JsonIgnore private final Started startedEvent;
@JsonIgnore private final Optional<HttpArtifactCacheEventFetchData> fetchData;
@JsonIgnore private final Optional<HttpArtifactCacheEventStoreData> storeData;
@JsonProperty("request_duration_millis")
private long requestDurationMillis;
public Finished(Started event, Optional<String> target, HttpArtifactCacheEventFetchData data) {
super(
event.getEventKey(),
CACHE_MODE,
event.getOperation(),
Preconditions.checkNotNull(target),
event.getRuleKeys(),
event.getInvocationType(),
data.getFetchResult());
this.startedEvent = event;
this.requestDurationMillis = -1;
this.fetchData = Optional.of(data);
this.storeData = Optional.empty();
}
public Finished(Started event, HttpArtifactCacheEventStoreData data) {
super(
event.getEventKey(),
CACHE_MODE,
event.getOperation(),
event.getTarget(),
event.getRuleKeys(),
event.getInvocationType(),
Optional.empty());
this.startedEvent = event;
this.requestDurationMillis = -1;
this.fetchData = Optional.empty();
this.storeData = Optional.of(data);
}
public long getRequestDurationMillis() {
return requestDurationMillis;
}
public HttpArtifactCacheEventFetchData getFetchData() {
Preconditions.checkState(fetchData.isPresent());
return fetchData.get();
}
public HttpArtifactCacheEventStoreData getStoreData() {
Preconditions.checkState(storeData.isPresent());
return storeData.get();
}
@Override
public void configure(
long timestampMillis,
long nanoTime,
long userThreadNanoTime,
long threadId,
BuildId buildId) {
super.configure(timestampMillis, nanoTime, userThreadNanoTime, threadId, buildId);
requestDurationMillis = timestampMillis - startedEvent.getTimestamp();
}
@Override
public String getEventName() {
return "HttpArtifactCacheEvent.Finished";
}
public static class Builder {
private final Started startedEvent;
private HttpArtifactCacheEventFetchData.Builder fetchDataBuilder;
private HttpArtifactCacheEventStoreData.Builder storeDataBuilder;
private Optional<String> target;
private Builder(Started event) {
this.startedEvent = event;
this.storeDataBuilder = HttpArtifactCacheEventStoreData.builder();
this.fetchDataBuilder = HttpArtifactCacheEventFetchData.builder();
this.target = Optional.empty();
}
public HttpArtifactCacheEvent.Finished build() {
if (startedEvent.getOperation() == Operation.FETCH) {
RuleKey requestsRuleKey =
Preconditions.checkNotNull(Iterables.getFirst(startedEvent.getRuleKeys(), null));
fetchDataBuilder.setRequestedRuleKey(requestsRuleKey);
return new HttpArtifactCacheEvent.Finished(
startedEvent, target, fetchDataBuilder.build());
} else {
storeDataBuilder.setRuleKeys(startedEvent.getRuleKeys());
return new HttpArtifactCacheEvent.Finished(startedEvent, storeDataBuilder.build());
}
}
public HttpArtifactCacheEventFetchData.Builder getFetchBuilder() {
return fetchDataBuilder;
}
public HttpArtifactCacheEventStoreData.Builder getStoreBuilder() {
return storeDataBuilder;
}
public Builder setFetchDataBuilder(HttpArtifactCacheEventFetchData.Builder fetchDataBuilder) {
this.fetchDataBuilder = fetchDataBuilder;
return this;
}
public Builder setTarget(Optional<String> target) {
this.target = target;
return this;
}
}
}
@Value.Immutable
@BuckStyleImmutable
interface AbstractHttpArtifactCacheEventFetchData {
Optional<Long> getResponseSizeBytes();
Optional<CacheResult> getFetchResult();
RuleKey getRequestedRuleKey();
Optional<String> getArtifactContentHash();
Optional<Long> getArtifactSizeBytes();
Optional<String> getErrorMessage();
ImmutableSet<RuleKey> getAssociatedRuleKeys();
}
@Value.Immutable
@BuckStyleImmutable
interface AbstractHttpArtifactCacheEventStoreData {
Optional<Long> getRequestSizeBytes();
Optional<Boolean> wasStoreSuccessful();
ImmutableSet<RuleKey> getRuleKeys();
Optional<String> getArtifactContentHash();
Optional<Long> getArtifactSizeBytes();
Optional<String> getErrorMessage();
}
}