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.identifiers.FedoraId;
026import org.springframework.beans.factory.annotation.Autowired;
027import org.springframework.beans.factory.annotation.Qualifier;
028import org.springframework.stereotype.Component;
029
030import java.time.Instant;
031import java.util.stream.Stream;
032
033/**
034 * ContainmentIndex wrapper for adding metrics
035 *
036 * @author pwinckles
037 */
038@Component("containmentIndex")
039public class ContainmentIndexMetrics implements ContainmentIndex {
040
041    private static final String METRIC_NAME = "fcrepo.db";
042    private static final String DB = "db";
043    private static final String CONTAINMENT = "containment";
044    private static final String OPERATION = "operation";
045
046    private static final Timer getContainsTimer = Metrics.timer(METRIC_NAME,
047            DB, CONTAINMENT, OPERATION, "getContains");
048    private static final Timer getContainsDeletedTimer = Metrics.timer(METRIC_NAME,
049            DB, CONTAINMENT, OPERATION, "getContainsDeleted");
050    private static final Timer getContainsByTimer = Metrics.timer(METRIC_NAME,
051            DB, CONTAINMENT, OPERATION, "getContainsBy");
052    private static final Timer removeContainedByTimer = Metrics.timer(METRIC_NAME,
053            DB, CONTAINMENT, OPERATION, "removeContainedBy");
054    private static final Timer removeResourceTimer = Metrics.timer(METRIC_NAME,
055            DB, CONTAINMENT, OPERATION, "removeResource");
056    private static final Timer purgeResourceTimer = Metrics.timer(METRIC_NAME,
057            DB, CONTAINMENT, OPERATION, "purgeResource");
058    private static final Timer addContainedByTimer = Metrics.timer(METRIC_NAME,
059            DB, CONTAINMENT, OPERATION, "addContainedBy");
060    private static final Timer commitTransactionTimer = Metrics.timer(METRIC_NAME,
061            DB, CONTAINMENT, OPERATION, "commitTransaction");
062    private static final Timer rollbackTransactionTimer = Metrics.timer(METRIC_NAME,
063            DB, CONTAINMENT, OPERATION, "rollbackTransaction");
064    private static final Timer resourceExistsTimer = Metrics.timer(METRIC_NAME,
065            DB, CONTAINMENT, OPERATION, "resourceExists");
066    private static final Timer getContainerIdByPathTimer = Metrics.timer(METRIC_NAME,
067            DB, CONTAINMENT, OPERATION, "getContainerIdByPath");
068    private static final Timer resetTimer = Metrics.timer(METRIC_NAME,
069            DB, CONTAINMENT, OPERATION, "reset");
070    private static final Timer hasResourcesStartingWithTimer = Metrics.timer(METRIC_NAME,
071            DB, CONTAINMENT, OPERATION, "hasResourcesStartingWith");
072    private static final Timer containmentLastUpdateTimer = Metrics.timer(METRIC_NAME, DB, CONTAINMENT, OPERATION,
073            "containmentLastUpdated");
074
075    @Autowired
076    @Qualifier("containmentIndexImpl")
077    private ContainmentIndex containmentIndexImpl;
078
079    @Override
080    public Stream<String> getContains(final String txId, final FedoraId fedoraId) {
081        return MetricsHelper.time(getContainsTimer, () -> {
082            return containmentIndexImpl.getContains(txId, fedoraId);
083        });
084    }
085
086    @Override
087    public Stream<String> getContainsDeleted(final String txId, final FedoraId fedoraId) {
088        return MetricsHelper.time(getContainsDeletedTimer, () -> {
089            return containmentIndexImpl.getContainsDeleted(txId, fedoraId);
090        });
091    }
092
093    @Override
094    public String getContainedBy(final String txID, final FedoraId resource) {
095        return MetricsHelper.time(getContainsByTimer, () -> {
096            return containmentIndexImpl.getContainedBy(txID, resource);
097        });
098    }
099
100    @Override
101    public void removeContainedBy(final String txID, final FedoraId parent, final FedoraId child) {
102        removeContainedByTimer.record(() -> {
103            containmentIndexImpl.removeContainedBy(txID, parent, child);
104        });
105    }
106
107    @Override
108    public void removeResource(final String txID, final FedoraId resource) {
109        removeResourceTimer.record(() -> {
110            containmentIndexImpl.removeResource(txID, resource);
111        });
112    }
113
114    @Override
115    public void purgeResource(final String txID, final FedoraId resource) {
116        purgeResourceTimer.record(() -> {
117            containmentIndexImpl.purgeResource(txID, resource);
118        });
119    }
120
121    @Override
122    public void addContainedBy(final String txID, final FedoraId parent, final FedoraId child) {
123        addContainedByTimer.record(() -> {
124            containmentIndexImpl.addContainedBy(txID, parent, child);
125        });
126    }
127
128    @Override
129    public void addContainedBy(final String txId, final FedoraId parent, final FedoraId child,
130                               final Instant startTime, final Instant endTime) {
131        addContainedByTimer.record(() -> containmentIndexImpl.addContainedBy(txId, parent, child, startTime, endTime));
132    }
133
134    @Override
135    public void commitTransaction(final String txId) {
136        commitTransactionTimer.record(() -> {
137            containmentIndexImpl.commitTransaction(txId);
138        });
139    }
140
141    @Override
142    public void rollbackTransaction(final String txId) {
143        rollbackTransactionTimer.record(() -> {
144            containmentIndexImpl.rollbackTransaction(txId);
145        });
146    }
147
148    @Override
149    public boolean resourceExists(final String txID, final FedoraId fedoraId, final boolean includeDeleted) {
150        return MetricsHelper.time(resourceExistsTimer, () -> {
151            return containmentIndexImpl.resourceExists(txID, fedoraId, includeDeleted);
152        });
153    }
154
155    @Override
156    public FedoraId getContainerIdByPath(final String txID, final FedoraId fedoraId, final boolean checkDeleted) {
157        return MetricsHelper.time(getContainerIdByPathTimer, () -> {
158            return containmentIndexImpl.getContainerIdByPath(txID, fedoraId, checkDeleted);
159        });
160    }
161
162    @Override
163    public void reset() {
164        resetTimer.record(() -> {
165            containmentIndexImpl.reset();
166        });
167    }
168
169    @Override
170    public boolean hasResourcesStartingWith(final String txId, final FedoraId fedoraId) {
171        return MetricsHelper.time(hasResourcesStartingWithTimer, () ->
172                containmentIndexImpl.hasResourcesStartingWith(txId, fedoraId));
173    }
174
175    @Override
176    public Instant containmentLastUpdated(final String txId, final FedoraId fedoraId) {
177        return MetricsHelper.time(containmentLastUpdateTimer, () ->
178                containmentIndexImpl.containmentLastUpdated(txId, fedoraId));
179    }
180}