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

org.glowroot.local.ui.TraceCommonService Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2012-2015 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.local.ui;

import java.io.IOException;
import java.sql.SQLException;

import javax.annotation.Nullable;

import org.glowroot.shaded.fasterxml.jackson.databind.ObjectMapper;
import org.glowroot.shaded.google.common.base.Ticker;
import org.glowroot.shaded.google.common.collect.Iterables;
import org.glowroot.shaded.google.common.io.CharSource;
import org.immutables.value.Value;

import org.glowroot.collector.EntriesChunkSourceCreator;
import org.glowroot.collector.ProfileChunkSourceCreator;
import org.glowroot.collector.Trace;
import org.glowroot.collector.TraceCreator;
import org.glowroot.common.ChunkSource;
import org.glowroot.common.Clock;
import org.glowroot.common.ObjectMappers;
import org.glowroot.local.store.TraceDao;
import org.glowroot.transaction.TransactionCollector;
import org.glowroot.transaction.TransactionRegistry;
import org.glowroot.transaction.model.Transaction;

class TraceCommonService {

    private static final ObjectMapper mapper = ObjectMappers.create();

    private final TraceDao traceDao;
    private final TransactionRegistry transactionRegistry;
    private final TransactionCollector transactionCollector;
    private final Clock clock;
    private final Ticker ticker;

    TraceCommonService(TraceDao traceDao, TransactionRegistry transactionRegistry,
            TransactionCollector transactionCollectorImpl, Clock clock, Ticker ticker) {
        this.traceDao = traceDao;
        this.transactionRegistry = transactionRegistry;
        this.transactionCollector = transactionCollectorImpl;
        this.clock = clock;
        this.ticker = ticker;
    }

    @Nullable
    Trace getTrace(String traceId) throws Exception {
        // check active traces first, then pending traces, and finally stored traces
        // to make sure that the trace is not missed if it is in transition between these states
        for (Transaction transaction : Iterables.concat(transactionRegistry.getTransactions(),
                transactionCollector.getPendingTransactions())) {
            if (transaction.getId().equals(traceId)) {
                return createTrace(transaction);
            }
        }
        return traceDao.readTrace(traceId);
    }

    // overwritten entries will return {"overwritten":true}
    // expired (not found) trace will return {"expired":true}
    @Nullable
    ChunkSource getEntries(String traceId) throws SQLException {
        // check active traces first, then pending traces, and finally stored traces
        // to make sure that the trace is not missed if it is in transition between these states
        for (Transaction transaction : Iterables.concat(transactionRegistry.getTransactions(),
                transactionCollector.getPendingTransactions())) {
            if (transaction.getId().equals(traceId)) {
                return createEntries(transaction);
            }
        }
        return toNullableChunkSource(traceDao.readEntries(traceId));
    }

    // overwritten profile will return {"overwritten":true}
    // expired (not found) trace will return {"expired":true}
    @Nullable
    ChunkSource getProfile(String traceId) throws Exception {
        // check active traces first, then pending traces, and finally stored traces
        // to make sure that the trace is not missed if it is in transition between these states
        for (Transaction transaction : Iterables.concat(transactionRegistry.getTransactions(),
                transactionCollector.getPendingTransactions())) {
            if (transaction.getId().equals(traceId)) {
                return createProfile(transaction);
            }
        }
        return toNullableChunkSource(traceDao.readProfile(traceId));
    }

    @Nullable
    TraceExport getExport(String traceId) throws Exception {
        // check active traces first, then pending traces, and finally stored traces
        // to make sure that the trace is not missed if it is in transition between these states
        for (Transaction transaction : Iterables.concat(transactionRegistry.getTransactions(),
                transactionCollector.getPendingTransactions())) {
            if (transaction.getId().equals(traceId)) {
                Trace trace = createTrace(transaction);
                return TraceExport.builder()
                        .trace(trace)
                        .traceJson(mapper.writeValueAsString(trace))
                        .entries(createEntries(transaction))
                        .profile(createProfile(transaction))
                        .build();
            }
        }
        Trace trace = traceDao.readTrace(traceId);
        if (trace == null) {
            return null;
        }
        return TraceExport.builder()
                .trace(trace)
                .traceJson(mapper.writeValueAsString(trace))
                .entries(toNullableChunkSource(traceDao.readEntries(traceId)))
                .profile(toNullableChunkSource(traceDao.readProfile(traceId)))
                .build();
    }

    private Trace createTrace(Transaction transaction) throws IOException {
        if (transaction.isCompleted()) {
            return TraceCreator.createCompletedTrace(transaction);
        } else {
            return TraceCreator.createActiveTrace(transaction, clock.currentTimeMillis(),
                    ticker.read());
        }
    }

    private @Nullable ChunkSource createEntries(Transaction active) {
        return EntriesChunkSourceCreator.createEntriesChunkSource(active.getEntries(),
                active.getStartTick(), ticker.read());
    }

    private @Nullable ChunkSource createProfile(Transaction active) throws IOException {
        return ProfileChunkSourceCreator.createProfileChunkSource(active.getProfile());
    }

    private @Nullable ChunkSource toNullableChunkSource(@Nullable CharSource charSource) {
        if (charSource == null) {
            return null;
        }
        return ChunkSource.from(charSource);
    }

    @Value.Immutable
    static abstract class TraceExportBase {

        abstract Trace trace();
        abstract String traceJson();
        abstract @Nullable ChunkSource entries();
        abstract @Nullable ChunkSource profile();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy