001package org.jpos.metrics.iso; 002 003import io.micrometer.core.instrument.MeterRegistry; 004import io.micrometer.core.instrument.Tags; 005import org.jpos.iso.ISOMsg; 006import org.jpos.metrics.MeterInfo; 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.stream.Collectors; 011 012public interface ISOMsgMetrics { 013 String DEFAULT_CHANNEL_METRIC_NAME = MeterInfo.ISOMSG_IN.id(); 014 015 String ENV_CHANNEL_TAGS = "metrics.channel.tags"; 016 String DEFAULT_TAGS = "name, type, direction"; 017 018 String ENV_CHANNEL_FIELDS = "metrics.channel.fields"; 019 String DEFAULT_CHANNEL_FIELDS = "mti"; 020 021 interface Source{ 022 void setISOMsgMetrics(ISOMsgMetrics metrics); 023 ISOMsgMetrics getISOMsgMetrics(); 024 } 025 026 void setMetricName(String metricName); 027 String getMetricName(); 028 029 String getMetricDescription(); 030 void setMetricDescription(String metricDescription); 031 032 Tags addTags(Tags tags); 033 default Tags addTags(String ...tags) { return addTags(Tags.of(tags)); } 034 default Tags getTags() { return addTags(Tags.empty()); } 035 036 /** 037 * Records an {@link ISOMsg} in the meter registry.<br/> 038 * The metric name and tags will be taken strictly from this object's 039 * configuration. <br/> 040 * If this object hasn't been successfully registered, it throws an 041 * {@link IllegalStateException}. 042 * 043 * @param m the {@link ISOMsg} to record. 044 * @throws IllegalStateException when this object hasn't been registered 045 */ 046 void recordMessage(ISOMsg m) throws IllegalStateException; 047 048 /** 049 * Records an {@link ISOMsg} in the meter registry.<br/> 050 * Similar to {@link #recordMessage(ISOMsg)} but using the metric name, description and maybe some 051 * tags taken from the {@link MeterInfo} argument. 052 * <p> 053 * If the metric for that combination of {@link MeterInfo} values and local values fails to register 054 * in the global {@link MeterRegistry} (or any underlying one like the Prometheus registry), the method 055 * may throw an {@link IllegalStateException}. This also happens if this object hasn't been successfully 056 * registered by The metric name and tags will be taken from 057 * what has been configured. If this object hasn't been successfully registered, it throws an 058 * {@link IllegalStateException}. 059 * 060 * @param m the {@link ISOMsg} to record. 061 * @throws IllegalStateException when this object hasn't been registered 062 */ 063 void recordMessage(ISOMsg m, MeterInfo meterInfo) throws IllegalStateException; 064 065 066 /** 067 * Register this object to work with a given {@link MeterRegistry}.</br> 068 * 069 * This method may serve more than one purpose in the object's lifecycle: 070 * <ul> 071 * <li>Assign a {@link MeterRegistry} to be used for the created meters. 072 * (The registry can be obtained by calling {@link #getRegistry()})</li> 073 * <li>Before this object has been registered, it can be configured by setting tags, etc., 074 * but attempting to record a message (e.g. through {@link #recordMessage(ISOMsg)}) 075 * will throw an {@link IllegalStateException}.</li> 076 * <li>After it has been registered, it's ready to record messages. 077 * However, it <b>can't be configured</b> any longer, or it will throw an {@link IllegalStateException}. 078 * The object's configuration can be considered "frozen".</li> 079 * <li>In some (future) implementation, it may make use of the {@link #getMetricSignature()} to 080 * do some caching to ensure that every metric name has only one set of tag keys, thus avoiding 081 * metrics name+keyset collision in {@code PrometheusMeterRegistry}.</li> 082 * </ul> 083 * 084 * The {@link #unregister()} method should be called when done using this object. 085 * 086 * @return true if successful, false if there was an error having this registered 087 */ 088 boolean register(MeterRegistry registry); 089 090 /** 091 * It calls {@link #removeMeters()} and clears its internal reference to its {@link MeterRegistry}.<br/> 092 * 093 * It will also "unfreeze" the object, making it available for reconfiguration. 094 */ 095 void unregister(); 096 097 MeterRegistry getRegistry(); 098 099 void removeMeters(); 100 101 102 /** 103 * A unique meter signature, concatenating the meter name, vertical pipe, comma-separated sorted list of all tag keys 104 * that this object produces.<br/> 105 * Default implementation uses the values from {@link #getMetricName()} and {@link #getTags()}. 106 * A concrete implementation must make sure of gathering all the appropriate tag keys from internal config state 107 * which may include more than what's returned by {@link #getTags()}. 108 * @return The unique metric signature. 109 */ 110 default String getMetricSignature() { 111 List<String> keys = new ArrayList<>(); 112 getTags().forEach(t -> keys.add(t.getKey())); 113 return getMetricName()+"|"+ 114 keys.stream().sorted().collect(Collectors.joining(",")); 115 } 116}