/*
* Copyright 2015-2016 the original author or authors.
*
* 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 org.glowroot.common.live;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import org.immutables.value.Value;
import org.glowroot.wire.api.model.ProfileOuterClass.Profile;
import org.glowroot.wire.api.model.TraceOuterClass.Trace;
public interface LiveTraceRepository {
// null return value means trace not found
@Nullable
Trace.Header getHeader(String agentRollupId, String agentId, String traceId) throws Exception;
// null return value means trace not found or was found but had no entries
//
// SharedQueryTexts are returned with either fullTrace or
// truncatedText/truncatedEndText/fullTraceSha1
@Nullable
Entries getEntries(String agentRollupId, String agentId, String traceId) throws Exception;
// null return value means trace not found or was found but had no main thread profile
@Nullable
Profile getMainThreadProfile(String agentRollupId, String agentId, String traceId)
throws Exception;
// null return value means trace not found or was found but had no aux thread profile
@Nullable
Profile getAuxThreadProfile(String agentRollupId, String agentId, String traceId)
throws Exception;
// null return value means trace not found
//
// since this is only used by export, SharedQueryTexts are always returned with fullTrace
// (never with truncatedText/truncatedEndText/fullTraceSha1)
@Nullable
Trace getFullTrace(String agentRollupId, String agentId, String traceId) throws Exception;
int getMatchingTraceCount(String transactionType, @Nullable String transactionName);
List<TracePoint> getMatchingActiveTracePoints(TraceKind traceKind, String transactionType,
@Nullable String transactionName, TracePointFilter filter, int limit, long captureTime,
long captureTick);
List<TracePoint> getMatchingPendingPoints(TraceKind traceKind, String transactionType,
@Nullable String transactionName, TracePointFilter filter, long captureTime);
@Value.Immutable
public interface Entries {
List<Trace.Entry> entries();
List<Trace.SharedQueryText> sharedQueryTexts();
}
@Value.Immutable
abstract class TracePointFilter {
public abstract @Nullable StringComparator headlineComparator();
public abstract @Nullable String headline();
public abstract @Nullable StringComparator errorMessageComparator();
public abstract @Nullable String errorMessage();
public abstract @Nullable StringComparator userComparator();
public abstract @Nullable String user();
public abstract @Nullable String attributeName();
public abstract @Nullable StringComparator attributeValueComparator();
public abstract @Nullable String attributeValue();
public boolean matchesHeadline(String headline) {
return matchesUsingStringComparator(headline, headline(), headlineComparator());
}
public boolean matchesError(String errorMessage) {
return matchesUsingStringComparator(errorMessage, errorMessage(),
errorMessageComparator());
}
public boolean matchesUser(String user) {
return matchesUsingStringComparator(user, user(), userComparator());
}
public boolean matchesAttributes(Map<String, ? extends Collection<String>> attributes) {
if (Strings.isNullOrEmpty(attributeName()) && (attributeValueComparator() == null
|| Strings.isNullOrEmpty(attributeValue()))) {
// no custom attribute filter
return true;
}
for (Entry<String, ? extends Collection<String>> entry : attributes.entrySet()) {
String attributeName = entry.getKey();
if (!matchesUsingStringComparator(attributeName, attributeName(),
StringComparator.EQUALS)) {
// name doesn't match, no need to test values
continue;
}
for (String attributeValue : entry.getValue()) {
if (matchesUsingStringComparator(attributeValue, attributeValue(),
attributeValueComparator())) {
// found matching name and value
return true;
}
}
}
return false;
}
private boolean matchesUsingStringComparator(String text, @Nullable String filterText,
@Nullable StringComparator filterComparator) throws AssertionError {
if (filterComparator == null || Strings.isNullOrEmpty(filterText)) {
return true;
}
return filterComparator.matches(text, filterText);
}
}
@Value.Immutable
interface TracePoint {
String agentId();
String traceId();
long captureTime();
long durationNanos();
boolean partial();
boolean error();
}
enum TraceKind {
SLOW, ERROR;
}
enum Existence {
YES, NO, EXPIRED;
}
class LiveTraceRepositoryNop implements LiveTraceRepository {
@Override
public @Nullable Trace.Header getHeader(String agentRollupId, String agentId,
String traceId) {
return null;
}
@Override
public @Nullable Entries getEntries(String agentRollupId, String agentId, String traceId) {
return null;
}
@Override
public @Nullable Profile getMainThreadProfile(String agentRollupId, String agentId,
String traceId) {
return null;
}
@Override
public @Nullable Profile getAuxThreadProfile(String agentRollupId, String agentId,
String traceId) {
return null;
}
@Override
public @Nullable Trace getFullTrace(String agentRollupId, String agentId, String traceId) {
return null;
}
@Override
public int getMatchingTraceCount(String transactionType, @Nullable String transactionName) {
return 0;
}
@Override
public List<TracePoint> getMatchingActiveTracePoints(TraceKind traceKind,
String transactionType, @Nullable String transactionName, TracePointFilter filter,
int limit, long captureTime, long captureTick) {
return ImmutableList.of();
}
@Override
public List<TracePoint> getMatchingPendingPoints(TraceKind traceKind,
String transactionType, @Nullable String transactionName, TracePointFilter filter,
long captureTime) {
return ImmutableList.of();
}
}
}