Skip to content

Commit

Permalink
Close #83: provide camunda metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
arolfes committed Mar 8, 2021
1 parent 692bb13 commit 309721c
Show file tree
Hide file tree
Showing 13 changed files with 632 additions and 0 deletions.
2 changes: 2 additions & 0 deletions micronaut-camunda-bpm-example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ micronaut {

dependencies {
implementation(project(":micronaut-camunda-bpm-feature"))
implementation("io.micronaut:micronaut-management")
implementation("io.micronaut.micrometer:micronaut-micrometer-core")
runtimeOnly("com.h2database:h2")
runtimeOnly("ch.qos.logback:logback-classic")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
micronaut:
application:
name: micronaut-camunda-example
metrics:
export:
logging:
enabled: true
camunda:
admin-user:
id: admin
Expand Down
1 change: 1 addition & 0 deletions micronaut-camunda-bpm-feature/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ dependencies {
implementation("io.micronaut:micronaut-runtime")
api("org.camunda.bpm:camunda-engine:$camundaVersion")

compileOnly("io.micronaut.micrometer:micronaut-micrometer-core")
compileOnly("io.micronaut.servlet:micronaut-servlet-engine")
compileOnly("io.micronaut:micronaut-http-server-netty")
compileOnly("io.micronaut.servlet:micronaut-http-server-jetty")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2021 original 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
*
* https://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 info.novatec.micronaut.camunda.bpm.feature.metrics;

import io.micronaut.context.ApplicationContext;
import org.camunda.bpm.engine.management.Metrics;

import javax.inject.Singleton;

@Singleton
public class BpmnExecutionMetrics extends CamundaMetrics {

private long rootProcessInstanceStart = 0;

private long activityInstanceStart = 0;

private long activityInstanceEnd = 0;

public BpmnExecutionMetrics(ApplicationContext applicationContext) {
super(applicationContext);
}

public long getRootProcessInstanceStart() {
doUpdateIfNecessary();
return rootProcessInstanceStart;
}

public long getActivityInstanceStart() {
doUpdateIfNecessary();
return activityInstanceStart;
}

public long getActivityInstanceEnd() {
doUpdateIfNecessary();
return activityInstanceEnd;
}

protected void update() {
rootProcessInstanceStart = sumMetric(Metrics.ROOT_PROCESS_INSTANCE_START);
activityInstanceStart = sumMetric(Metrics.ACTIVTY_INSTANCE_START);
activityInstanceEnd = sumMetric(Metrics.ACTIVTY_INSTANCE_END);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2021 original 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
*
* https://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 info.novatec.micronaut.camunda.bpm.feature.metrics;

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.camunda.bpm.engine.management.Metrics;

import javax.inject.Singleton;

import static info.novatec.micronaut.camunda.bpm.feature.metrics.CamundaMetricsBinderTags.BPMN_EXECUTION_DEFAULT_TAGS;
import static info.novatec.micronaut.camunda.bpm.feature.metrics.CamundaMetricsBinderTags.TAG_KEY_NAME;

@Singleton
public class BpmnExecutionMetricsBinder implements MeterBinder {

protected final BpmnExecutionMetrics bpmnExecutionMetrics;

public BpmnExecutionMetricsBinder(BpmnExecutionMetrics bpmnExecutionMetrics) {
this.bpmnExecutionMetrics = bpmnExecutionMetrics;
}

@Override
public void bindTo(MeterRegistry registry) {

Gauge.builder("camunda.bpmn." + Metrics.ROOT_PROCESS_INSTANCE_START.replace('-', '.'), bpmnExecutionMetrics, BpmnExecutionMetrics::getRootProcessInstanceStart)
.description("The number of root process instance executions started. This is also known as Root Process Instances (RPI). A root process instance has no parent process instance, i.e. it is a top-level execution.")
.tags(Tags.concat(BPMN_EXECUTION_DEFAULT_TAGS, TAG_KEY_NAME, Metrics.ROOT_PROCESS_INSTANCE_START))
.register(registry);
Gauge.builder("camunda.bpmn." + Metrics.ACTIVTY_INSTANCE_START.replace('-', '.'), bpmnExecutionMetrics, BpmnExecutionMetrics::getActivityInstanceStart)
.description("The number of activity instances started. This is also known as flow node instances (FNI).")
.tags(Tags.concat(BPMN_EXECUTION_DEFAULT_TAGS, TAG_KEY_NAME, Metrics.ACTIVTY_INSTANCE_START))
.register(registry);
Gauge.builder("camunda.bpmn." + Metrics.ACTIVTY_INSTANCE_END.replace('-', '.'), bpmnExecutionMetrics, BpmnExecutionMetrics::getActivityInstanceEnd)
.description("The number of activity instances ended.")
.tags(Tags.concat(BPMN_EXECUTION_DEFAULT_TAGS, TAG_KEY_NAME, Metrics.ACTIVTY_INSTANCE_END))
.register(registry);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright 2021 original 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
*
* https://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 info.novatec.micronaut.camunda.bpm.feature.metrics;

import io.micronaut.context.ApplicationContext;
import org.camunda.bpm.engine.ManagementService;
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.camunda.bpm.engine.management.MetricsQuery;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

abstract public class CamundaMetrics {

//@Property(name = MICRONAUT_METRICS_BINDERS + ".camunda.refreshWaitTime", defaultValue = "60")
private long refreshWaitTimeSeconds = 60;

private LocalDateTime lastUpdate = LocalDateTime.now();

private ManagementService managementService = null;

// Using application context here because injection of managementService or processEngine leads to infinity loop during initialization
// metrics are init very early even before datasource is completly setup
// but processengine needs datasource
private final ApplicationContext applicationContext;

private final Map<String, MetricsQuery> metricsQueryMap = new HashMap<>();

protected CamundaMetrics(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}


abstract protected void update();

protected void doUpdateIfNecessary() {
if (shouldLoad()) {
update();
}
}

protected boolean shouldLoad() {

LocalDateTime now = LocalDateTime.now();
if (now.isAfter(lastUpdate.minusMinutes(refreshWaitTimeSeconds))) {
lastUpdate = now;
return true;
}
return false;
}

protected long sumMetric(String metricName) {

MetricsQuery metricsQuery = getMetricsQuery(metricName);
if (metricsQuery != null) {
return metricsQuery.sum();
} else {
return 0;
}
}

private MetricsQuery getMetricsQuery(String metricsName) {
if (metricsQueryMap.containsKey(metricsName)) {
return metricsQueryMap.get(metricsName);
}
if (initManagementService()) {
MetricsQuery metricsQuery = managementService.createMetricsQuery().name(metricsName);
// does not return the intialized metrics query
metricsQueryMap.put(metricsName, metricsQuery);
return metricsQuery;
}
return null;
}

private boolean initManagementService() {
if (managementService == null) {
managementService = applicationContext.getBean(ProcessEngineConfigurationImpl.class).getManagementService();
return true;
}
return false;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2021 original 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
*
* https://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 info.novatec.micronaut.camunda.bpm.feature.metrics;

import io.micrometer.core.instrument.Tag;

import java.util.Arrays;

public class CamundaMetricsBinderTags {

static final String TAG_KEY_NAME = "name";

static final String TAG_KEY_CATEGORY = "category";

static final Tag TAG_CLASS_CAMUNDA = Tag.of("class", "camunda");

static final Iterable<Tag> JOB_EXECUTOR_DEFAULT_TAGS = Arrays.asList(TAG_CLASS_CAMUNDA, Tag.of(TAG_KEY_CATEGORY, "job-executor"));

static final Iterable<Tag> DMN_EXECUTION_DEFAULT_TAGS = Arrays.asList(TAG_CLASS_CAMUNDA, Tag.of(TAG_KEY_CATEGORY, "dmn-execution"));

static final Iterable<Tag> BPMN_EXECUTION_DEFAULT_TAGS = Arrays.asList(TAG_CLASS_CAMUNDA, Tag.of(TAG_KEY_CATEGORY, "bpmn-execution"));

static final Iterable<Tag> HISTORY_CLEAN_UP_DEFAULT_TAGS = Arrays.asList(TAG_CLASS_CAMUNDA, Tag.of(TAG_KEY_CATEGORY, "history-clean-up"));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2021 original 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
*
* https://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 info.novatec.micronaut.camunda.bpm.feature.metrics;

import io.micronaut.context.ApplicationContext;
import org.camunda.bpm.engine.management.Metrics;

import javax.inject.Singleton;

@Singleton
public class DmnExecutionMetrics extends CamundaMetrics {

private long executedDecisionInstances = 0;

private long executedDecisionElements = 0;

public DmnExecutionMetrics(ApplicationContext applicationContext) {
super(applicationContext);
}

public long getExecutedDecisionInstances() {
doUpdateIfNecessary();
return executedDecisionInstances;
}

public long getExecutedDecisionElements() {
doUpdateIfNecessary();
return executedDecisionElements;
}

protected void update() {
executedDecisionInstances = sumMetric(Metrics.EXECUTED_DECISION_INSTANCES);
executedDecisionElements = sumMetric(Metrics.EXECUTED_DECISION_ELEMENTS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2021 original 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
*
* https://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 info.novatec.micronaut.camunda.bpm.feature.metrics;

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.camunda.bpm.engine.management.Metrics;

import javax.inject.Singleton;

import static info.novatec.micronaut.camunda.bpm.feature.metrics.CamundaMetricsBinderTags.DMN_EXECUTION_DEFAULT_TAGS;
import static info.novatec.micronaut.camunda.bpm.feature.metrics.CamundaMetricsBinderTags.TAG_KEY_NAME;

@Singleton
public class DmnExecutionMetricsBinder implements MeterBinder {

protected final DmnExecutionMetrics dmnExecutionMetrics;

public DmnExecutionMetricsBinder(DmnExecutionMetrics dmnExecutionMetrics) {
this.dmnExecutionMetrics = dmnExecutionMetrics;
}

@Override
public void bindTo(MeterRegistry registry) {

Gauge.builder("camunda.dmn." + Metrics.EXECUTED_DECISION_INSTANCES.replace('-', '.'), dmnExecutionMetrics, DmnExecutionMetrics::getExecutedDecisionInstances)
.description("The number of evaluated decision instances (EDI). A decision instance is a DMN decision table or a DMN Literal Expression.")
.tags(Tags.concat(DMN_EXECUTION_DEFAULT_TAGS, TAG_KEY_NAME, Metrics.EXECUTED_DECISION_INSTANCES))
.register(registry);
Gauge.builder("camunda.dmn." + Metrics.EXECUTED_DECISION_ELEMENTS.replace('-', '.'), dmnExecutionMetrics, DmnExecutionMetrics::getExecutedDecisionElements)
.description("The number of decision elements executed during evaluation of DMN decision tables. For one table, this is calculated as the number of clauses multiplied by the number of rules.")
.tags(Tags.concat(DMN_EXECUTION_DEFAULT_TAGS, TAG_KEY_NAME, Metrics.EXECUTED_DECISION_ELEMENTS))
.register(registry);
}
}
Loading

0 comments on commit 309721c

Please sign in to comment.