001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.fcrepo.kernel.impl;
020
021import io.micrometer.core.instrument.Metrics;
022import io.micrometer.core.instrument.Timer;
023import org.fcrepo.common.metrics.MetricsHelper;
024import org.fcrepo.kernel.api.ContainmentIndex;
025import org.fcrepo.kernel.api.Transaction;
026import org.fcrepo.kernel.api.identifiers.FedoraId;
027import org.springframework.beans.factory.annotation.Autowired;
028import org.springframework.beans.factory.annotation.Qualifier;
029import org.springframework.stereotype.Component;
030
031import java.time.Instant;
032import java.util.stream.Stream;
033
034/**
035 * ContainmentIndex wrapper for adding metrics
036 *
037 * @author pwinckles
038 */
039@Component("containmentIndex")
040public class ContainmentIndexMetrics implements ContainmentIndex {
041
042    private static final String METRIC_NAME = "fcrepo.db";
043    private static final String DB = "db";
044    private static final String CONTAINMENT = "containment";
045    private static final String OPERATION = "operation";
046
047    private static final Timer getContainsTimer = Metrics.timer(METRIC_NAME,
048            DB, CONTAINMENT, OPERATION, "getContains");
049    private static final Timer getContainsDeletedTimer = Metrics.timer(METRIC_NAME,
050            DB, CONTAINMENT, OPERATION, "getContainsDeleted");
051    private static final Timer getContainsByTimer = Metrics.timer(METRIC_NAME,
052            DB, CONTAINMENT, OPERATION, "getContainsBy");
053    private static final Timer removeContainedByTimer = Metrics.timer(METRIC_NAME,
054            DB, CONTAINMENT, OPERATION, "removeContainedBy");
055    private static final Timer removeResourceTimer = Metrics.timer(METRIC_NAME,
056            DB, CONTAINMENT, OPERATION, "removeResource");
057    private static final Timer purgeResourceTimer = Metrics.timer(METRIC_NAME,
058            DB, CONTAINMENT, OPERATION, "purgeResource");
059    private static final Timer addContainedByTimer = Metrics.timer(METRIC_NAME,
060            DB, CONTAINMENT, OPERATION, "addContainedBy");
061    private static final Timer commitTransactionTimer = Metrics.timer(METRIC_NAME,
062            DB, CONTAINMENT, OPERATION, "commitTransaction");
063    private static final Timer rollbackTransactionTimer = Metrics.timer(METRIC_NAME,
064            DB, CONTAINMENT, OPERATION, "rollbackTransaction");
065    private static final Timer resourceExistsTimer = Metrics.timer(METRIC_NAME,
066            DB, CONTAINMENT, OPERATION, "resourceExists");
067    private static final Timer getContainerIdByPathTimer = Metrics.timer(METRIC_NAME,
068            DB, CONTAINMENT, OPERATION, "getContainerIdByPath");
069    private static final Timer resetTimer = Metrics.timer(METRIC_NAME,
070            DB, CONTAINMENT, OPERATION, "reset");
071    private static final Timer hasResourcesStartingWithTimer = Metrics.timer(METRIC_NAME,
072            DB, CONTAINMENT, OPERATION, "hasResourcesStartingWith");
073    private static final Timer containmentLastUpdateTimer = Metrics.timer(METRIC_NAME, DB, CONTAINMENT, OPERATION,
074            "containmentLastUpdated");
075
076    @Autowired
077    @Qualifier("containmentIndexImpl")
078    private ContainmentIndex containmentIndexImpl;
079
080    @Override
081    public Stream<String> getContains(final Transaction tx, final FedoraId fedoraId) {
082        return MetricsHelper.time(getContainsTimer, () -> {
083            return containmentIndexImpl.getContains(tx, fedoraId);
084        });
085    }
086
087    @Override
088    public Stream<String> getContainsDeleted(final Transaction tx, final FedoraId fedoraId) {
089        return MetricsHelper.time(getContainsDeletedTimer, () -> {
090            return containmentIndexImpl.getContainsDeleted(tx, fedoraId);
091        });
092    }
093
094    @Override
095    public String getContainedBy(final Transaction tx, final FedoraId resource) {
096        return MetricsHelper.time(getContainsByTimer, () -> {
097            return containmentIndexImpl.getContainedBy(tx, resource);
098        });
099    }
100
101    @Override
102    public void removeContainedBy(final Transaction tx, final FedoraId parent, final FedoraId child) {
103        removeContainedByTimer.record(() -> {
104            containmentIndexImpl.removeContainedBy(tx, parent, child);
105        });
106    }
107
108    @Override
109    public void removeResource(final Transaction tx, final FedoraId resource) {
110        removeResourceTimer.record(() -> {
111            containmentIndexImpl.removeResource(tx, resource);
112        });
113    }
114
115    @Override
116    public void purgeResource(final Transaction tx, final FedoraId resource) {
117        purgeResourceTimer.record(() -> {
118            containmentIndexImpl.purgeResource(tx, resource);
119        });
120    }
121
122    @Override
123    public void addContainedBy(final Transaction tx, final FedoraId parent, final FedoraId child) {
124        addContainedByTimer.record(() -> {
125            containmentIndexImpl.addContainedBy(tx, parent, child);
126        });
127    }
128
129    @Override
130    public void addContainedBy(final Transaction tx, final FedoraId parent, final FedoraId child,
131                               final Instant startTime, final Instant endTime) {
132        addContainedByTimer.record(() -> containmentIndexImpl.addContainedBy(tx, parent, child, startTime, endTime));
133    }
134
135    @Override
136    public void commitTransaction(final Transaction tx) {
137        commitTransactionTimer.record(() -> {
138            containmentIndexImpl.commitTransaction(tx);
139        });
140    }
141
142    @Override
143    public void rollbackTransaction(final Transaction tx) {
144        rollbackTransactionTimer.record(() -> {
145            containmentIndexImpl.rollbackTransaction(tx);
146        });
147    }
148
149    @Override
150    public boolean resourceExists(final Transaction tx, final FedoraId fedoraId, final boolean includeDeleted) {
151        return MetricsHelper.time(resourceExistsTimer, () -> {
152            return containmentIndexImpl.resourceExists(tx, fedoraId, includeDeleted);
153        });
154    }
155
156    @Override
157    public FedoraId getContainerIdByPath(final Transaction tx, final FedoraId fedoraId, final boolean checkDeleted) {
158        return MetricsHelper.time(getContainerIdByPathTimer, () -> {
159            return containmentIndexImpl.getContainerIdByPath(tx, fedoraId, checkDeleted);
160        });
161    }
162
163    @Override
164    public void reset() {
165        resetTimer.record(() -> {
166            containmentIndexImpl.reset();
167        });
168    }
169
170    @Override
171    public boolean hasResourcesStartingWith(final Transaction tx, final FedoraId fedoraId) {
172        return MetricsHelper.time(hasResourcesStartingWithTimer, () ->
173                containmentIndexImpl.hasResourcesStartingWith(tx, fedoraId));
174    }
175
176    @Override
177    public Instant containmentLastUpdated(final Transaction tx, final FedoraId fedoraId) {
178        return MetricsHelper.time(containmentLastUpdateTimer, () ->
179                containmentIndexImpl.containmentLastUpdated(tx, fedoraId));
180    }
181}