Provide agent-side meter api (#4816)
This commit is contained in:
parent
e143ae62eb
commit
cc9ea271a7
|
|
@ -0,0 +1,31 @@
|
|||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
~ contributor license agreements. See the NOTICE file distributed with
|
||||
~ this work for additional information regarding copyright ownership.
|
||||
~ The ASF licenses this file to You 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.
|
||||
~
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>apm-application-toolkit</artifactId>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-toolkit-meter</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<url>http://maven.apache.org</url>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
public interface BaseBuilder<Builder extends BaseBuilder, Meter extends BaseMeter> {
|
||||
|
||||
/**
|
||||
* append new tags to this meter
|
||||
*/
|
||||
Builder tag(String name, String value);
|
||||
|
||||
/**
|
||||
* Build a new meter object
|
||||
*/
|
||||
Meter build();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
public interface BaseMeter {
|
||||
|
||||
/**
|
||||
* Get meter name
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Get tag value
|
||||
*/
|
||||
String getTag(String tagKey);
|
||||
|
||||
/**
|
||||
* Get meter Id
|
||||
*/
|
||||
MeterId getMeterId();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
/**
|
||||
* A counter is a cumulative metric that represents a single monotonically increasing counter whose value can only increase or be reset to zero on restart.
|
||||
*/
|
||||
public interface Counter extends BaseMeter {
|
||||
|
||||
void increment(double count);
|
||||
|
||||
double get();
|
||||
|
||||
/**
|
||||
* Counter mode
|
||||
*/
|
||||
enum Mode {
|
||||
/**
|
||||
* Increase single value, report the real value
|
||||
*/
|
||||
INCREMENT,
|
||||
|
||||
/**
|
||||
* Rate with previous value when report
|
||||
*/
|
||||
RATE
|
||||
}
|
||||
|
||||
interface Builder extends BaseBuilder<Builder, Counter> {
|
||||
/**
|
||||
* Setting counter mode
|
||||
*/
|
||||
Builder mode(Mode mode);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
/**
|
||||
* A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
|
||||
*/
|
||||
public interface Gauge extends BaseMeter {
|
||||
|
||||
/**
|
||||
* Get count
|
||||
*/
|
||||
double get();
|
||||
|
||||
interface Builder extends BaseBuilder<Builder, Gauge> {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Similar to a histogram, a summary sample observations (usual things like request durations and response sizes).
|
||||
* While it also provides a total count of observations and a sum of all observed values, it calculates configurable quartiles over a sliding time window.
|
||||
* The histogram provides detailed data in each data group.
|
||||
*/
|
||||
public interface Histogram extends BaseMeter {
|
||||
|
||||
/**
|
||||
* Add value into the histogram, automatic analyze what bucket count need to be increment
|
||||
* [step1, step2)
|
||||
*/
|
||||
void addValue(double value);
|
||||
|
||||
/**
|
||||
* Get all buckets
|
||||
*/
|
||||
Bucket[] getBuckets();
|
||||
|
||||
interface Builder extends BaseBuilder<Builder, Histogram> {
|
||||
|
||||
/**
|
||||
* Setting bucket steps
|
||||
*/
|
||||
Builder steps(List<Double> steps);
|
||||
|
||||
/**
|
||||
* Setting min value, default is zero
|
||||
*/
|
||||
Builder minValue(double minValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Histogram bucket
|
||||
*/
|
||||
interface Bucket {
|
||||
|
||||
/**
|
||||
* Get bucket key
|
||||
*/
|
||||
double getBucket();
|
||||
|
||||
/**
|
||||
* Get bucket count
|
||||
*/
|
||||
long getCount();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class MeterFactory {
|
||||
|
||||
/**
|
||||
* Create a counter builder by name
|
||||
*/
|
||||
public static Counter.Builder counter(String name) {
|
||||
return new CounterImpl.Builder(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a counter builder by meter id
|
||||
*/
|
||||
public static Counter.Builder counter(MeterId meterId) {
|
||||
return new CounterImpl.Builder(meterId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a gauge builder by name and getter
|
||||
*/
|
||||
public static Gauge.Builder gauge(String name, Supplier<Double> getter) {
|
||||
return new GaugeImpl.Builder(name, getter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a gauge builder by meter id and getter
|
||||
*/
|
||||
public static Gauge.Builder gauge(MeterId meterId, Supplier<Double> getter) {
|
||||
return new GaugeImpl.Builder(meterId, getter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a histogram builder by name
|
||||
*/
|
||||
public static Histogram.Builder histogram(String name) {
|
||||
return new HistogramImpl.Builder(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a histogram builder by meterId
|
||||
*/
|
||||
public static Histogram.Builder histogram(MeterId meterId) {
|
||||
return new HistogramImpl.Builder(meterId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Meter identity
|
||||
*/
|
||||
public class MeterId {
|
||||
|
||||
protected final String name;
|
||||
protected final MeterType type;
|
||||
protected final List<Tag> tags = new ArrayList<>();
|
||||
|
||||
public MeterId(String name, MeterType type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public MeterId(String name, MeterType type, List<Tag> tags) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.tags.addAll(tags);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public MeterType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public List<Tag> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple copy to a new meter id, change the name and type
|
||||
*/
|
||||
public MeterId copyTo(String name, MeterType type) {
|
||||
return new MeterId(name, type, tags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MeterId meterId = (MeterId) o;
|
||||
return Objects.equals(name, meterId.name) &&
|
||||
type == meterId.type &&
|
||||
Objects.equals(tags, meterId.tags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, type, tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* The meter type
|
||||
*/
|
||||
public static enum MeterType {
|
||||
COUNTER,
|
||||
GAUGE,
|
||||
HISTOGRAM
|
||||
}
|
||||
|
||||
/**
|
||||
* Using name/value pair as the tag, also it will {@link Comparable} when we sort all of tags
|
||||
*/
|
||||
public static class Tag implements Comparable<Tag> {
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public Tag(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Tag tag = (Tag) o;
|
||||
return Objects.equals(name, tag.name) &&
|
||||
Objects.equals(value, tag.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Tag o) {
|
||||
return this.name.compareTo(o.name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter.impl;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.BaseBuilder;
|
||||
import org.apache.skywalking.apm.toolkit.meter.BaseMeter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Help to build the meter
|
||||
*/
|
||||
public abstract class AbstractBuilder<BUILDER extends BaseBuilder, BASE extends BaseMeter, IMPL extends AbstractMeter> implements BaseBuilder<BUILDER, BASE> {
|
||||
protected final MeterId meterId;
|
||||
|
||||
/**
|
||||
* Build a new meter build, meter name is required
|
||||
*/
|
||||
public AbstractBuilder(String name) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Meter name cannot be null");
|
||||
}
|
||||
this.meterId = new MeterId(name, getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new meter build from exists meter id
|
||||
*/
|
||||
public AbstractBuilder(MeterId meterId) {
|
||||
if (meterId == null) {
|
||||
throw new IllegalArgumentException("Meter id cannot be null");
|
||||
}
|
||||
if (!Objects.equals(meterId.getType(), getType())) {
|
||||
throw new IllegalArgumentException("Meter id type is not matches");
|
||||
}
|
||||
this.meterId = meterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* append new tag to this meter
|
||||
*/
|
||||
public BUILDER tag(String name, String value) {
|
||||
meterId.getTags().add(new MeterId.Tag(name, value));
|
||||
return (BUILDER) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a meter
|
||||
*/
|
||||
protected abstract BASE create(MeterId meterId);
|
||||
|
||||
/**
|
||||
* Accept the new meter when register, could use it to judge histogram buckets is correct.
|
||||
* It's working on the same meter id only.
|
||||
* @throws IllegalArgumentException if cannot be accept, throws information
|
||||
*/
|
||||
protected void accept(IMPL meter) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get supported build meter type
|
||||
*/
|
||||
protected abstract MeterId.MeterType getType();
|
||||
|
||||
/**
|
||||
* Get current meter id
|
||||
*/
|
||||
public MeterId getMeterId() {
|
||||
return meterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new meter object
|
||||
*/
|
||||
public BASE build() {
|
||||
// sort the tags
|
||||
this.meterId.getTags().sort(MeterId.Tag::compareTo);
|
||||
// create or get the meter
|
||||
return MeterCenter.getOrCreateMeter(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter.impl;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Base meter implementation bean
|
||||
*/
|
||||
public abstract class AbstractMeter {
|
||||
|
||||
protected final MeterId meterId;
|
||||
|
||||
public AbstractMeter(MeterId meterId) {
|
||||
this.meterId = meterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get meter name
|
||||
*/
|
||||
public String getName() {
|
||||
return meterId.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tag value
|
||||
*/
|
||||
public String getTag(String tagKey) {
|
||||
for (MeterId.Tag tag : meterId.getTags()) {
|
||||
if (tag.getName().equals(tagKey)) {
|
||||
return tag.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
AbstractMeter abstractMeter = (AbstractMeter) o;
|
||||
return Objects.equals(meterId, abstractMeter.meterId);
|
||||
}
|
||||
|
||||
public MeterId getMeterId() {
|
||||
return meterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(meterId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter.impl;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.atomic.DoubleAdder;
|
||||
|
||||
/**
|
||||
* Using {@link DoubleAdder} to add count
|
||||
*/
|
||||
public class CounterImpl extends AbstractMeter implements Counter {
|
||||
|
||||
protected final DoubleAdder count;
|
||||
protected final Mode mode;
|
||||
|
||||
private final AtomicReference<Double> previous = new AtomicReference();
|
||||
|
||||
protected CounterImpl(MeterId meterId, Mode mode) {
|
||||
super(meterId);
|
||||
this.count = new DoubleAdder();
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment count
|
||||
*/
|
||||
public void increment(double count) {
|
||||
this.count.add(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count value
|
||||
*/
|
||||
public double get() {
|
||||
return this.count.doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Using at the Skywalking agent get, make is support {@link Mode#RATE}
|
||||
*/
|
||||
public double agentGet() {
|
||||
final double currentValue = get();
|
||||
double count;
|
||||
if (Objects.equals(Mode.RATE, this.mode)) {
|
||||
final Double previousValue = previous.getAndSet(currentValue);
|
||||
|
||||
// calculate the add count
|
||||
if (previousValue == null) {
|
||||
count = currentValue;
|
||||
} else {
|
||||
count = currentValue - previousValue;
|
||||
}
|
||||
} else {
|
||||
count = currentValue;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static class Builder extends AbstractBuilder<Counter.Builder, Counter, CounterImpl> implements Counter.Builder {
|
||||
private Counter.Mode mode = Counter.Mode.INCREMENT;
|
||||
|
||||
public Builder(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public Builder(MeterId meterId) {
|
||||
super(meterId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting counter mode
|
||||
*/
|
||||
public Builder mode(Counter.Mode mode) {
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void accept(CounterImpl meter) throws IllegalArgumentException {
|
||||
// Rate mode must be same
|
||||
if (!Objects.equals(meter.mode, this.mode)) {
|
||||
throw new IllegalArgumentException("Mode is not same");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Counter create(MeterId meterId) {
|
||||
return new CounterImpl(meterId, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MeterId.MeterType getType() {
|
||||
return MeterId.MeterType.COUNTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter.impl;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.Gauge;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Using {@link Supplier} as the value.
|
||||
*/
|
||||
public class GaugeImpl extends AbstractMeter implements Gauge {
|
||||
|
||||
protected Supplier<Double> getter;
|
||||
|
||||
public GaugeImpl(MeterId meterId, Supplier<Double> getter) {
|
||||
super(meterId);
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count
|
||||
*/
|
||||
public double get() {
|
||||
return getter.get();
|
||||
}
|
||||
|
||||
public static class Builder extends AbstractBuilder<Gauge.Builder, Gauge, GaugeImpl> implements Gauge.Builder {
|
||||
private final Supplier<Double> getter;
|
||||
|
||||
public Builder(String name, Supplier<Double> getter) {
|
||||
super(name);
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
public Builder(MeterId meterId, Supplier<Double> getter) {
|
||||
super(meterId);
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(GaugeImpl meter) {
|
||||
if (this.getter != meter.getter) {
|
||||
throw new IllegalArgumentException("Getter is not same");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GaugeImpl create(MeterId meterId) {
|
||||
if (getter == null) {
|
||||
throw new IllegalArgumentException("getter cannot be null");
|
||||
}
|
||||
return new GaugeImpl(meterId, getter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId.MeterType getType() {
|
||||
return MeterId.MeterType.GAUGE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter.impl;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.Histogram;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Custom bucket as the steps.
|
||||
*/
|
||||
public class HistogramImpl extends AbstractMeter implements Histogram {
|
||||
|
||||
protected final Bucket[] buckets;
|
||||
protected final List<Double> steps;
|
||||
|
||||
public static HistogramImpl.Builder create(String name) {
|
||||
return new Builder(name);
|
||||
}
|
||||
|
||||
protected HistogramImpl(MeterId meterId, List<Double> steps) {
|
||||
super(meterId);
|
||||
this.steps = steps;
|
||||
this.buckets = initBuckets(steps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add value into the histogram, automatic analyze what bucket count need to be increment
|
||||
* [step1, step2)
|
||||
*/
|
||||
public void addValue(double value) {
|
||||
Bucket bucket = findBucket(value);
|
||||
if (bucket == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
bucket.increment(1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getting all buckets
|
||||
*/
|
||||
public Bucket[] getBuckets() {
|
||||
return buckets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using binary search the bucket
|
||||
*/
|
||||
private Bucket findBucket(double value) {
|
||||
int low = 0;
|
||||
int high = buckets.length - 1;
|
||||
|
||||
while (low <= high) {
|
||||
int mid = (low + high) / 2;
|
||||
if (buckets[mid].bucket < value)
|
||||
low = mid + 1;
|
||||
else if (buckets[mid].bucket > value)
|
||||
high = mid - 1;
|
||||
else
|
||||
return buckets[mid];
|
||||
}
|
||||
|
||||
// because using min value as bucket, need using previous bucket
|
||||
low -= 1;
|
||||
|
||||
return low < buckets.length && low >= 0 ? buckets[low] : null;
|
||||
}
|
||||
|
||||
private Bucket[] initBuckets(List<Double> buckets) {
|
||||
final Bucket[] list = new Bucket[buckets.size()];
|
||||
for (int i = 0; i < buckets.size(); i++) {
|
||||
list[i] = new Bucket(buckets.get(i));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Histogram builder
|
||||
*/
|
||||
public static class Builder extends AbstractBuilder<Histogram.Builder, Histogram, HistogramImpl> implements Histogram.Builder {
|
||||
private double minValue = 0;
|
||||
private List<Double> steps;
|
||||
|
||||
public Builder(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public Builder(MeterId meterId) {
|
||||
super(meterId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting bucket steps
|
||||
*/
|
||||
public Builder steps(List<Double> steps) {
|
||||
this.steps = new ArrayList<>(steps);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting min value, default is zero
|
||||
*/
|
||||
public Builder minValue(double minValue) {
|
||||
this.minValue = minValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(HistogramImpl meter) {
|
||||
if (this.steps.get(0) != minValue) {
|
||||
this.steps.add(0, minValue);
|
||||
}
|
||||
if (meter.buckets.length != this.steps.size()) {
|
||||
throw new IllegalArgumentException("Steps are not has the same size");
|
||||
}
|
||||
List<Double> meterSteps = new ArrayList<>(meter.buckets.length);
|
||||
for (Bucket bucket : meter.buckets) {
|
||||
meterSteps.add(bucket.bucket);
|
||||
}
|
||||
if (!Objects.equals(meterSteps, this.steps)) {
|
||||
throw new IllegalArgumentException("Steps are not the same");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistogramImpl create(MeterId meterId) {
|
||||
if (steps == null || steps.isEmpty()) {
|
||||
throw new IllegalArgumentException("Missing steps setting");
|
||||
}
|
||||
|
||||
// sort and distinct the steps
|
||||
steps = steps.stream().distinct().sorted().collect(Collectors.toList());
|
||||
|
||||
// verify steps with except min value
|
||||
if (steps.get(0) < minValue) {
|
||||
throw new IllegalArgumentException("First step must bigger than min value");
|
||||
} else if (steps.get(0) != minValue) {
|
||||
// add the min value to the steps
|
||||
steps.add(0, minValue);
|
||||
}
|
||||
|
||||
return new HistogramImpl(meterId, steps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId.MeterType getType() {
|
||||
return MeterId.MeterType.HISTOGRAM;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Histogram bucket
|
||||
*/
|
||||
private static class Bucket implements Histogram.Bucket {
|
||||
protected double bucket;
|
||||
protected AtomicLong count = new AtomicLong();
|
||||
|
||||
public Bucket(double bucket) {
|
||||
this.bucket = bucket;
|
||||
}
|
||||
|
||||
public void increment(long count) {
|
||||
this.count.addAndGet(count);
|
||||
}
|
||||
|
||||
public double getBucket() {
|
||||
return bucket;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Bucket bucket1 = (Bucket) o;
|
||||
return bucket == bucket1.bucket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(bucket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter.impl;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.BaseBuilder;
|
||||
import org.apache.skywalking.apm.toolkit.meter.BaseMeter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Management all the meter.
|
||||
*/
|
||||
public class MeterCenter {
|
||||
|
||||
private static final Map<MeterId, BaseMeter> METER_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Get or create a new meter
|
||||
* @return If already exists, it will return existed meter, otherwise it will register it.
|
||||
*/
|
||||
public static <BUILDER extends BaseBuilder, BASE extends BaseMeter, IMPL extends AbstractMeter> BASE getOrCreateMeter(AbstractBuilder<BUILDER, BASE, IMPL> builder) {
|
||||
if (builder == null) {
|
||||
return null;
|
||||
}
|
||||
return (BASE) METER_MAP.compute(builder.getMeterId(), (meterId, previous) -> {
|
||||
if (previous == null) {
|
||||
return builder.create(meterId);
|
||||
}
|
||||
|
||||
// Check previous meter is accept the new meter
|
||||
builder.accept((IMPL) previous);
|
||||
|
||||
return previous;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove meter
|
||||
* @return Meter reference if exists
|
||||
*/
|
||||
public static BaseMeter removeMeter(MeterId id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
return METER_MAP.remove(id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.AbstractBuilder;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.AbstractMeter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.internal.util.reflection.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
public class AbstractMeterTest {
|
||||
|
||||
@Test
|
||||
public void testBuild() {
|
||||
// simple name and tags
|
||||
TestCounter.Builder meterBuilder1 = Mockito.spy(TestCounter.create("test_meter"));
|
||||
meterBuilder1.tag("k1", "v1");
|
||||
final Counter testCounter1 = meterBuilder1.build();
|
||||
Assert.assertNotNull(testCounter1);
|
||||
|
||||
verify(meterBuilder1, times(1)).create(any());
|
||||
verify(meterBuilder1, times(0)).accept(any());
|
||||
|
||||
final MeterId meterId = (MeterId) Whitebox.getInternalState(testCounter1, "meterId");
|
||||
Assert.assertNotNull(meterId);
|
||||
Assert.assertEquals(meterId.getName(), "test_meter");
|
||||
Assert.assertEquals(meterId.getType(), MeterId.MeterType.COUNTER);
|
||||
Assert.assertEquals(meterId.getTags(), Arrays.asList(new MeterId.Tag("k1", "v1")));
|
||||
|
||||
// same name and tags
|
||||
TestCounter.Builder meterBuilder2 = Mockito.spy(TestCounter.create("test_meter"));
|
||||
meterBuilder2.tag("k1", "v1");
|
||||
final Counter testCounter2 = meterBuilder2.build();
|
||||
Assert.assertNotNull(testCounter2);
|
||||
verify(meterBuilder2, times(0)).create(any());
|
||||
verify(meterBuilder2, times(1)).accept(any());
|
||||
|
||||
// empty name
|
||||
try {
|
||||
TestCounter.create(null).build();
|
||||
throw new RuntimeException();
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
// correct meter id
|
||||
final MeterId tmpMeterId = new MeterId("test_meter_builder", MeterId.MeterType.COUNTER, Collections.emptyList());
|
||||
new TestCounter.Builder(tmpMeterId).build();
|
||||
|
||||
final MeterId copiedMeterId = tmpMeterId.copyTo("test_meter_builder", MeterId.MeterType.GAUGE);
|
||||
// not matched type
|
||||
try {
|
||||
new TestCounter.Builder(copiedMeterId).build();
|
||||
throw new RuntimeException();
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
// empty meterId
|
||||
try {
|
||||
MeterId emptyId = null;
|
||||
new TestCounter.Builder(emptyId).build();
|
||||
throw new RuntimeException();
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
// same name
|
||||
Assert.assertEquals(
|
||||
TestCounter.create("test").build(),
|
||||
TestCounter.create("test").build()
|
||||
);
|
||||
|
||||
// same name and tag
|
||||
Assert.assertEquals(
|
||||
TestCounter.create("test").tag("k1", "v1").build(),
|
||||
TestCounter.create("test").tag("k1", "v1").build()
|
||||
);
|
||||
|
||||
// not orders tags
|
||||
Assert.assertEquals(
|
||||
TestCounter.create("test").tag("k2", "v2").tag("k3", "v3").build(),
|
||||
TestCounter.create("test").tag("k3", "v3").tag("k2", "v2").build()
|
||||
);
|
||||
|
||||
// not same name
|
||||
Assert.assertNotEquals(
|
||||
TestCounter.create("test1").build(),
|
||||
TestCounter.create("test2").build()
|
||||
);
|
||||
|
||||
// same name, not same tag
|
||||
Assert.assertNotEquals(
|
||||
TestCounter.create("test3").tag("k1", "v1").build(),
|
||||
TestCounter.create("test4").tag("k1", "v2").build()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetName() {
|
||||
final Counter meter = TestCounter.create("test").build();
|
||||
Assert.assertEquals(meter.getName(), "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTag() {
|
||||
final Counter meter = TestCounter.create("test").tag("k1", "v1").build();
|
||||
Assert.assertEquals(meter.getTag("k1"), "v1");
|
||||
Assert.assertNull(meter.getTag("k2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMeterId() {
|
||||
final Counter meter = TestCounter.create("test").tag("k1", "v1").build();
|
||||
final MeterId tmpMeterId = new MeterId("test", MeterId.MeterType.COUNTER,
|
||||
Arrays.asList(new MeterId.Tag("k1", "v1")));
|
||||
final TestCounter counter = (TestCounter) meter;
|
||||
Assert.assertEquals(tmpMeterId, counter.getMeterId());
|
||||
}
|
||||
|
||||
private static class TestCounter extends AbstractMeter implements Counter {
|
||||
private TestCounter(MeterId meterId) {
|
||||
super(meterId);
|
||||
}
|
||||
|
||||
public static TestCounter.Builder create(String name) {
|
||||
return new Builder(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(double count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double get() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static class Builder extends AbstractBuilder<Builder, Counter, TestCounter> {
|
||||
|
||||
public Builder(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public Builder(MeterId meterId) {
|
||||
super(meterId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestCounter create(MeterId meterId) {
|
||||
return new TestCounter(meterId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void accept(TestCounter meter) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId.MeterType getType() {
|
||||
return MeterId.MeterType.COUNTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class CounterTest {
|
||||
|
||||
@Test
|
||||
public void testBuild() {
|
||||
Counter counter1 = MeterFactory.counter("test_counter").tag("k1", "v1").build();
|
||||
Assert.assertNotNull(counter1);
|
||||
|
||||
final Counter counter2 = MeterFactory.counter(new MeterId("test_counter", MeterId.MeterType.COUNTER, Arrays.asList(new MeterId.Tag("k1", "v1")))).build();
|
||||
Assert.assertNotNull(counter2);
|
||||
Assert.assertEquals(counter1, counter2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncrement() {
|
||||
Counter counter = MeterFactory.counter("test_counter1").tag("k1", "v1").build();
|
||||
counter.increment(1);
|
||||
Assert.assertEquals(counter.get(), 1d, 0.0);
|
||||
|
||||
counter.increment(1.5);
|
||||
Assert.assertEquals(counter.get(), 2.5d, 0.0);
|
||||
|
||||
counter.increment(-1d);
|
||||
Assert.assertEquals(counter.get(), 1.5d, 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
Counter counter = MeterFactory.counter("test_counter_accept")
|
||||
.tag("k1", "v1")
|
||||
.mode(Counter.Mode.INCREMENT)
|
||||
.build();
|
||||
|
||||
// Check the same mode
|
||||
try {
|
||||
MeterFactory.counter("test_counter_accept")
|
||||
.tag("k1", "v1")
|
||||
.mode(Counter.Mode.INCREMENT)
|
||||
.build();
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
// Check the different mode
|
||||
try {
|
||||
MeterFactory.counter("test_counter_accept")
|
||||
.tag("k1", "v1")
|
||||
.mode(Counter.Mode.RATE)
|
||||
.build();
|
||||
throw new IllegalStateException();
|
||||
} catch (IllegalStateException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAgentGetWithoutRate() {
|
||||
final Counter counter = MeterFactory.counter("test_counter_without_rate")
|
||||
.tag("k1", "v1")
|
||||
.build();
|
||||
|
||||
final CounterImpl counterImpl = (CounterImpl) counter;
|
||||
counter.increment(1);
|
||||
Assert.assertEquals(counterImpl.agentGet(), 1d, 0.0);
|
||||
Assert.assertEquals(counterImpl.agentGet(), 1d, 0.0);
|
||||
|
||||
counter.increment(1.5);
|
||||
counter.increment(-0.5);
|
||||
Assert.assertEquals(counterImpl.agentGet(), 2d, 0.0);
|
||||
Assert.assertEquals(counterImpl.agentGet(), 2d, 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAgentGetWithRate() {
|
||||
final Counter counter = MeterFactory.counter("test_counter_with_rate")
|
||||
.tag("k1", "v1")
|
||||
.mode(Counter.Mode.RATE).build();
|
||||
|
||||
final CounterImpl counterImpl = (CounterImpl) counter;
|
||||
counter.increment(1);
|
||||
Assert.assertEquals(counterImpl.agentGet(), 1d, 0.0);
|
||||
Assert.assertEquals(counterImpl.agentGet(), 0d, 0.0);
|
||||
|
||||
counter.increment(1.5);
|
||||
counter.increment(-0.5);
|
||||
Assert.assertEquals(counterImpl.agentGet(), 1d, 0.0);
|
||||
Assert.assertEquals(counterImpl.agentGet(), 0d, 0.0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class GaugeTest {
|
||||
|
||||
@Test
|
||||
public void testBuild() {
|
||||
Gauge gauge = MeterFactory.gauge("test_gauge1", () -> 1d).tag("k1", "v1").build();
|
||||
Assert.assertNotNull(gauge);
|
||||
|
||||
// Same meter name and new getter
|
||||
try {
|
||||
MeterFactory.gauge("test_gauge1", () -> 1d).tag("k1", "v1").build();
|
||||
throw new IllegalStateException();
|
||||
} catch (IllegalStateException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
// Missing getter reference
|
||||
try {
|
||||
MeterFactory.gauge("test_gauge2", null).build();
|
||||
throw new IllegalStateException();
|
||||
} catch (IllegalStateException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
// Build by meterId
|
||||
final Gauge gauge1 = MeterFactory.gauge(new MeterId("test_gauge3", MeterId.MeterType.GAUGE, Collections.emptyList()), () -> 1d).build();
|
||||
Assert.assertNotNull(gauge1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet() {
|
||||
Gauge gauge = MeterFactory.gauge("test_gauge3", () -> 1d).tag("k1", "v1").build();
|
||||
Assert.assertEquals(gauge.get(), 1d, 0.0);
|
||||
|
||||
// Need throw exception
|
||||
gauge = MeterFactory.gauge("test_gauge4", () -> Double.valueOf(1 / 0)).build();
|
||||
try {
|
||||
gauge.get();
|
||||
throw new IllegalStateException();
|
||||
} catch (IllegalStateException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class HistogramTest {
|
||||
|
||||
@Test
|
||||
public void testBuild() {
|
||||
// normal
|
||||
Histogram histogram = MeterFactory.histogram("test_histogram1").steps(Arrays.asList(1d, 5d, 10d)).minValue(-10)
|
||||
.tag("k1", "v1").build();
|
||||
verifyHistogram(histogram, -10d, 0, 1d, 0, 5d, 0, 10d, 0);
|
||||
|
||||
// except value bigger than first bucket
|
||||
try {
|
||||
histogram = HistogramImpl.create("test_histogram2").steps(Arrays.asList(1d, 5d, 10d)).minValue(2).build();
|
||||
throw new IllegalStateException("valid failed");
|
||||
} catch (IllegalStateException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
Assert.assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
|
||||
// except min value is equals first step
|
||||
histogram = HistogramImpl.create("test_histogram3").steps(Arrays.asList(1d, 5d, 10d)).minValue(1d)
|
||||
.tag("k1", "v1").build();
|
||||
verifyHistogram(histogram, 1d, 0, 5d, 0, 10d, 0);
|
||||
|
||||
// empty step
|
||||
try {
|
||||
HistogramImpl.create("test").build();
|
||||
throw new IllegalStateException();
|
||||
} catch (IllegalStateException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
Assert.assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
|
||||
// Build by meterId
|
||||
histogram = MeterFactory.histogram(new MeterId("test_histogram4", MeterId.MeterType.HISTOGRAM, Collections.emptyList()))
|
||||
.steps(Arrays.asList(1d, 5d, 10d)).minValue(0d).build();
|
||||
Assert.assertNotNull(histogram);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccept() {
|
||||
MeterFactory.histogram("test_histogram_accept").steps(Arrays.asList(1d, 3d, 5d)).minValue(0).build();
|
||||
|
||||
// same histogram
|
||||
HistogramImpl.create("test_histogram_accept").steps(Arrays.asList(1d, 3d, 5d)).minValue(0).build();
|
||||
|
||||
// not same steps size
|
||||
try {
|
||||
HistogramImpl.create("test_histogram_accept").steps(Arrays.asList(1d, 3d, 5d, 7d)).minValue(-1).build();
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
// not same steps value
|
||||
try {
|
||||
HistogramImpl.create("test_histogram_accept").steps(Arrays.asList(1d, 3d, 6d)).minValue(-1).build();
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddValue() {
|
||||
Histogram histogram = MeterFactory.histogram("test_histogram5").steps(Arrays.asList(1d, 5d, 10d)).minValue(-10)
|
||||
.tag("k1", "v1").build();
|
||||
|
||||
// single value
|
||||
histogram.addValue(2);
|
||||
verifyHistogram(histogram, -10d, 0L, 1d, 1L, 5d, 0L, 10d, 0L);
|
||||
|
||||
// multiple values
|
||||
histogram.addValue(2);
|
||||
histogram.addValue(2);
|
||||
histogram.addValue(9);
|
||||
verifyHistogram(histogram, -10d, 0L, 1d, 3L, 5d, 1L, 10d, 0L);
|
||||
|
||||
// un-support value
|
||||
histogram.addValue(-11);
|
||||
verifyHistogram(histogram, -10d, 0L, 1d, 3L, 5d, 1L, 10d, 0L);
|
||||
|
||||
// max value
|
||||
histogram.addValue(Integer.MAX_VALUE);
|
||||
histogram.addValue(9);
|
||||
histogram.addValue(10);
|
||||
verifyHistogram(histogram, -10d, 0L, 1d, 3L, 5d, 2L, 10d, 2L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify histogram bucket counts
|
||||
*/
|
||||
public static void verifyHistogram(Histogram histogram, double... buckets) {
|
||||
Assert.assertNotNull(histogram);
|
||||
final Histogram.Bucket[] histogramBuckets = histogram.getBuckets();
|
||||
Assert.assertEquals(histogramBuckets.length, buckets.length / 2);
|
||||
for (int i = 0; i < histogramBuckets.length; i++) {
|
||||
Assert.assertNotNull(buckets[i]);
|
||||
Assert.assertEquals(buckets[i * 2], histogramBuckets[i].getBucket(), 0.0);
|
||||
Assert.assertEquals(buckets[i * 2 + 1], histogramBuckets[i].getCount(), 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.AbstractMeter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.MeterCenter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class MeterCenterTest {
|
||||
|
||||
private Map<MeterId, AbstractMeter> meterMap;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
meterMap = Whitebox.getInternalState(MeterCenter.class, "METER_MAP");
|
||||
meterMap.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateOrGet() {
|
||||
// null
|
||||
Assert.assertNull(MeterCenter.getOrCreateMeter(null));
|
||||
|
||||
// simple counter
|
||||
final Counter counter = MeterFactory.counter("test").build();
|
||||
final MeterId counterMeterId = Whitebox.getInternalState(counter, "meterId");
|
||||
Assert.assertNotNull(counterMeterId);
|
||||
Assert.assertNotNull(meterMap.get(counterMeterId));
|
||||
Assert.assertEquals(meterMap.get(counterMeterId), counter);
|
||||
|
||||
// same counter
|
||||
Assert.assertEquals(counter, MeterFactory.counter("test").build());
|
||||
Assert.assertEquals(meterMap.size(), 1);
|
||||
Assert.assertNotNull(meterMap.get(counterMeterId));
|
||||
Assert.assertEquals(meterMap.get(counterMeterId), counter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveMeter() {
|
||||
final Counter counter = MeterFactory.counter("test").build();
|
||||
Assert.assertEquals(meterMap.size(), 1);
|
||||
final MeterId counterMeterId = Whitebox.getInternalState(counter, "meterId");
|
||||
MeterCenter.removeMeter(counterMeterId);
|
||||
Assert.assertEquals(meterMap.size(), 0);
|
||||
|
||||
// not registered meter id
|
||||
final MeterId newMeterId = new MeterId("test1", MeterId.MeterType.COUNTER, Collections.emptyList());
|
||||
MeterCenter.removeMeter(newMeterId);
|
||||
Assert.assertEquals(meterMap.size(), 0);
|
||||
|
||||
// remove null
|
||||
MeterCenter.removeMeter(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class MeterIdTest {
|
||||
|
||||
@Test
|
||||
public void testCopyTo() {
|
||||
final MeterId meterId = new MeterId("test", MeterId.MeterType.COUNTER, Arrays.asList(new MeterId.Tag("k1", "v1")));
|
||||
final MeterId copied = meterId.copyTo("test_copied", MeterId.MeterType.GAUGE);
|
||||
|
||||
Assert.assertEquals("test_copied", copied.getName());
|
||||
Assert.assertEquals(MeterId.MeterType.GAUGE, copied.getType());
|
||||
Assert.assertEquals(meterId.getTags(), copied.getTags());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
~ contributor license agreements. See the NOTICE file distributed with
|
||||
~ this work for additional information regarding copyright ownership.
|
||||
~ The ASF licenses this file to You 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.
|
||||
~
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>apm-application-toolkit</artifactId>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-toolkit-micrometer-registry</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<micrometer-core.version>1.5.0</micrometer-core.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<artifactId>apm-toolkit-meter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-core</artifactId>
|
||||
<version>${micrometer-core.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.core.instrument.util.TimeUtils;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Histogram;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Help to build the meter
|
||||
*/
|
||||
public class MeterBuilder {
|
||||
|
||||
/**
|
||||
* Build the counter
|
||||
*/
|
||||
public static Counter buildCounter(MeterId meterId, SkywalkingConfig config) {
|
||||
return MeterFactory.counter(meterId)
|
||||
.mode(getCounterMode(meterId, config))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get counter mode
|
||||
*/
|
||||
public static Counter.Mode getCounterMode(MeterId meterId, SkywalkingConfig config) {
|
||||
return config.isRateCounter(meterId.getName()) ? Counter.Mode.RATE : Counter.Mode.INCREMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the histogram
|
||||
* @return return histogram if support
|
||||
*/
|
||||
public static Optional<Histogram> buildHistogram(MeterId meterId, boolean supportsAggregablePercentiles,
|
||||
DistributionStatisticConfig distributionStatisticConfig,
|
||||
boolean useNanoTime) {
|
||||
if (!distributionStatisticConfig.isPublishingHistogram()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
final NavigableSet<Double> buckets = distributionStatisticConfig.getHistogramBuckets(supportsAggregablePercentiles);
|
||||
final List<Double> steps = buckets.stream().sorted(Double::compare)
|
||||
.map(t -> useNanoTime ? TimeUtils.nanosToUnit(t, TimeUnit.MILLISECONDS) : t).collect(Collectors.toList());
|
||||
|
||||
final Histogram.Builder histogramBuilder = MeterFactory.histogram(
|
||||
meterId.copyTo(meterId.getName() + "_histogram", MeterId.MeterType.HISTOGRAM)).steps(steps);
|
||||
final Double minimumExpectedValueAsDouble = distributionStatisticConfig.getMinimumExpectedValueAsDouble();
|
||||
if (minimumExpectedValueAsDouble != null) {
|
||||
histogramBuilder.minValue(useNanoTime ?
|
||||
TimeUtils.nanosToUnit(minimumExpectedValueAsDouble, TimeUnit.MILLISECONDS) : minimumExpectedValueAsDouble);
|
||||
}
|
||||
return Optional.of(histogramBuilder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert micrometer {@link Meter.Id} to skywalking {@link MeterId}
|
||||
*/
|
||||
public static MeterId convertId(Meter.Id id, String name) {
|
||||
MeterId.MeterType type;
|
||||
switch (id.getType()) {
|
||||
case COUNTER:
|
||||
type = MeterId.MeterType.COUNTER;
|
||||
break;
|
||||
case GAUGE:
|
||||
type = MeterId.MeterType.GAUGE;
|
||||
break;
|
||||
default:
|
||||
// other meter need to use multiple customize meter
|
||||
type = MeterId.MeterType.HISTOGRAM;
|
||||
break;
|
||||
}
|
||||
final List<MeterId.Tag> tags = id.getTags().stream().map(t -> new MeterId.Tag(t.getKey(), t.getValue())).collect(Collectors.toList());
|
||||
final MeterId meterId = new MeterId(name, type, tags);
|
||||
return meterId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.config.MeterRegistryConfig;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Skywalking config
|
||||
*/
|
||||
public class SkywalkingConfig implements MeterRegistryConfig {
|
||||
|
||||
public static final SkywalkingConfig DEFAULT = new SkywalkingConfig(Collections.emptyList());
|
||||
|
||||
/**
|
||||
* Supporting rate by agent side counter names
|
||||
*/
|
||||
private final List<String> rateCounterNames;
|
||||
|
||||
public SkywalkingConfig(List<String> rateCounterNames) {
|
||||
this.rateCounterNames = rateCounterNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is counter need rate by agent side
|
||||
*/
|
||||
public boolean isRateCounter(String name) {
|
||||
return rateCounterNames == null ? false : rateCounterNames.contains(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String prefix() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String key) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractMeter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
|
||||
/**
|
||||
* Wrapper the {@link CounterImpl} to {@link io.micrometer.core.instrument.Counter}
|
||||
*/
|
||||
public class SkywalkingCounter extends AbstractMeter implements io.micrometer.core.instrument.Counter {
|
||||
private final Counter counter;
|
||||
|
||||
SkywalkingCounter(Id id, Counter counter) {
|
||||
super(id);
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(double amount) {
|
||||
this.counter.increment(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double count() {
|
||||
return counter.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.AbstractBuilder;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
/**
|
||||
* Work for custom {@link Measurement}, support the skywalking rate mode
|
||||
*/
|
||||
public class SkywalkingCustomCounter extends CounterImpl {
|
||||
|
||||
private final Measurement measurement;
|
||||
|
||||
protected SkywalkingCustomCounter(MeterId meterId, Measurement measurement, SkywalkingConfig config) {
|
||||
super(meterId, MeterBuilder.getCounterMode(meterId, config));
|
||||
this.measurement = measurement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double get() {
|
||||
return measurement.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom counter builder
|
||||
*/
|
||||
public static class Builder extends AbstractBuilder<Builder, Counter, SkywalkingCustomCounter> {
|
||||
private final Measurement measurement;
|
||||
private final SkywalkingConfig config;
|
||||
|
||||
public Builder(MeterId meterId, Measurement measurement, SkywalkingConfig config) {
|
||||
super(meterId);
|
||||
this.measurement = measurement;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SkywalkingCustomCounter create(MeterId meterId) {
|
||||
return new SkywalkingCustomCounter(meterId, measurement, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MeterId.MeterType getType() {
|
||||
return MeterId.MeterType.COUNTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractDistributionSummary;
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Gauge;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Histogram;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.DoubleAccumulator;
|
||||
|
||||
/**
|
||||
* Combine the meters to {@link io.micrometer.core.instrument.DistributionSummary}
|
||||
*/
|
||||
public class SkywalkingDistributionSummary extends AbstractDistributionSummary {
|
||||
|
||||
/**
|
||||
* Summary record count
|
||||
*/
|
||||
private final Counter counter;
|
||||
|
||||
/**
|
||||
* Total summary count
|
||||
*/
|
||||
private final Counter sum;
|
||||
|
||||
/**
|
||||
* Max amount in this summary
|
||||
*/
|
||||
private final Gauge max;
|
||||
private final DoubleAccumulator maxAdder;
|
||||
|
||||
/**
|
||||
* Histogram of summary
|
||||
*/
|
||||
private final Optional<Histogram> histogram;
|
||||
|
||||
protected SkywalkingDistributionSummary(Id id, MeterId meterId, SkywalkingConfig config, Clock clock,
|
||||
DistributionStatisticConfig distributionStatisticConfig, double scale,
|
||||
boolean supportsAggregablePercentiles) {
|
||||
super(id, clock, distributionStatisticConfig, scale, supportsAggregablePercentiles);
|
||||
|
||||
// meter base name
|
||||
String baseName = meterId.getName();
|
||||
|
||||
this.counter = MeterBuilder.buildCounter(meterId.copyTo(baseName + "_count", MeterId.MeterType.COUNTER), config);
|
||||
this.sum = MeterBuilder.buildCounter(meterId.copyTo(baseName + "_sum", MeterId.MeterType.COUNTER), config);
|
||||
this.maxAdder = new DoubleAccumulator((a, b) -> a > b ? a : b, 0.000);
|
||||
this.max = MeterFactory.gauge(meterId.copyTo(baseName + "_max", MeterId.MeterType.GAUGE),
|
||||
() -> maxAdder.doubleValue()).build();
|
||||
|
||||
this.histogram = MeterBuilder.buildHistogram(meterId, supportsAggregablePercentiles, distributionStatisticConfig, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recordNonNegative(double amount) {
|
||||
counter.increment(1d);
|
||||
this.sum.increment(amount);
|
||||
maxAdder.accumulate(amount);
|
||||
|
||||
histogram.ifPresent(h -> h.addValue(amount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return (long) counter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalAmount() {
|
||||
return sum.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double max() {
|
||||
return max.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.core.instrument.internal.DefaultLongTaskTimer;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Combine the meters to {@link io.micrometer.core.instrument.LongTaskTimer}
|
||||
*/
|
||||
public class SkywalkingLongTaskTimer extends DefaultLongTaskTimer {
|
||||
|
||||
public SkywalkingLongTaskTimer(Id id, MeterId meterId, Clock clock, TimeUnit baseTimeUnit, DistributionStatisticConfig distributionStatisticConfig, boolean supportsAggregablePercentiles) {
|
||||
super(id, clock, baseTimeUnit, distributionStatisticConfig, supportsAggregablePercentiles);
|
||||
final String baseName = meterId.getName();
|
||||
|
||||
MeterFactory.gauge(
|
||||
meterId.copyTo(baseName + "_active_count", MeterId.MeterType.GAUGE), () -> (double) activeTasks()).build();
|
||||
MeterFactory.gauge(
|
||||
meterId.copyTo(baseName + "_duration_sum", MeterId.MeterType.GAUGE), () -> duration(TimeUnit.MILLISECONDS)).build();
|
||||
MeterFactory.gauge(
|
||||
meterId.copyTo(baseName + "_max", MeterId.MeterType.GAUGE), () -> max(TimeUnit.MILLISECONDS)).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.FunctionCounter;
|
||||
import io.micrometer.core.instrument.FunctionTimer;
|
||||
import io.micrometer.core.instrument.LongTaskTimer;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Statistic;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.micrometer.core.instrument.cumulative.CumulativeFunctionCounter;
|
||||
import io.micrometer.core.instrument.cumulative.CumulativeFunctionTimer;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
|
||||
import io.micrometer.core.instrument.internal.DefaultGauge;
|
||||
import io.micrometer.core.instrument.internal.DefaultMeter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.MeterCenter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
import java.util.function.ToLongFunction;
|
||||
|
||||
/**
|
||||
* Skywalking adapt the micrometer registry.
|
||||
*/
|
||||
public class SkywalkingMeterRegistry extends MeterRegistry {
|
||||
|
||||
private final SkywalkingConfig config;
|
||||
|
||||
public SkywalkingMeterRegistry() {
|
||||
this(SkywalkingConfig.DEFAULT, Clock.SYSTEM);
|
||||
}
|
||||
|
||||
public SkywalkingMeterRegistry(SkywalkingConfig config) {
|
||||
this(config, Clock.SYSTEM);
|
||||
}
|
||||
|
||||
public SkywalkingMeterRegistry(Clock clock) {
|
||||
this(SkywalkingConfig.DEFAULT, clock);
|
||||
}
|
||||
|
||||
public SkywalkingMeterRegistry(SkywalkingConfig config, Clock clock) {
|
||||
super(clock);
|
||||
this.config = config;
|
||||
config().namingConvention(NamingConvention.snakeCase);
|
||||
config().onMeterRemoved(this::onMeterRemoved);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> io.micrometer.core.instrument.Gauge newGauge(Meter.Id id, T obj, ToDoubleFunction<T> valueFunction) {
|
||||
final MeterId meterId = convertId(id);
|
||||
MeterFactory.gauge(meterId, () -> valueFunction.applyAsDouble(obj)).build();
|
||||
return new DefaultGauge<>(id, obj, valueFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected io.micrometer.core.instrument.Counter newCounter(Meter.Id id) {
|
||||
final MeterId meterId = convertId(id);
|
||||
return new SkywalkingCounter(id, MeterBuilder.buildCounter(meterId, config));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LongTaskTimer newLongTaskTimer(Meter.Id id, DistributionStatisticConfig distributionStatisticConfig) {
|
||||
final MeterId meterId = convertId(id);
|
||||
return new SkywalkingLongTaskTimer(id, meterId, clock, TimeUnit.MILLISECONDS, distributionStatisticConfig, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Timer newTimer(Meter.Id id, DistributionStatisticConfig distributionStatisticConfig, PauseDetector pauseDetector) {
|
||||
final MeterId meterId = convertId(id);
|
||||
return new SkywalkingTimer(id, meterId, config, clock, distributionStatisticConfig, pauseDetector, TimeUnit.MILLISECONDS, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DistributionSummary newDistributionSummary(Meter.Id id, DistributionStatisticConfig distributionStatisticConfig, double scale) {
|
||||
final MeterId meterId = convertId(id);
|
||||
return new SkywalkingDistributionSummary(id, meterId, config, clock, distributionStatisticConfig, scale, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Meter newMeter(Meter.Id id, Meter.Type type, Iterable<Measurement> measurements) {
|
||||
final MeterId meterId = convertId(id);
|
||||
final String baseName = meterId.getName();
|
||||
|
||||
measurements.forEach(m -> {
|
||||
String meterName = baseName;
|
||||
boolean isCounter = false;
|
||||
switch (m.getStatistic()) {
|
||||
case TOTAL:
|
||||
case TOTAL_TIME:
|
||||
meterName = baseName + "_sum";
|
||||
isCounter = true;
|
||||
break;
|
||||
case COUNT:
|
||||
isCounter = true;
|
||||
break;
|
||||
case MAX:
|
||||
meterName = baseName + "_max";
|
||||
break;
|
||||
case ACTIVE_TASKS:
|
||||
meterName = baseName + "_active_count";
|
||||
break;
|
||||
case DURATION:
|
||||
meterName = baseName + "_duration_sum";
|
||||
break;
|
||||
}
|
||||
|
||||
if (isCounter) {
|
||||
new SkywalkingCustomCounter.Builder(meterId.copyTo(meterName, MeterId.MeterType.COUNTER), m, config).build();
|
||||
} else {
|
||||
MeterFactory.gauge(meterId.copyTo(meterName, MeterId.MeterType.GAUGE), () -> m.getValue()).build();
|
||||
}
|
||||
});
|
||||
|
||||
return new DefaultMeter(id, type, measurements);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> FunctionTimer newFunctionTimer(Meter.Id id, T obj, ToLongFunction<T> countFunction, ToDoubleFunction<T> totalTimeFunction, TimeUnit totalTimeFunctionUnit) {
|
||||
final MeterId meterId = convertId(id);
|
||||
FunctionTimer ft = new CumulativeFunctionTimer<>(id, obj, countFunction, totalTimeFunction, totalTimeFunctionUnit, getBaseTimeUnit());
|
||||
final String baseName = meterId.getName();
|
||||
|
||||
MeterFactory.gauge(
|
||||
meterId.copyTo(baseName + "_count", MeterId.MeterType.GAUGE), () -> ft.count()).build();
|
||||
MeterFactory.gauge(
|
||||
meterId.copyTo(baseName + "_sum", MeterId.MeterType.GAUGE), () -> ft.totalTime(TimeUnit.MILLISECONDS)).build();
|
||||
return ft;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> FunctionCounter newFunctionCounter(Meter.Id id, T obj, ToDoubleFunction<T> countFunction) {
|
||||
final MeterId meterId = convertId(id);
|
||||
FunctionCounter fc = new CumulativeFunctionCounter<>(id, obj, countFunction);
|
||||
|
||||
new SkywalkingCustomCounter.Builder(meterId, new Measurement(() -> countFunction.applyAsDouble(obj), Statistic.COUNT), config).build();
|
||||
return fc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TimeUnit getBaseTimeUnit() {
|
||||
return TimeUnit.MILLISECONDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DistributionStatisticConfig defaultHistogramConfig() {
|
||||
return DistributionStatisticConfig.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify on the meter has been removed
|
||||
*/
|
||||
private void onMeterRemoved(Meter meter) {
|
||||
final MeterId meterId = convertId(meter.getId());
|
||||
MeterCenter.removeMeter(meterId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the micrometer meter id to skywalking meter id
|
||||
*/
|
||||
private MeterId convertId(Meter.Id id) {
|
||||
return MeterBuilder.convertId(id, getConventionName(id));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractTimer;
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Gauge;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Histogram;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.DoubleAccumulator;
|
||||
|
||||
public class SkywalkingTimer extends AbstractTimer {
|
||||
|
||||
/**
|
||||
* Execute finished count
|
||||
*/
|
||||
private final Counter counter;
|
||||
|
||||
/**
|
||||
* Total execute finished duration
|
||||
*/
|
||||
private final Counter sum;
|
||||
|
||||
/**
|
||||
* Max duration of execute finished time
|
||||
*/
|
||||
private final Gauge max;
|
||||
private final DoubleAccumulator maxAdder;
|
||||
|
||||
/**
|
||||
* Histogram of execute finished duration
|
||||
*/
|
||||
private final Optional<Histogram> histogram;
|
||||
|
||||
protected SkywalkingTimer(Id id, MeterId meterId, SkywalkingConfig config, Clock clock,
|
||||
DistributionStatisticConfig distributionStatisticConfig, PauseDetector pauseDetector,
|
||||
TimeUnit baseTimeUnit, boolean supportsAggregablePercentiles) {
|
||||
super(id, clock, distributionStatisticConfig, pauseDetector, baseTimeUnit, supportsAggregablePercentiles);
|
||||
|
||||
// meter base name
|
||||
String baseName = meterId.getName();
|
||||
|
||||
this.counter = MeterBuilder.buildCounter(meterId.copyTo(baseName + "_count", MeterId.MeterType.COUNTER), config);
|
||||
this.sum = MeterBuilder.buildCounter(meterId.copyTo(baseName + "_sum", MeterId.MeterType.COUNTER), config);
|
||||
this.maxAdder = new DoubleAccumulator((a, b) -> a > b ? a : b, 0.000);
|
||||
this.max = MeterFactory.gauge(meterId.copyTo(baseName + "_max", MeterId.MeterType.GAUGE),
|
||||
() -> maxAdder.doubleValue()).build();
|
||||
|
||||
this.histogram = MeterBuilder.buildHistogram(meterId, supportsAggregablePercentiles, distributionStatisticConfig, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recordNonNegative(long amount, TimeUnit unit) {
|
||||
counter.increment(1d);
|
||||
final long amountToMillisecond = TimeUnit.MILLISECONDS.convert(amount, unit);
|
||||
sum.increment(amountToMillisecond);
|
||||
maxAdder.accumulate(amountToMillisecond);
|
||||
|
||||
histogram.ifPresent(h -> h.addValue(amountToMillisecond));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return (long) counter.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalTime(TimeUnit unit) {
|
||||
return unit.convert((long) sum.get(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double max(TimeUnit unit) {
|
||||
return unit.convert((long) max.get(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Histogram;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MeterBuilderTest {
|
||||
|
||||
@Test
|
||||
public void testBuildHistogram() {
|
||||
final MeterId meterId = new MeterId("test", MeterId.MeterType.COUNTER,
|
||||
Arrays.asList(new MeterId.Tag("k1", "v1")));
|
||||
|
||||
// Build a new distribution config
|
||||
final DistributionStatisticConfig statisticConfig = DistributionStatisticConfig.builder()
|
||||
.serviceLevelObjectives(Duration.ofMillis(1).toNanos(), Duration.ofMillis(5).toNanos(), Duration.ofMillis(10).toNanos())
|
||||
.minimumExpectedValue(0d).build();
|
||||
|
||||
// Check buckets
|
||||
final Optional<Histogram> histogramOptional = MeterBuilder.buildHistogram(meterId, true, statisticConfig, true);
|
||||
final Histogram histogram = histogramOptional.orElse(null);
|
||||
Assert.assertNotNull(histogram);
|
||||
final Histogram.Bucket[] buckets = histogram.getBuckets();
|
||||
Assert.assertEquals(4, buckets.length);
|
||||
Assert.assertEquals(0d, buckets[0].getBucket(), 0.0);
|
||||
Assert.assertEquals(1d, buckets[1].getBucket(), 0.0);
|
||||
Assert.assertEquals(5d, buckets[2].getBucket(), 0.0);
|
||||
Assert.assertEquals(10d, buckets[3].getBucket(), 0.0);
|
||||
|
||||
// Check meter id
|
||||
Assert.assertEquals("test_histogram", histogram.getMeterId().getName());
|
||||
Assert.assertEquals(MeterId.MeterType.HISTOGRAM, histogram.getMeterId().getType());
|
||||
Assert.assertEquals(Arrays.asList(new MeterId.Tag("k1", "v1")), histogram.getMeterId().getTags());
|
||||
|
||||
// Don't need the histogram
|
||||
Assert.assertNull(MeterBuilder.buildHistogram(meterId, true, DistributionStatisticConfig.DEFAULT, true).orElse(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertId() {
|
||||
final List<MeterId.Tag> meterTags = Arrays.asList(new MeterId.Tag("k1", "v1"));
|
||||
|
||||
// Counter type check
|
||||
final Meter.Id counterId = new Meter.Id("test", Tags.of("k1", "v1"), null, "test", Meter.Type.COUNTER);
|
||||
assertId(MeterBuilder.convertId(counterId, "test"), "test", MeterId.MeterType.COUNTER, meterTags);
|
||||
|
||||
// Gauge type check
|
||||
final Meter.Id gaugeId = new Meter.Id("test", Tags.of("k1", "v1"), null, "test", Meter.Type.GAUGE);
|
||||
assertId(MeterBuilder.convertId(gaugeId, "test"), "test", MeterId.MeterType.GAUGE, meterTags);
|
||||
|
||||
// Histogram type check
|
||||
final Meter.Id otherId = new Meter.Id("test", Tags.of("k1", "v1"), null, "test", Meter.Type.DISTRIBUTION_SUMMARY);
|
||||
assertId(MeterBuilder.convertId(otherId, "test"), "test", MeterId.MeterType.HISTOGRAM, meterTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the meter id
|
||||
*/
|
||||
private void assertId(MeterId meterId, String name, MeterId.MeterType type, List<MeterId.Tag> tags) {
|
||||
Assert.assertEquals(name, meterId.getName());
|
||||
Assert.assertEquals(type, meterId.getType());
|
||||
Assert.assertEquals(tags, meterId.getTags());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class SkywalkingCounterTest extends SkywalkingMeterBaseTest {
|
||||
|
||||
@Test
|
||||
public void testCounter() {
|
||||
// Creating a simplify micrometer counter
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
Counter counter = registry.counter("test_counter", "skywalking", "test");
|
||||
|
||||
// Check Skywalking counter type
|
||||
Assert.assertTrue(counter instanceof SkywalkingCounter);
|
||||
final SkywalkingCounter skywalkingCounter = (SkywalkingCounter) counter;
|
||||
final org.apache.skywalking.apm.toolkit.meter.Counter realCounter =
|
||||
Whitebox.getInternalState(skywalkingCounter, "counter");
|
||||
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
|
||||
|
||||
// Simplify increment
|
||||
skywalkingCounter.increment(1d);
|
||||
assertCounter(realCounter, "test_counter", tags, 1);
|
||||
Assert.assertEquals(1d, skywalkingCounter.count(), 0.0);
|
||||
|
||||
// Multiple increment
|
||||
skywalkingCounter.increment(2d);
|
||||
skywalkingCounter.increment(3d);
|
||||
assertCounter(realCounter, "test_counter", tags, 6);
|
||||
Assert.assertEquals(6d, skywalkingCounter.count(), 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRateCounter() {
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry(new SkywalkingConfig(Arrays.asList("test_rate_counter")));
|
||||
final Counter counter = registry.counter("test_rate_counter", "skywalking", "test");
|
||||
|
||||
// Check Skywalking counter type
|
||||
Assert.assertTrue(counter instanceof SkywalkingCounter);
|
||||
final SkywalkingCounter skywalkingCounter = (SkywalkingCounter) counter;
|
||||
final CounterImpl realCounter =
|
||||
Whitebox.getInternalState(skywalkingCounter, "counter");
|
||||
|
||||
// check mode
|
||||
final org.apache.skywalking.apm.toolkit.meter.Counter.Mode counterMode = Whitebox.getInternalState(realCounter, "mode");
|
||||
Assert.assertEquals(org.apache.skywalking.apm.toolkit.meter.Counter.Mode.RATE, counterMode);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.Statistic;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class SkywalkingCustomCounterTest extends SkywalkingMeterBaseTest {
|
||||
|
||||
@Test
|
||||
public void testBuild() {
|
||||
// Creating a custom measurement
|
||||
Measurement measurement = new Measurement(() -> 1d, Statistic.COUNT);
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "custom_counter"));
|
||||
final MeterId meterId = new MeterId("test_custom_conter", MeterId.MeterType.COUNTER, tags);
|
||||
final Counter counter = new SkywalkingCustomCounter.Builder(meterId, measurement, SkywalkingConfig.DEFAULT).build();
|
||||
|
||||
// Check is counter meter id and value
|
||||
assertCounter(counter, "test_custom_conter", tags, 1d);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class SkywalkingDistributionSummaryTest extends SkywalkingMeterBaseTest {
|
||||
|
||||
@Test
|
||||
public void testSimple() {
|
||||
// Creating a simplify distribution summary
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
final DistributionSummary summary = registry.summary("test_simple_distribution_summary", "skywalking", "test");
|
||||
|
||||
// Check Skywalking type
|
||||
Assert.assertTrue(summary instanceof SkywalkingDistributionSummary);
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
|
||||
|
||||
// Multiple record data
|
||||
summary.record(10d);
|
||||
summary.record(13d);
|
||||
summary.record(2d);
|
||||
|
||||
// Check micrometer data
|
||||
Assert.assertEquals(3, summary.count());
|
||||
Assert.assertEquals(25d, summary.totalAmount(), 0.0);
|
||||
Assert.assertEquals(13d, summary.max(), 0.0);
|
||||
|
||||
// Check Skywalking data
|
||||
assertCounter(Whitebox.getInternalState(summary, "counter"), "test_simple_distribution_summary_count", tags, 3d);
|
||||
assertCounter(Whitebox.getInternalState(summary, "sum"), "test_simple_distribution_summary_sum", tags, 25d);
|
||||
assertGauge(Whitebox.getInternalState(summary, "max"), "test_simple_distribution_summary_max", tags, 13d);
|
||||
assertHistogramNull(Whitebox.getInternalState(summary, "histogram"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplex() {
|
||||
// Creating a support histogram distribution summary
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
final DistributionSummary summary = DistributionSummary.builder("test_complex_distribution_summary")
|
||||
.tags("skywalking", "test")
|
||||
.publishPercentiles(0.5, 0.95)
|
||||
.serviceLevelObjectives(10, 20)
|
||||
.minimumExpectedValue(1d)
|
||||
.register(registry);
|
||||
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
|
||||
|
||||
// Multiple record data
|
||||
summary.record(10d);
|
||||
summary.record(13d);
|
||||
summary.record(2d);
|
||||
|
||||
// Check micrometer data
|
||||
Assert.assertEquals(3, summary.count());
|
||||
Assert.assertEquals(25d, summary.totalAmount(), 0.0);
|
||||
Assert.assertEquals(13d, summary.max(), 0.0);
|
||||
|
||||
// Check Skywalking data
|
||||
assertCounter(Whitebox.getInternalState(summary, "counter"), "test_complex_distribution_summary_count", tags, 3d);
|
||||
assertCounter(Whitebox.getInternalState(summary, "sum"), "test_complex_distribution_summary_sum", tags, 25d);
|
||||
assertGauge(Whitebox.getInternalState(summary, "max"), "test_complex_distribution_summary_max", tags, 13d);
|
||||
assertHistogram(Whitebox.getInternalState(summary, "histogram"), "test_complex_distribution_summary_histogram", tags, 1, 1, 10, 2, 20, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.LongTaskTimer;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Gauge;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.AbstractMeter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.MeterCenter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SkywalkingLongTaskTimerTest extends SkywalkingMeterBaseTest {
|
||||
|
||||
private Map<MeterId, AbstractMeter> meterMap;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// Need to clear all of the meter, long task timer has some meter not field field reference
|
||||
meterMap = Whitebox.getInternalState(MeterCenter.class, "METER_MAP");
|
||||
meterMap.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimple() throws InterruptedException {
|
||||
// Creating a simplify long task timer
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
final LongTaskTimer longTaskTimer = registry.more().longTaskTimer("test_simple_long_task_timer", "skywalking", "test");
|
||||
|
||||
// Adding tasks
|
||||
addLongTask(longTaskTimer, 450);
|
||||
addLongTask(longTaskTimer, 20);
|
||||
|
||||
// Make sure the second task has finished
|
||||
TimeUnit.MILLISECONDS.sleep(200);
|
||||
|
||||
// Check Skywalking type
|
||||
Assert.assertTrue(longTaskTimer instanceof SkywalkingLongTaskTimer);
|
||||
final SkywalkingLongTaskTimer timer = (SkywalkingLongTaskTimer) longTaskTimer;
|
||||
|
||||
// Check Original data
|
||||
Assert.assertEquals(1, timer.activeTasks());
|
||||
Assert.assertTrue(timer.duration(TimeUnit.MILLISECONDS) > 0);
|
||||
Assert.assertTrue(timer.max(TimeUnit.MILLISECONDS) > 0);
|
||||
|
||||
// Check Skywalking data
|
||||
assertGauge((Gauge) meterMap.values().stream().filter(m -> m.getName().endsWith("_active_count")).findFirst().orElse(null),
|
||||
"test_simple_long_task_timer_active_count", Arrays.asList(new MeterId.Tag("skywalking", "test")), 1);
|
||||
assertGauge((Gauge) meterMap.values().stream().filter(m -> m.getName().endsWith("_duration_sum")).findFirst().orElse(null),
|
||||
"test_simple_long_task_timer_duration_sum", Arrays.asList(new MeterId.Tag("skywalking", "test")), 0, true);
|
||||
assertGauge((Gauge) meterMap.values().stream().filter(m -> m.getName().endsWith("_max")).findFirst().orElse(null),
|
||||
"test_simple_long_task_timer_max", Arrays.asList(new MeterId.Tag("skywalking", "test")), 0, true);
|
||||
}
|
||||
|
||||
// Add long time task
|
||||
private void addLongTask(LongTaskTimer longTaskTimer, int sleepMills) {
|
||||
new Thread(() -> {
|
||||
longTaskTimer.record(() -> {
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(sleepMills);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
});
|
||||
}).start();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Gauge;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Histogram;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SkywalkingMeterBaseTest {
|
||||
|
||||
/**
|
||||
* Check counter data
|
||||
*/
|
||||
public void assertCounter(Counter counter, String name, List<MeterId.Tag> tags, double count) {
|
||||
Assert.assertEquals(name, counter.getMeterId().getName());
|
||||
Assert.assertEquals(tags, counter.getMeterId().getTags());
|
||||
Assert.assertEquals(MeterId.MeterType.COUNTER, counter.getMeterId().getType());
|
||||
|
||||
Assert.assertEquals(count, counter.get(), 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check gauge data, and value must be same
|
||||
*/
|
||||
public void assertGauge(Gauge gauge, String name, List<MeterId.Tag> tags, double value) {
|
||||
assertGauge(gauge, name, tags, value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check gauge data, and value could greater than provide value
|
||||
*/
|
||||
public void assertGauge(Gauge gauge, String name, List<MeterId.Tag> tags, double value, boolean greaterThanValueMode) {
|
||||
Assert.assertEquals(name, gauge.getMeterId().getName());
|
||||
Assert.assertEquals(tags, gauge.getMeterId().getTags());
|
||||
Assert.assertEquals(MeterId.MeterType.GAUGE, gauge.getMeterId().getType());
|
||||
|
||||
if (greaterThanValueMode) {
|
||||
Assert.assertTrue(gauge.get() > value);
|
||||
} else {
|
||||
Assert.assertEquals(value, gauge.get(), 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check not have histogram
|
||||
*/
|
||||
public void assertHistogramNull(Optional<Histogram> histogramOptional) {
|
||||
Assert.assertNull(histogramOptional.orElse(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check histogram cannot be null and data correct
|
||||
* @param bucketsAndCount bucket and value array
|
||||
*/
|
||||
public void assertHistogram(Optional<Histogram> histogramOptional, String name, List<MeterId.Tag> tags, double... bucketsAndCount) {
|
||||
final Histogram histogram = histogramOptional.orElse(null);
|
||||
Assert.assertNotNull(histogram);
|
||||
Assert.assertEquals(name, histogram.getMeterId().getName());
|
||||
Assert.assertEquals(tags, histogram.getMeterId().getTags());
|
||||
Assert.assertEquals(MeterId.MeterType.HISTOGRAM, histogram.getMeterId().getType());
|
||||
|
||||
final Histogram.Bucket[] buckets = histogram.getBuckets();
|
||||
Assert.assertEquals(bucketsAndCount.length / 2, buckets.length);
|
||||
for (int i = 0; i < buckets.length; i++) {
|
||||
Assert.assertEquals(bucketsAndCount[i * 2], buckets[i].getBucket(), 0.0);
|
||||
Assert.assertEquals((long) bucketsAndCount[i * 2 + 1], buckets[i].getCount());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.Statistic;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import org.apache.skywalking.apm.toolkit.meter.BaseMeter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Counter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Gauge;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.MeterCenter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Only test in build-in meters
|
||||
*/
|
||||
public class SkywalkingMeterRegistryTest extends SkywalkingMeterBaseTest {
|
||||
|
||||
private Map<MeterId, BaseMeter> meterMap;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// Make sure meters are clear
|
||||
meterMap = Whitebox.getInternalState(MeterCenter.class, "METER_MAP");
|
||||
meterMap.clear();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
// Clear meters after finish each test case
|
||||
meterMap.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGauge() {
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
final GaugeTestBean gaugeTestBean = new GaugeTestBean(1d);
|
||||
registry.gauge("test_counter", gaugeTestBean, GaugeTestBean::getCount);
|
||||
|
||||
// Check meter and count
|
||||
Assert.assertEquals(1, meterMap.size());
|
||||
final BaseMeter meter = meterMap.values().iterator().next();
|
||||
Assert.assertTrue(meter instanceof Gauge);
|
||||
final Gauge gauge = (Gauge) meter;
|
||||
|
||||
Assert.assertEquals(1d, gauge.get(), 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionTimer() {
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
final FunctionTimerBean task = new FunctionTimerBean(1, 200);
|
||||
registry.more().timer("test_function_timer", Tags.of("skywalking", "test"), task,
|
||||
FunctionTimerBean::getCount, FunctionTimerBean::getTotalTime, TimeUnit.MILLISECONDS);
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
|
||||
|
||||
// Check is has appoint meter
|
||||
Assert.assertEquals(2, meterMap.size());
|
||||
Gauge countGauge = null;
|
||||
Gauge sumGauge = null;
|
||||
for (BaseMeter meter : meterMap.values()) {
|
||||
if (meter.getName().endsWith("count")) {
|
||||
countGauge = (Gauge) meter;
|
||||
} else if (meter.getName().endsWith("sum")) {
|
||||
sumGauge = (Gauge) meter;
|
||||
}
|
||||
}
|
||||
|
||||
// Check data
|
||||
assertGauge(countGauge, "test_function_timer_count", tags, 1);
|
||||
assertGauge(sumGauge, "test_function_timer_sum", tags, 200);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionCounter() {
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
final FunctionTimerBean task = new FunctionTimerBean(1, 200);
|
||||
registry.more().counter("test_function_counter", Tags.of("skywalking", "test"), task,
|
||||
FunctionTimerBean::getCount);
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
|
||||
|
||||
// Check meter and count
|
||||
Assert.assertEquals(1, meterMap.size());
|
||||
Counter countGauge = (Counter) meterMap.values().iterator().next();
|
||||
|
||||
// Check data
|
||||
assertCounter(countGauge, "test_function_counter", tags, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewMeterSum() {
|
||||
// sum
|
||||
testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.TOTAL, data -> {
|
||||
assertCounter((Counter) data.getMeter(),
|
||||
"test_meter_sum", data.getTags(), 1d);
|
||||
});
|
||||
|
||||
// count
|
||||
testNewMeter("test_meter", Meter.Type.COUNTER, Statistic.COUNT, data -> {
|
||||
assertCounter((Counter) data.getMeter(),
|
||||
"test_meter", data.getTags(), 1d);
|
||||
});
|
||||
|
||||
// max
|
||||
testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.MAX, data -> {
|
||||
assertGauge((Gauge) data.getMeter(),
|
||||
"test_meter_max", data.getTags(), 1d);
|
||||
});
|
||||
|
||||
// activeCount
|
||||
testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.ACTIVE_TASKS, data -> {
|
||||
assertGauge((Gauge) data.getMeter(),
|
||||
"test_meter_active_count", data.getTags(), 1d);
|
||||
});
|
||||
|
||||
// durationSum
|
||||
testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.DURATION, data -> {
|
||||
assertGauge((Gauge) data.getMeter(),
|
||||
"test_meter_duration_sum", data.getTags(), 1d);
|
||||
});
|
||||
|
||||
// others
|
||||
testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.VALUE, data -> {
|
||||
assertGauge((Gauge) data.getMeter(),
|
||||
"test_meter", data.getTags(), 1d);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check custom measurement
|
||||
*/
|
||||
private void testNewMeter(String meterName, Meter.Type type, Statistic statistic, Consumer<MeterData> meterChecker) {
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
|
||||
// Create measurement
|
||||
Meter.builder(meterName, type, Arrays.asList(new Measurement(() -> 1d, statistic)))
|
||||
.tag("skywalking", "test")
|
||||
.register(registry);
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
|
||||
Assert.assertEquals(1, meterMap.size());
|
||||
meterChecker.accept(new MeterData(meterMap.values().iterator().next(), tags));
|
||||
|
||||
// clear all data
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
final io.micrometer.core.instrument.Counter counter = registry.counter("test_remove_counter");
|
||||
Assert.assertEquals(1, meterMap.size());
|
||||
|
||||
registry.remove(counter.getId());
|
||||
Assert.assertEquals(0, meterMap.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Working on {@link io.micrometer.core.instrument.Gauge} check
|
||||
*/
|
||||
private static class GaugeTestBean {
|
||||
private final double count;
|
||||
|
||||
public GaugeTestBean(double count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public double getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Working on {@link io.micrometer.core.instrument.FunctionTimer} check
|
||||
*/
|
||||
private static class FunctionTimerBean {
|
||||
private final long count;
|
||||
private final double totalTime;
|
||||
|
||||
public FunctionTimerBean(long count, double totalTime) {
|
||||
this.count = count;
|
||||
this.totalTime = totalTime;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public double getTotalTime() {
|
||||
return totalTime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Working on custom {@link Measurement} check
|
||||
*/
|
||||
private static class MeterData {
|
||||
private final BaseMeter meter;
|
||||
private final List<MeterId.Tag> tags;
|
||||
|
||||
public MeterData(BaseMeter meter, List<MeterId.Tag> tags) {
|
||||
this.meter = meter;
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public BaseMeter getMeter() {
|
||||
return meter;
|
||||
}
|
||||
|
||||
public List<MeterId.Tag> getTags() {
|
||||
return tags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.meter.micrometer;
|
||||
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SkywalkingTimerTest extends SkywalkingMeterBaseTest {
|
||||
|
||||
@Test
|
||||
public void testSimpleTimer() {
|
||||
// Creating a simplify timer
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
final Timer timer = registry.timer("test_simple_timer", "skywalking", "test");
|
||||
|
||||
// Check Skywalking type
|
||||
Assert.assertTrue(timer instanceof SkywalkingTimer);
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
|
||||
|
||||
// Multiple record data
|
||||
timer.record(10, TimeUnit.MILLISECONDS);
|
||||
timer.record(20, TimeUnit.MILLISECONDS);
|
||||
timer.record(3, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Check micrometer data
|
||||
Assert.assertEquals(3, timer.count());
|
||||
Assert.assertEquals(33d, timer.totalTime(TimeUnit.MILLISECONDS), 0.0);
|
||||
Assert.assertEquals(20d, timer.max(TimeUnit.MILLISECONDS), 0.0);
|
||||
|
||||
// Check Skywalking data
|
||||
assertCounter(Whitebox.getInternalState(timer, "counter"), "test_simple_timer_count", tags, 3d);
|
||||
assertCounter(Whitebox.getInternalState(timer, "sum"), "test_simple_timer_sum", tags, 33d);
|
||||
assertGauge(Whitebox.getInternalState(timer, "max"), "test_simple_timer_max", tags, 20d);
|
||||
assertHistogramNull(Whitebox.getInternalState(timer, "histogram"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilder() {
|
||||
// Creating a support histogram timer
|
||||
final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
Timer timer = Timer.builder("test_complex_timer")
|
||||
.tag("skywalking", "test")
|
||||
.publishPercentiles(0.5, 0.95) // median and 95th percentile
|
||||
.serviceLevelObjectives(Duration.ofMillis(10), Duration.ofMillis(20))
|
||||
.minimumExpectedValue(Duration.ofMillis(1))
|
||||
.register(registry);
|
||||
|
||||
// Check Skywalking type
|
||||
Assert.assertTrue(timer instanceof SkywalkingTimer);
|
||||
final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
|
||||
|
||||
// Multiple record data
|
||||
timer.record(10, TimeUnit.MILLISECONDS);
|
||||
timer.record(22, TimeUnit.MILLISECONDS);
|
||||
timer.record(13, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Check micrometer data
|
||||
Assert.assertEquals(3, timer.count());
|
||||
Assert.assertEquals(45d, timer.totalTime(TimeUnit.MILLISECONDS), 0.0);
|
||||
Assert.assertEquals(22d, timer.max(TimeUnit.MILLISECONDS), 0.0);
|
||||
|
||||
// Check Skywalking data
|
||||
assertCounter(Whitebox.getInternalState(timer, "counter"), "test_complex_timer_count", tags, 3d);
|
||||
assertCounter(Whitebox.getInternalState(timer, "sum"), "test_complex_timer_sum", tags, 45d);
|
||||
assertGauge(Whitebox.getInternalState(timer, "max"), "test_complex_timer_max", tags, 22d);
|
||||
assertHistogram(Whitebox.getInternalState(timer, "histogram"), "test_complex_timer_histogram", tags, 1, 0, 10, 2, 20, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -36,5 +36,7 @@
|
|||
<module>apm-toolkit-logback-1.x</module>
|
||||
<module>apm-toolkit-opentracing</module>
|
||||
<module>apm-toolkit-trace</module>
|
||||
<module>apm-toolkit-meter</module>
|
||||
<module>apm-toolkit-micrometer-registry</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 7e563891f3cfaf5c19ad086434af93aaab996719
|
||||
Subproject commit 24788cf41807048dcbe8dba0958688aaaf630d73
|
||||
|
|
@ -170,6 +170,23 @@ public class Config {
|
|||
public static int SNAPSHOT_TRANSPORT_BUFFER_SIZE = 500;
|
||||
}
|
||||
|
||||
public static class Meter {
|
||||
/**
|
||||
* If true, skywalking agent will enable sending meters. Otherwise disable meter report.
|
||||
*/
|
||||
public static boolean ACTIVE = true;
|
||||
|
||||
/**
|
||||
* Report meters interval
|
||||
*/
|
||||
public static Integer REPORT_INTERVAL = 20;
|
||||
|
||||
/**
|
||||
* Max size of the meter count, using {@link org.apache.skywalking.apm.agent.core.meter.MeterId} as identity
|
||||
*/
|
||||
public static Integer MAX_METER_SIZE = 500;
|
||||
}
|
||||
|
||||
public static class Jvm {
|
||||
/**
|
||||
* The buffer size of collected JVM info.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter;
|
||||
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.Label;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Identity the meter, including name, type and tags.
|
||||
*/
|
||||
public class MeterId {
|
||||
|
||||
private final String name;
|
||||
private final MeterType type;
|
||||
private final List<MeterTag> tags;
|
||||
|
||||
// cache the gRPC label message
|
||||
private List<Label> labels;
|
||||
|
||||
public MeterId(String name, MeterType type, List<MeterTag> tags) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<MeterTag> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public MeterType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* transform tags to label message
|
||||
*/
|
||||
public List<Label> transformTags() {
|
||||
if (labels != null) {
|
||||
return labels;
|
||||
}
|
||||
|
||||
return labels = tags.stream()
|
||||
.map(t -> Label.newBuilder().setName(t.getKey()).setValue(t.getValue()).build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MeterId meterId = (MeterId) o;
|
||||
return Objects.equals(name, meterId.name) &&
|
||||
type == meterId.type &&
|
||||
Objects.equals(tags, meterId.tags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, type, tags);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter;
|
||||
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import org.apache.skywalking.apm.agent.core.boot.BootService;
|
||||
import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor;
|
||||
import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory;
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.conf.Config;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.remote.GRPCChannelListener;
|
||||
import org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager;
|
||||
import org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus;
|
||||
import org.apache.skywalking.apm.agent.core.remote.GRPCStreamServiceStatus;
|
||||
import org.apache.skywalking.apm.network.common.v3.Commands;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterReportServiceGrpc;
|
||||
import org.apache.skywalking.apm.util.RunnableWithExceptionProtection;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.apache.skywalking.apm.agent.core.conf.Config.Collector.GRPC_UPSTREAM_TIMEOUT;
|
||||
|
||||
@DefaultImplementor
|
||||
public class MeterService implements BootService, Runnable, GRPCChannelListener {
|
||||
private static final ILog logger = LogManager.getLogger(MeterService.class);
|
||||
|
||||
// all meters
|
||||
private final ConcurrentHashMap<MeterId, MeterTransformer> meterMap = new ConcurrentHashMap<>();
|
||||
|
||||
// channel status
|
||||
private volatile GRPCChannelStatus status = GRPCChannelStatus.DISCONNECT;
|
||||
|
||||
// gRPC stub
|
||||
private volatile MeterReportServiceGrpc.MeterReportServiceStub meterReportServiceStub;
|
||||
|
||||
// report meters
|
||||
private volatile ScheduledFuture<?> reportMeterFuture;
|
||||
|
||||
/**
|
||||
* Register the meterTransformer
|
||||
*/
|
||||
public <T extends MeterTransformer> void register(T meterTransformer) {
|
||||
if (meterTransformer == null) {
|
||||
return;
|
||||
}
|
||||
if (meterMap.size() >= Config.Meter.MAX_METER_SIZE) {
|
||||
logger.warn("Already out of the meter system max size, will not report. meter name:{}", meterTransformer.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
meterMap.putIfAbsent(meterTransformer.getId(), meterTransformer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare() throws Throwable {
|
||||
ServiceManager.INSTANCE.findService(GRPCChannelManager.class).addChannelListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boot() throws Throwable {
|
||||
if (Config.Meter.ACTIVE) {
|
||||
reportMeterFuture = Executors.newSingleThreadScheduledExecutor(
|
||||
new DefaultNamedThreadFactory("MeterReportService")
|
||||
).scheduleWithFixedDelay(new RunnableWithExceptionProtection(
|
||||
this,
|
||||
t -> logger.error("Report meters failure.", t)
|
||||
), 0, Config.Meter.REPORT_INTERVAL, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() throws Throwable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() throws Throwable {
|
||||
if (reportMeterFuture != null) {
|
||||
reportMeterFuture.cancel(true);
|
||||
}
|
||||
// clear all of the meter report
|
||||
meterMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (status != GRPCChannelStatus.CONNECTED || meterMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
StreamObserver<MeterData> reportStreamObserver = null;
|
||||
final GRPCStreamServiceStatus status = new GRPCStreamServiceStatus(false);
|
||||
try {
|
||||
reportStreamObserver = meterReportServiceStub.withDeadlineAfter(
|
||||
GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS
|
||||
).collect(new StreamObserver<Commands>() {
|
||||
@Override
|
||||
public void onNext(Commands commands) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
status.finished();
|
||||
if (logger.isErrorEnable()) {
|
||||
logger.error(throwable, "Send meters to collector fail with a grpc internal exception.");
|
||||
}
|
||||
ServiceManager.INSTANCE.findService(GRPCChannelManager.class).reportError(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
status.finished();
|
||||
}
|
||||
});
|
||||
|
||||
// build and report meters
|
||||
boolean hasSendMachineInfo = false;
|
||||
for (MeterTransformer meterTransformer : meterMap.values()) {
|
||||
final MeterData.Builder dataBuilder = meterTransformer.transform();
|
||||
if (dataBuilder == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// only send the service base info at the first data
|
||||
if (!hasSendMachineInfo) {
|
||||
dataBuilder.setService(Config.Agent.SERVICE_NAME);
|
||||
dataBuilder.setServiceInstance(Config.Agent.INSTANCE_NAME);
|
||||
dataBuilder.setTimestamp(System.currentTimeMillis());
|
||||
hasSendMachineInfo = true;
|
||||
}
|
||||
|
||||
reportStreamObserver.onNext(dataBuilder.build());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (!(e instanceof StatusRuntimeException)) {
|
||||
logger.error(e, "Report meters to backend fail.");
|
||||
return;
|
||||
}
|
||||
final StatusRuntimeException statusRuntimeException = (StatusRuntimeException) e;
|
||||
if (statusRuntimeException.getStatus().getCode() == Status.Code.UNIMPLEMENTED) {
|
||||
logger.warn("Backend doesn't support meter, it will be disabled");
|
||||
if (reportMeterFuture != null) {
|
||||
reportMeterFuture.cancel(true);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (reportStreamObserver != null) {
|
||||
reportStreamObserver.onCompleted();
|
||||
}
|
||||
status.wait4Finish();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void statusChanged(GRPCChannelStatus status) {
|
||||
if (GRPCChannelStatus.CONNECTED.equals(status)) {
|
||||
Channel channel = ServiceManager.INSTANCE.findService(GRPCChannelManager.class).getChannel();
|
||||
meterReportServiceStub = MeterReportServiceGrpc.newStub(channel);
|
||||
} else {
|
||||
meterReportServiceStub = null;
|
||||
}
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MeterTag {
|
||||
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
public MeterTag(String key, String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MeterTag meterTag = (MeterTag) o;
|
||||
return Objects.equals(key, meterTag.key) &&
|
||||
Objects.equals(value, meterTag.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(key, value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter;
|
||||
|
||||
public enum MeterType {
|
||||
COUNTER,
|
||||
GAUGE,
|
||||
HISTOGRAM
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.adapter;
|
||||
|
||||
public interface CounterAdapter extends MeterAdapter {
|
||||
Double getCount();
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.adapter;
|
||||
|
||||
public interface GaugeAdapter extends MeterAdapter {
|
||||
Double getCount();
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.adapter;
|
||||
|
||||
public interface HistogramAdapter extends MeterAdapter {
|
||||
|
||||
/**
|
||||
* Get all buckets
|
||||
*/
|
||||
double[] getAllBuckets();
|
||||
|
||||
/**
|
||||
* Get currently bucket values
|
||||
*/
|
||||
long[] getBucketValues();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.adapter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
|
||||
/**
|
||||
* Working on adapt the tool-kit side with agent core
|
||||
*/
|
||||
public interface MeterAdapter {
|
||||
MeterId getId();
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.transform;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterService;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.CounterAdapter;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
|
||||
|
||||
public class CounterTransformer extends MeterTransformer<CounterAdapter> {
|
||||
private static MeterService METER_SERVICE;
|
||||
|
||||
public CounterTransformer(CounterAdapter adapter) {
|
||||
super(adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterData.Builder transform() {
|
||||
if (METER_SERVICE == null) {
|
||||
METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
|
||||
}
|
||||
|
||||
final MeterData.Builder builder = MeterData.newBuilder();
|
||||
builder.setSingleValue(MeterSingleValue.newBuilder()
|
||||
.setName(getName())
|
||||
.addAllLabels(transformTags())
|
||||
.setValue(adapter.getCount()).build());
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.transform;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.GaugeAdapter;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
|
||||
|
||||
public class GaugeTransformer extends MeterTransformer<GaugeAdapter> {
|
||||
private static final ILog logger = LogManager.getLogger(GaugeTransformer.class);
|
||||
|
||||
public GaugeTransformer(GaugeAdapter adapter) {
|
||||
super(adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterData.Builder transform() {
|
||||
// get count
|
||||
Double count;
|
||||
try {
|
||||
count = adapter.getCount();
|
||||
} catch (Exception e) {
|
||||
logger.warn(e, "Cannot get the count in meter:{}", adapter.getId().getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (count == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final MeterData.Builder builder = MeterData.newBuilder();
|
||||
builder.setSingleValue(MeterSingleValue.newBuilder()
|
||||
.setName(getName())
|
||||
.addAllLabels(transformTags())
|
||||
.setValue(count).build());
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.transform;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.HistogramAdapter;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterBucketValue;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterHistogram;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class HistogramTransformer extends MeterTransformer<HistogramAdapter> {
|
||||
|
||||
private final Bucket[] buckets;
|
||||
|
||||
public HistogramTransformer(HistogramAdapter adapter) {
|
||||
super(adapter);
|
||||
this.buckets = initBuckets(adapter.getAllBuckets());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterData.Builder transform() {
|
||||
final MeterData.Builder builder = MeterData.newBuilder();
|
||||
|
||||
// get all values
|
||||
List<MeterBucketValue> values = new ArrayList<>(this.buckets.length);
|
||||
final long[] bucketValues = adapter.getBucketValues();
|
||||
for (int i = 0; i < bucketValues.length; i++) {
|
||||
values.add(buckets[i].transform(bucketValues[i]));
|
||||
}
|
||||
|
||||
return builder.setHistogram(MeterHistogram.newBuilder()
|
||||
.setName(getName())
|
||||
.addAllLabels(transformTags())
|
||||
.addAllValues(values)
|
||||
.build());
|
||||
}
|
||||
|
||||
private Bucket[] initBuckets(double[] buckets) {
|
||||
final Bucket[] list = new Bucket[buckets.length];
|
||||
for (int i = 0; i < buckets.length; i++) {
|
||||
list[i] = new Bucket(buckets[i]);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static class Bucket {
|
||||
private double bucket;
|
||||
|
||||
public Bucket(double bucket) {
|
||||
this.bucket = bucket;
|
||||
}
|
||||
|
||||
public MeterBucketValue transform(long currentCount) {
|
||||
return MeterBucketValue.newBuilder()
|
||||
.setBucket(bucket)
|
||||
.setCount(currentCount)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Bucket bucket1 = (Bucket) o;
|
||||
return Double.compare(bucket1.bucket, bucket) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(bucket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.transform;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.MeterAdapter;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.Label;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Meter transformer base data
|
||||
*
|
||||
* @see CounterTransformer
|
||||
* @see GaugeTransformer
|
||||
* @see HistogramTransformer
|
||||
*/
|
||||
public abstract class MeterTransformer<T extends MeterAdapter> {
|
||||
|
||||
protected T adapter;
|
||||
|
||||
// cache the gRPC label message
|
||||
private List<Label> labels;
|
||||
|
||||
public MeterTransformer(T adapter) {
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identity the meter
|
||||
*/
|
||||
public MeterId getId() {
|
||||
return adapter.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get meter name
|
||||
*/
|
||||
public String getName() {
|
||||
return getId().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform all tags to gRPC message
|
||||
*/
|
||||
public List<Label> transformTags() {
|
||||
if (labels != null) {
|
||||
return labels;
|
||||
}
|
||||
|
||||
return labels = getId().getTags().stream()
|
||||
.map(t -> Label.newBuilder().setName(t.getKey()).setValue(t.getValue()).build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the meter to gRPC message bean
|
||||
* @return if dont need to transform or no changed, return null to ignore
|
||||
*/
|
||||
public abstract MeterData.Builder transform();
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MeterTransformer meterTransformer = (MeterTransformer) o;
|
||||
return Objects.equals(getId(), meterTransformer.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getId());
|
||||
}
|
||||
}
|
||||
|
|
@ -27,3 +27,4 @@ org.apache.skywalking.apm.agent.core.commands.CommandService
|
|||
org.apache.skywalking.apm.agent.core.commands.CommandExecutorService
|
||||
org.apache.skywalking.apm.agent.core.profile.ProfileTaskChannelService
|
||||
org.apache.skywalking.apm.agent.core.profile.ProfileTaskExecutionService
|
||||
org.apache.skywalking.apm.agent.core.meter.MeterService
|
||||
|
|
@ -27,6 +27,7 @@ import org.apache.skywalking.apm.agent.core.context.TracingContext;
|
|||
import org.apache.skywalking.apm.agent.core.context.TracingContextListener;
|
||||
import org.apache.skywalking.apm.agent.core.context.TracingThreadListener;
|
||||
import org.apache.skywalking.apm.agent.core.jvm.JVMService;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterService;
|
||||
import org.apache.skywalking.apm.agent.core.profile.ProfileTaskChannelService;
|
||||
import org.apache.skywalking.apm.agent.core.profile.ProfileTaskExecutionService;
|
||||
import org.apache.skywalking.apm.agent.core.remote.GRPCChannelListener;
|
||||
|
|
@ -57,7 +58,7 @@ public class ServiceManagerTest {
|
|||
public void testServiceDependencies() throws Exception {
|
||||
HashMap<Class, BootService> registryService = getFieldValue(ServiceManager.INSTANCE, "bootedServices");
|
||||
|
||||
assertThat(registryService.size(), is(11));
|
||||
assertThat(registryService.size(), is(12));
|
||||
|
||||
assertTraceSegmentServiceClient(ServiceManager.INSTANCE.findService(TraceSegmentServiceClient.class));
|
||||
assertContextManager(ServiceManager.INSTANCE.findService(ContextManager.class));
|
||||
|
|
@ -66,6 +67,7 @@ public class ServiceManagerTest {
|
|||
assertJVMService(ServiceManager.INSTANCE.findService(JVMService.class));
|
||||
assertProfileTaskQueryService(ServiceManager.INSTANCE.findService(ProfileTaskChannelService.class));
|
||||
assertProfileTaskExecuteService(ServiceManager.INSTANCE.findService(ProfileTaskExecutionService.class));
|
||||
assertMeterRegisterService(ServiceManager.INSTANCE.findService(MeterService.class));
|
||||
|
||||
assertTracingContextListener();
|
||||
assertIgnoreTracingContextListener();
|
||||
|
|
@ -105,7 +107,7 @@ public class ServiceManagerTest {
|
|||
assertNotNull(service);
|
||||
|
||||
List<GRPCChannelListener> listeners = getFieldValue(service, "listeners");
|
||||
assertEquals(listeners.size(), 5);
|
||||
assertEquals(listeners.size(), 6);
|
||||
}
|
||||
|
||||
private void assertSamplingService(SamplingService service) {
|
||||
|
|
@ -120,6 +122,10 @@ public class ServiceManagerTest {
|
|||
assertNotNull(service);
|
||||
}
|
||||
|
||||
private void assertMeterRegisterService(MeterService service) {
|
||||
assertNotNull(service);
|
||||
}
|
||||
|
||||
private <T> T getFieldValue(Object instance, String fieldName) throws Exception {
|
||||
Field field = instance.getClass().getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter;
|
||||
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.Label;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.util.reflection.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class MeterIdTest {
|
||||
|
||||
@Test
|
||||
public void testTransformTags() {
|
||||
MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
|
||||
// Label message check
|
||||
List<Label> labels = meterId.transformTags();
|
||||
Assert.assertEquals(1, labels.size());
|
||||
final Label label = labels.get(0);
|
||||
Assert.assertEquals("k1", label.getName());
|
||||
Assert.assertEquals("v1", label.getValue());
|
||||
Assert.assertEquals(MeterType.COUNTER, meterId.getType());
|
||||
|
||||
// Must cache the Label message
|
||||
final List<Label> cacheLabels = (List<Label>) Whitebox.getInternalState(meterId, "labels");
|
||||
Assert.assertEquals(labels, cacheLabels);
|
||||
|
||||
// Check empty tags
|
||||
meterId = new MeterId("test", MeterType.COUNTER, Collections.emptyList());
|
||||
labels = meterId.transformTags();
|
||||
Assert.assertEquals(0, labels.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
final MeterId meterId1 = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
final MeterId meterId2 = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
|
||||
Assert.assertEquals(meterId1, meterId2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter;
|
||||
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.grpc.testing.GrpcServerRule;
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.conf.Config;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.CounterAdapter;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.HistogramAdapter;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.CounterTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.HistogramTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus;
|
||||
import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule;
|
||||
import org.apache.skywalking.apm.agent.core.test.tools.TracingSegmentRunner;
|
||||
import org.apache.skywalking.apm.network.common.v3.Commands;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterBucketValue;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterHistogram;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterReportServiceGrpc;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
@RunWith(TracingSegmentRunner.class)
|
||||
public class MeterServiceTest {
|
||||
|
||||
@Rule
|
||||
public AgentServiceRule agentServiceRule = new AgentServiceRule();
|
||||
|
||||
@Rule
|
||||
public GrpcServerRule grpcServerRule = new GrpcServerRule().directExecutor();
|
||||
|
||||
private MeterService registryService = new MeterService();
|
||||
private List<MeterData> upstreamMeters;
|
||||
|
||||
private MeterReportServiceGrpc.MeterReportServiceImplBase serviceImplBase = new MeterReportServiceGrpc.MeterReportServiceImplBase() {
|
||||
@Override
|
||||
public StreamObserver<MeterData> collect(final StreamObserver<Commands> responseObserver) {
|
||||
return new StreamObserver<MeterData>() {
|
||||
@Override
|
||||
public void onNext(MeterData value) {
|
||||
upstreamMeters.add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
responseObserver.onNext(Commands.getDefaultInstance());
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
Config.Meter.ACTIVE = true;
|
||||
Config.Agent.SERVICE_NAME = "testService";
|
||||
Config.Agent.INSTANCE_NAME = "testServiceInstance";
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
Config.Agent.KEEP_TRACING = false;
|
||||
ServiceManager.INSTANCE.shutdown();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Throwable {
|
||||
spy(registryService);
|
||||
|
||||
Whitebox.setInternalState(
|
||||
registryService, "meterReportServiceStub", MeterReportServiceGrpc.newStub(grpcServerRule.getChannel()));
|
||||
Whitebox.setInternalState(registryService, "status", GRPCChannelStatus.CONNECTED);
|
||||
|
||||
upstreamMeters = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegister() {
|
||||
grpcServerRule.getServiceRegistry().addService(serviceImplBase);
|
||||
|
||||
// Register null
|
||||
registryService.register(null);
|
||||
assertThat(upstreamMeters.size(), is(0));
|
||||
|
||||
// Empty meter
|
||||
registryService.run();
|
||||
assertThat(upstreamMeters.size(), is(0));
|
||||
|
||||
// Add one
|
||||
final MeterId counterId = new MeterId("test1", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
final CounterTransformer transformer1 = new CounterTransformer(new TestCounterAdapter(counterId));
|
||||
registryService.register(transformer1);
|
||||
registryService.run();
|
||||
assertThat(upstreamMeters.size(), is(1));
|
||||
isSameWithCounter(upstreamMeters.get(0), true, counterId, 2);
|
||||
|
||||
// Add second
|
||||
upstreamMeters.clear();
|
||||
final MeterId percentileId = new MeterId("test2", MeterType.HISTOGRAM, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
final HistogramTransformer transformer2 = new HistogramTransformer(new TestHistogramAdapter(percentileId));
|
||||
registryService.register(transformer2);
|
||||
registryService.run();
|
||||
assertThat(upstreamMeters.size(), is(2));
|
||||
for (int i = 0; i < upstreamMeters.size(); i++) {
|
||||
if (Objects.equals(upstreamMeters.get(i).getMetricCase(), MeterData.MetricCase.HISTOGRAM)) {
|
||||
isSameWithHistogram(upstreamMeters.get(i), i == 0, percentileId, 2d, 1L);
|
||||
} else {
|
||||
isSameWithCounter(upstreamMeters.get(i), i == 0, counterId, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeterSizeAndShutdown() throws Throwable {
|
||||
final Map<MeterId, MeterTransformer> map = Whitebox.getInternalState(registryService, "meterMap");
|
||||
map.clear();
|
||||
|
||||
// Check max meter size
|
||||
for (Integer i = 0; i < Config.Meter.MAX_METER_SIZE + 1; i++) {
|
||||
final MeterId counterId = new MeterId("test_" + i, MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
final CounterTransformer transformer1 = new CounterTransformer(new TestCounterAdapter(counterId));
|
||||
registryService.register(transformer1);
|
||||
}
|
||||
assertThat(map.size(), is(Config.Meter.MAX_METER_SIZE));
|
||||
|
||||
// Check shutdown
|
||||
registryService.shutdown();
|
||||
assertThat(map.size(), is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check counter message
|
||||
*/
|
||||
private void isSameWithCounter(MeterData meterData, boolean firstData, MeterId meterId, long count) {
|
||||
Assert.assertNotNull(meterData);
|
||||
if (firstData) {
|
||||
Assert.assertEquals(meterData.getService(), "testService");
|
||||
Assert.assertEquals(meterData.getServiceInstance(), "testServiceInstance");
|
||||
Assert.assertTrue(meterData.getTimestamp() > 0);
|
||||
} else {
|
||||
Assert.assertEquals(meterData.getService(), "");
|
||||
Assert.assertEquals(meterData.getServiceInstance(), "");
|
||||
Assert.assertTrue(meterData.getTimestamp() == 0L);
|
||||
}
|
||||
|
||||
Assert.assertEquals(meterData.getMetricCase(), MeterData.MetricCase.SINGLEVALUE);
|
||||
Assert.assertNotNull(meterData.getSingleValue());
|
||||
final MeterSingleValue singleValue = meterData.getSingleValue();
|
||||
|
||||
Assert.assertEquals(singleValue.getName(), meterId.getName());
|
||||
Assert.assertEquals(singleValue.getLabelsList(), meterId.transformTags());
|
||||
Assert.assertEquals(singleValue.getValue(), count, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check histogram message
|
||||
*/
|
||||
public void isSameWithHistogram(MeterData meterData, boolean firstData, MeterId meterId, Object... values) {
|
||||
Assert.assertNotNull(meterData);
|
||||
if (firstData) {
|
||||
Assert.assertEquals(meterData.getService(), "testService");
|
||||
Assert.assertEquals(meterData.getServiceInstance(), "testServiceInstance");
|
||||
Assert.assertTrue(meterData.getTimestamp() > 0);
|
||||
} else {
|
||||
Assert.assertEquals(meterData.getService(), "");
|
||||
Assert.assertEquals(meterData.getServiceInstance(), "");
|
||||
Assert.assertTrue(meterData.getTimestamp() == 0L);
|
||||
}
|
||||
|
||||
Assert.assertEquals(meterData.getMetricCase(), MeterData.MetricCase.HISTOGRAM);
|
||||
Assert.assertNotNull(meterData.getSingleValue());
|
||||
final MeterHistogram histogram = meterData.getHistogram();
|
||||
|
||||
Assert.assertEquals(histogram.getName(), meterId.getName());
|
||||
Assert.assertEquals(histogram.getLabelsList(), meterId.transformTags());
|
||||
for (int i = 0; i < values.length; i += 2) {
|
||||
final MeterBucketValue bucketValue = histogram.getValues(i);
|
||||
Assert.assertNotNull(bucketValue);
|
||||
Assert.assertEquals(bucketValue.getBucket(), (double) values[i], 0.0);
|
||||
Assert.assertEquals(bucketValue.getCount(), values[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating a new {@link CounterAdapter} with appoint count
|
||||
*/
|
||||
private static class TestCounterAdapter implements CounterAdapter {
|
||||
|
||||
private final MeterId meterId;
|
||||
|
||||
public TestCounterAdapter(MeterId meterId) {
|
||||
this.meterId = meterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getCount() {
|
||||
return 2d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId getId() {
|
||||
return this.meterId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating a new {@link HistogramAdapter} with appoint bucket and value
|
||||
*/
|
||||
private static class TestHistogramAdapter implements HistogramAdapter {
|
||||
private final MeterId meterId;
|
||||
|
||||
public TestHistogramAdapter(MeterId meterId) {
|
||||
this.meterId = meterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId getId() {
|
||||
return meterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getAllBuckets() {
|
||||
return new double[] {2};
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getBucketValues() {
|
||||
return new long[] {1};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MeterTagTest {
|
||||
|
||||
@Test
|
||||
public void testGetSet() {
|
||||
// Different key and value
|
||||
final MeterTag tag1 = new MeterTag("k1", "v1");
|
||||
final MeterTag tag2 = new MeterTag("k2", "v2");
|
||||
Assert.assertNotEquals(tag1, tag2);
|
||||
|
||||
// Change to same
|
||||
tag2.setKey("k1");
|
||||
tag2.setValue("v1");
|
||||
Assert.assertEquals(tag1, tag2);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.transform;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.CounterAdapter;
|
||||
import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.Label;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.DoubleAdder;
|
||||
|
||||
public class CounterTransformerTest {
|
||||
|
||||
@Rule
|
||||
public AgentServiceRule agentServiceRule = new AgentServiceRule();
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ServiceManager.INSTANCE.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransform() {
|
||||
final MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
final DoubleAdder counter = new DoubleAdder();
|
||||
CounterTransformer transformer = new CounterTransformer(new TestCounterAdapter(meterId, counter));
|
||||
|
||||
counter.add(2d);
|
||||
|
||||
validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), 2d, transformer.transform());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the single value message
|
||||
*/
|
||||
private void validateMeterData(String name, List<Label> labels, double value, MeterData.Builder validate) {
|
||||
Assert.assertNotNull(validate);
|
||||
Assert.assertEquals(validate.getMetricCase().getNumber(), MeterData.SINGLEVALUE_FIELD_NUMBER);
|
||||
MeterSingleValue singleValue = validate.getSingleValue();
|
||||
Assert.assertNotNull(singleValue);
|
||||
Assert.assertEquals(value, singleValue.getValue(), 0.0);
|
||||
Assert.assertEquals(name, singleValue.getName());
|
||||
Assert.assertEquals(labels, singleValue.getLabelsList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link CounterAdapter} using {@link DoubleAdder} as the counter value
|
||||
*/
|
||||
private static class TestCounterAdapter implements CounterAdapter {
|
||||
private final MeterId meterId;
|
||||
private DoubleAdder counter;
|
||||
|
||||
public TestCounterAdapter(MeterId meterId, DoubleAdder counter) {
|
||||
this.meterId = meterId;
|
||||
this.counter = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getCount() {
|
||||
return counter.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId getId() {
|
||||
return meterId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.transform;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.GaugeAdapter;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.Label;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class GaugeTransformerTest {
|
||||
|
||||
@Test
|
||||
public void testTransform() {
|
||||
final MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
final List<Label> labels = Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build());
|
||||
|
||||
// Normal
|
||||
GaugeTransformer transformer1 = new GaugeTransformer(new TestGaugeAdapter(meterId, () -> 2d));
|
||||
validateMeterData("test", labels, 2d, transformer1.transform());
|
||||
|
||||
// Exception
|
||||
GaugeTransformer transformer2 = new GaugeTransformer(new TestGaugeAdapter(meterId, () -> Double.valueOf(2 / 0)));
|
||||
Assert.assertNull(transformer2.transform());
|
||||
|
||||
// Null
|
||||
GaugeTransformer transformer3 = new GaugeTransformer(new TestGaugeAdapter(meterId, () -> null));
|
||||
Assert.assertNull(transformer3.transform());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the single value message
|
||||
*/
|
||||
private void validateMeterData(String name, List<Label> labels, double value, MeterData.Builder validate) {
|
||||
Assert.assertNotNull(validate);
|
||||
Assert.assertEquals(validate.getMetricCase().getNumber(), MeterData.SINGLEVALUE_FIELD_NUMBER);
|
||||
MeterSingleValue singleValue = validate.getSingleValue();
|
||||
Assert.assertNotNull(singleValue);
|
||||
Assert.assertEquals(singleValue.getValue(), value, 0.0);
|
||||
Assert.assertEquals(singleValue.getName(), name);
|
||||
Assert.assertEquals(singleValue.getLabelsList(), labels);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link GaugeAdapter} using {@link Supplier} as data getter
|
||||
*/
|
||||
private static class TestGaugeAdapter implements GaugeAdapter {
|
||||
private final MeterId meterId;
|
||||
private Supplier<Double> supplier;
|
||||
|
||||
public TestGaugeAdapter(MeterId meterId, Supplier<Double> supplier) {
|
||||
this.meterId = meterId;
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getCount() {
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId getId() {
|
||||
return meterId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.meter.transform;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.HistogramAdapter;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.Label;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.MeterHistogram;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.util.reflection.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class HistogramTransformerTest {
|
||||
|
||||
@Test
|
||||
public void testBuckets() {
|
||||
final MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
|
||||
// Check buckets
|
||||
final TestHistogramAdapter adapter = new TestHistogramAdapter(meterId, new double[] {2d, 5d});
|
||||
final HistogramTransformer transformer = new HistogramTransformer(adapter);
|
||||
final HistogramTransformer.Bucket[] buckets = (HistogramTransformer.Bucket[]) Whitebox.getInternalState(transformer, "buckets");
|
||||
Assert.assertEquals(2, buckets.length);
|
||||
Assert.assertEquals(buckets[0], new HistogramTransformer.Bucket(2));
|
||||
Assert.assertEquals(buckets[1], new HistogramTransformer.Bucket(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransform() {
|
||||
final MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
|
||||
final List<Label> labels = Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build());
|
||||
|
||||
// Check histogram message
|
||||
final TestHistogramAdapter adapter = new TestHistogramAdapter(meterId, new double[] {2d, 5d});
|
||||
final HistogramTransformer transformer = new HistogramTransformer(adapter);
|
||||
adapter.setValues(new long[] {5L, 10L});
|
||||
verifyHistogram("test", labels, Arrays.asList(2d, 5d), Arrays.asList(5L, 10L), transformer.transform());
|
||||
|
||||
adapter.setValues(new long[] {6L, 12L});
|
||||
verifyHistogram("test", labels, Arrays.asList(2d, 5d), Arrays.asList(6L, 12L), transformer.transform());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check histogram message
|
||||
*/
|
||||
public static void verifyHistogram(String name, List<Label> labels, List<Double> buckets,
|
||||
List<Long> bucketValues, MeterData.Builder validate) {
|
||||
Assert.assertNotNull(validate);
|
||||
Assert.assertEquals(validate.getMetricCase().getNumber(), MeterData.HISTOGRAM_FIELD_NUMBER);
|
||||
MeterHistogram histogram = validate.getHistogram();
|
||||
Assert.assertNotNull(histogram);
|
||||
Assert.assertEquals(histogram.getName(), name);
|
||||
Assert.assertEquals(histogram.getLabelsList(), labels);
|
||||
Assert.assertNotNull(histogram.getValuesList());
|
||||
Assert.assertEquals(histogram.getValuesCount(), bucketValues.size());
|
||||
|
||||
for (int i = 0; i < bucketValues.size(); i++) {
|
||||
Assert.assertNotNull(histogram.getValues(i));
|
||||
Assert.assertEquals(histogram.getValues(i).getBucket(), buckets.get(i).doubleValue(), 0.0);
|
||||
Assert.assertEquals(histogram.getValues(i).getCount(), bucketValues.get(i).longValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link HistogramAdapter} with appoint buckets and values
|
||||
*/
|
||||
private static class TestHistogramAdapter implements HistogramAdapter {
|
||||
private final MeterId meterId;
|
||||
private final double[] buckets;
|
||||
private long[] values;
|
||||
|
||||
public TestHistogramAdapter(MeterId meterId, double[] buckets) {
|
||||
this.meterId = meterId;
|
||||
this.buckets = buckets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getAllBuckets() {
|
||||
return buckets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getBucketValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId getId() {
|
||||
return meterId;
|
||||
}
|
||||
|
||||
public void setValues(long[] values) {
|
||||
this.values = values;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
~ contributor license agreements. See the NOTICE file distributed with
|
||||
~ this work for additional information regarding copyright ownership.
|
||||
~ The ASF licenses this file to You 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.
|
||||
~
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>apm-toolkit-activation</artifactId>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-toolkit-meter-activation</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<artifactId>apm-toolkit-meter</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
public class CounterActivation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byName("org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[] {
|
||||
new ConstructorInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getConstructorMatcher() {
|
||||
return takesArguments(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConstructorInterceptor() {
|
||||
return "org.apache.skywalking.apm.toolkit.activation.meter.CounterInterceptor";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[0];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.CounterTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterService;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.adapter.TookitCounterAdapter;
|
||||
|
||||
public class CounterInterceptor implements InstanceConstructorInterceptor {
|
||||
private static MeterService METER_SERVICE;
|
||||
|
||||
@Override
|
||||
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
|
||||
final CounterImpl toolkitCounter = (CounterImpl) objInst;
|
||||
|
||||
final TookitCounterAdapter counterAdapter = new TookitCounterAdapter(toolkitCounter);
|
||||
final CounterTransformer counterTransformer = new CounterTransformer(counterAdapter);
|
||||
|
||||
if (METER_SERVICE == null) {
|
||||
METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
|
||||
}
|
||||
METER_SERVICE.register(counterTransformer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
public class GaugeActivation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byName("org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[] {
|
||||
new ConstructorInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getConstructorMatcher() {
|
||||
return takesArguments(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConstructorInterceptor() {
|
||||
return "org.apache.skywalking.apm.toolkit.activation.meter.GaugeInterceptor";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[0];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.GaugeTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterService;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitGaugeAdapter;
|
||||
|
||||
public class GaugeInterceptor implements InstanceConstructorInterceptor {
|
||||
private static MeterService METER_SERVICE;
|
||||
|
||||
@Override
|
||||
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
|
||||
final GaugeImpl toolkitGauge = (GaugeImpl) objInst;
|
||||
|
||||
final ToolkitGaugeAdapter gaugeAdapter = new ToolkitGaugeAdapter(toolkitGauge);
|
||||
final GaugeTransformer gaugeTransformer = new GaugeTransformer(gaugeAdapter);
|
||||
|
||||
if (METER_SERVICE == null) {
|
||||
METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
|
||||
}
|
||||
METER_SERVICE.register(gaugeTransformer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
public class HistogramActivation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byName("org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[] {
|
||||
new ConstructorInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getConstructorMatcher() {
|
||||
return takesArguments(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConstructorInterceptor() {
|
||||
return "org.apache.skywalking.apm.toolkit.activation.meter.HistogramInterceptor";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[0];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.HistogramTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterService;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitHistogramAdapter;
|
||||
|
||||
public class HistogramInterceptor implements InstanceConstructorInterceptor {
|
||||
private static MeterService METER_SERVICE;
|
||||
|
||||
@Override
|
||||
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
|
||||
final HistogramImpl toolkitHistogram = (HistogramImpl) objInst;
|
||||
|
||||
final ToolkitHistogramAdapter histogramAdapter = new ToolkitHistogramAdapter(toolkitHistogram);
|
||||
final HistogramTransformer histogramTransformer = new HistogramTransformer(histogramAdapter);
|
||||
|
||||
// register the meter
|
||||
if (METER_SERVICE == null) {
|
||||
METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
|
||||
}
|
||||
METER_SERVICE.register(histogramTransformer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter.adapter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.CounterAdapter;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
|
||||
public class TookitCounterAdapter implements CounterAdapter {
|
||||
|
||||
private final CounterImpl counter;
|
||||
private final MeterId id;
|
||||
|
||||
public TookitCounterAdapter(CounterImpl counter) {
|
||||
this.counter = counter;
|
||||
this.id = MeterIdConverter.convert(counter.getMeterId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getCount() {
|
||||
// Using agent get, support rate mode
|
||||
return counter.agentGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter.adapter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.GaugeAdapter;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Gauge;
|
||||
|
||||
public class ToolkitGaugeAdapter implements GaugeAdapter {
|
||||
|
||||
private final Gauge gauge;
|
||||
private final MeterId id;
|
||||
|
||||
public ToolkitGaugeAdapter(Gauge gauge) {
|
||||
this.gauge = gauge;
|
||||
this.id = MeterIdConverter.convert(gauge.getMeterId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getCount() {
|
||||
return gauge.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter.adapter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.adapter.HistogramAdapter;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.Histogram;
|
||||
|
||||
public class ToolkitHistogramAdapter implements HistogramAdapter {
|
||||
|
||||
private final Histogram histogram;
|
||||
private final MeterId id;
|
||||
|
||||
public ToolkitHistogramAdapter(Histogram histogram) {
|
||||
this.histogram = histogram;
|
||||
this.id = MeterIdConverter.convert(histogram.getMeterId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getAllBuckets() {
|
||||
final int bucketLength = histogram.getBuckets().length;
|
||||
final double[] buckets = new double[bucketLength];
|
||||
for (int i = 0; i < bucketLength; i++) {
|
||||
buckets[i] = histogram.getBuckets()[i].getBucket();
|
||||
}
|
||||
return buckets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getBucketValues() {
|
||||
final int bucketLength = histogram.getBuckets().length;
|
||||
final long[] bucketValues = new long[bucketLength];
|
||||
for (int i = 0; i < bucketLength; i++) {
|
||||
bucketValues[i] = histogram.getBuckets()[i].getCount();
|
||||
}
|
||||
return bucketValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeterId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter.util;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MeterIdConverter {
|
||||
|
||||
/**
|
||||
* Convert toolkit id to agent core id
|
||||
*/
|
||||
public static MeterId convert(org.apache.skywalking.apm.toolkit.meter.MeterId id) {
|
||||
final String meterName = id.getName();
|
||||
MeterType type = convertType(id);
|
||||
List<MeterTag> tags = Collections.emptyList();
|
||||
if (id.getTags() != null) {
|
||||
tags = id.getTags().stream().map(t -> new MeterTag(t.getName(), t.getValue())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return new MeterId(meterName, type, tags);
|
||||
}
|
||||
|
||||
private static MeterType convertType(org.apache.skywalking.apm.toolkit.meter.MeterId id) {
|
||||
switch (id.getType()) {
|
||||
case GAUGE:
|
||||
return MeterType.GAUGE;
|
||||
case COUNTER:
|
||||
return MeterType.COUNTER;
|
||||
case HISTOGRAM:
|
||||
return MeterType.HISTOGRAM;
|
||||
default:
|
||||
throw new IllegalStateException("Could not found the meter type: " + id.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
toolkit-counter=org.apache.skywalking.apm.toolkit.activation.meter.CounterActivation
|
||||
toolkit-gauge=org.apache.skywalking.apm.toolkit.activation.meter.GaugeActivation
|
||||
toolkit-histogram=org.apache.skywalking.apm.toolkit.activation.meter.HistogramActivation
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterService;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.CounterTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.util.reflection.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
public class CounterInterceptorTest {
|
||||
|
||||
@Rule
|
||||
public AgentServiceRule agentServiceRule = new AgentServiceRule();
|
||||
|
||||
private CounterInterceptor counterInterceptor = new CounterInterceptor();
|
||||
private EnhancedInstance enhancedInstance = new CounterEnhance(
|
||||
new MeterId("test", MeterId.MeterType.COUNTER, Arrays.asList(new MeterId.Tag("k1", "v1"))));
|
||||
|
||||
@Test
|
||||
public void testConstruct() {
|
||||
counterInterceptor.onConstruct(enhancedInstance, null);
|
||||
|
||||
final MeterService service = ServiceManager.INSTANCE.findService(MeterService.class);
|
||||
final Map<MeterId, MeterTransformer> meterMap = (Map<MeterId, MeterTransformer>) Whitebox.getInternalState(service, "meterMap");
|
||||
Assert.assertEquals(1, meterMap.size());
|
||||
|
||||
final MeterTransformer transformer = meterMap.values().iterator().next();
|
||||
Assert.assertTrue(transformer instanceof CounterTransformer);
|
||||
final CounterTransformer counterTransformer = (CounterTransformer) transformer;
|
||||
|
||||
Assert.assertNotNull(counterTransformer.getId());
|
||||
Assert.assertEquals("test", counterTransformer.getId().getName());
|
||||
Assert.assertEquals(MeterType.COUNTER, counterTransformer.getId().getType());
|
||||
Assert.assertEquals(Arrays.asList(new MeterTag("k1", "v1")), counterTransformer.getId().getTags());
|
||||
}
|
||||
|
||||
private static class CounterEnhance extends CounterImpl implements EnhancedInstance {
|
||||
protected CounterEnhance(MeterId meterId) {
|
||||
super(meterId, Mode.INCREMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSkyWalkingDynamicField() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyWalkingDynamicField(Object value) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterService;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.GaugeTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.util.reflection.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class GaugeInterceptorTest {
|
||||
|
||||
@Rule
|
||||
public AgentServiceRule agentServiceRule = new AgentServiceRule();
|
||||
|
||||
private GaugeInterceptor gaugeInterceptor = new GaugeInterceptor();
|
||||
private EnhancedInstance enhancedInstance = new GaugeEnhance(
|
||||
new MeterId("test", MeterId.MeterType.GAUGE, Arrays.asList(new MeterId.Tag("k1", "v1"))), () -> 1d);
|
||||
|
||||
@Test
|
||||
public void testConstruct() {
|
||||
gaugeInterceptor.onConstruct(enhancedInstance, null);
|
||||
|
||||
final MeterService service = ServiceManager.INSTANCE.findService(MeterService.class);
|
||||
final Map<MeterId, MeterTransformer> meterMap = (Map<MeterId, MeterTransformer>) Whitebox.getInternalState(service, "meterMap");
|
||||
Assert.assertEquals(1, meterMap.size());
|
||||
|
||||
final Object field = meterMap.values().iterator().next();
|
||||
Assert.assertNotNull(field);
|
||||
Assert.assertTrue(field instanceof GaugeTransformer);
|
||||
final GaugeTransformer gaugeTransformer = (GaugeTransformer) field;
|
||||
|
||||
Assert.assertNotNull(gaugeTransformer.getId());
|
||||
Assert.assertEquals("test", gaugeTransformer.getId().getName());
|
||||
Assert.assertEquals(MeterType.GAUGE, gaugeTransformer.getId().getType());
|
||||
Assert.assertEquals(Arrays.asList(new MeterTag("k1", "v1")), gaugeTransformer.getId().getTags());
|
||||
}
|
||||
|
||||
private static class GaugeEnhance extends GaugeImpl implements EnhancedInstance {
|
||||
protected GaugeEnhance(MeterId meterId, Supplier<Double> getter) {
|
||||
super(meterId, getter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSkyWalkingDynamicField() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyWalkingDynamicField(Object value) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.activation.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterService;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.HistogramTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterId;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.util.reflection.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class HistogramInterceptorTest {
|
||||
|
||||
@Rule
|
||||
public AgentServiceRule agentServiceRule = new AgentServiceRule();
|
||||
|
||||
private HistogramInterceptor histogramInterceptor = new HistogramInterceptor();
|
||||
private EnhancedInstance enhancedInstance = new HistogramEnhance(
|
||||
new MeterId("test", MeterId.MeterType.HISTOGRAM, Arrays.asList(new MeterId.Tag("k1", "v1"))),
|
||||
Arrays.asList(1d, 2d, 3d));
|
||||
|
||||
@Test
|
||||
public void testConstruct() {
|
||||
histogramInterceptor.onConstruct(enhancedInstance, null);
|
||||
|
||||
final MeterService service = ServiceManager.INSTANCE.findService(MeterService.class);
|
||||
final Map<MeterId, MeterTransformer> meterMap = (Map<MeterId, MeterTransformer>) Whitebox.getInternalState(service, "meterMap");
|
||||
Assert.assertEquals(1, meterMap.size());
|
||||
|
||||
final Object field = meterMap.values().iterator().next();
|
||||
Assert.assertNotNull(field);
|
||||
Assert.assertTrue(field instanceof HistogramTransformer);
|
||||
final HistogramTransformer histogramTransformer = (HistogramTransformer) field;
|
||||
|
||||
Assert.assertNotNull(histogramTransformer.getId());
|
||||
Assert.assertEquals("test", histogramTransformer.getId().getName());
|
||||
Assert.assertEquals(MeterType.HISTOGRAM, histogramTransformer.getId().getType());
|
||||
Assert.assertEquals(Arrays.asList(new MeterTag("k1", "v1")), histogramTransformer.getId().getTags());
|
||||
}
|
||||
|
||||
private static class HistogramEnhance extends HistogramImpl implements EnhancedInstance {
|
||||
protected HistogramEnhance(MeterId meterId, List<Double> steps) {
|
||||
super(meterId, steps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSkyWalkingDynamicField() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkyWalkingDynamicField(Object value) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.adapter.TookitCounterAdapter;
|
||||
import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ToolkitCounterAdapterTest {
|
||||
|
||||
@Test
|
||||
public void testGetCount() {
|
||||
final Counter counter = MeterFactory.counter("test").build();
|
||||
final TookitCounterAdapter adapter = new TookitCounterAdapter((CounterImpl) counter);
|
||||
|
||||
counter.increment(1d);
|
||||
counter.increment(2d);
|
||||
|
||||
Assert.assertEquals(adapter.getCount(), 3d, 0.0);
|
||||
|
||||
counter.increment(-4d);
|
||||
Assert.assertEquals(adapter.getCount(), -1d, 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCountWithRate() {
|
||||
final Counter counter = MeterFactory.counter("test_with_rate").mode(Counter.Mode.RATE).build();
|
||||
final TookitCounterAdapter adapter = new TookitCounterAdapter((CounterImpl) counter);
|
||||
|
||||
counter.increment(1d);
|
||||
counter.increment(2d);
|
||||
|
||||
Assert.assertEquals(adapter.getCount(), 3d, 0.0);
|
||||
Assert.assertEquals(adapter.getCount(), 0d, 0.0);
|
||||
|
||||
counter.increment(-4d);
|
||||
Assert.assertEquals(adapter.getCount(), -4d, 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetId() {
|
||||
final Counter counter = MeterFactory.counter("test").tag("k1", "v1").build();
|
||||
final TookitCounterAdapter adapter = new TookitCounterAdapter((CounterImpl) counter);
|
||||
|
||||
final MeterId id = adapter.getId();
|
||||
Assert.assertEquals("test", id.getName());
|
||||
Assert.assertEquals(MeterType.COUNTER, id.getType());
|
||||
Assert.assertEquals(1, id.getTags().size());
|
||||
Assert.assertEquals(new MeterTag("k1", "v1"), id.getTags().get(0));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitGaugeAdapter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ToolkitGaugeAdapterTest {
|
||||
|
||||
@Test
|
||||
public void testGetCount() {
|
||||
final Gauge gauge = MeterFactory.gauge("test", () -> 1d).build();
|
||||
final ToolkitGaugeAdapter adapter = new ToolkitGaugeAdapter(gauge);
|
||||
|
||||
Assert.assertEquals(adapter.getCount(), 1d, 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetId() {
|
||||
final Gauge gauge = MeterFactory.gauge("test", () -> 1d).tag("k1", "v1").build();
|
||||
final ToolkitGaugeAdapter adapter = new ToolkitGaugeAdapter(gauge);
|
||||
|
||||
final MeterId id = adapter.getId();
|
||||
Assert.assertEquals("test", id.getName());
|
||||
Assert.assertEquals(MeterType.GAUGE, id.getType());
|
||||
Assert.assertEquals(1, id.getTags().size());
|
||||
Assert.assertEquals(new MeterTag("k1", "v1"), id.getTags().get(0));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.toolkit.meter;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterId;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterTag;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterType;
|
||||
import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitHistogramAdapter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ToolkitHistogramAdapterTest {
|
||||
|
||||
@Test
|
||||
public void testGetAllBuckets() {
|
||||
final Histogram histogram = MeterFactory.histogram("test").steps(Arrays.asList(2d, 5d)).build();
|
||||
final ToolkitHistogramAdapter adapter = new ToolkitHistogramAdapter(histogram);
|
||||
|
||||
Assert.assertArrayEquals(adapter.getAllBuckets(), new double[] {0d, 2d, 5d}, 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBucketValues() {
|
||||
final Histogram histogram = MeterFactory.histogram("test").steps(Arrays.asList(2d, 5d)).build();
|
||||
final ToolkitHistogramAdapter adapter = new ToolkitHistogramAdapter(histogram);
|
||||
|
||||
histogram.addValue(1d);
|
||||
histogram.addValue(2d);
|
||||
histogram.addValue(3d);
|
||||
histogram.addValue(20d);
|
||||
|
||||
Assert.assertArrayEquals(adapter.getBucketValues(), new long[] {1L, 2L, 1L});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetId() {
|
||||
final Histogram histogram = MeterFactory.histogram("test").steps(Arrays.asList(2d, 5d)).tag("k1", "v1").build();
|
||||
final ToolkitHistogramAdapter adapter = new ToolkitHistogramAdapter(histogram);
|
||||
|
||||
final MeterId id = adapter.getId();
|
||||
Assert.assertEquals("test", id.getName());
|
||||
Assert.assertEquals(MeterType.HISTOGRAM, id.getType());
|
||||
Assert.assertEquals(1, id.getTags().size());
|
||||
Assert.assertEquals(new MeterTag("k1", "v1"), id.getTags().get(0));
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
<module>apm-toolkit-logback-1.x-activation</module>
|
||||
<module>apm-toolkit-opentracing-activation</module>
|
||||
<module>apm-toolkit-trace-activation</module>
|
||||
<module>apm-toolkit-meter-activation</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>apm-toolkit-activation</artifactId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
* Dependency the toolkit, such as using maven or gradle
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<artifactId>apm-toolkit-meter</artifactId>
|
||||
<version>${skywalking.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
* `Counter` API represents a single monotonically increasing counter, automatic collect data and report to backend.
|
||||
```java
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
|
||||
|
||||
Counter counter = MeterFactory.counter(meterName).tag("tagKey", "tagValue").mode(Counter.Mode.INCREMENT).build();
|
||||
counter.increment(1d);
|
||||
```
|
||||
1. `MeterFactory.counter` Create a new counter builder with the meter name.
|
||||
1. `Counter.Builder.tag(String key, String value)` Mark a tag key/value pair.
|
||||
1. `Counter.Builder.mode(Counter.Mode mode)` Change the counter mode, `RATE` mode means reporting rate to the backend.
|
||||
1. `Counter.Builder.build()` Build a new `Counter` which is collected and reported to the backend.
|
||||
1. `Counter.increment(double count)` Increment count to the `Counter`, It could be a positive/negative value.
|
||||
|
||||
* `Gauge` API represents a single numerical value.
|
||||
```java
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
|
||||
|
||||
ThreadPoolExecutor threadPool = ...;
|
||||
Gauge gauge = MeterFactory.gauge(meterName, () -> threadPool.getActiveCount()).tag("tagKey", "tagValue").build();
|
||||
```
|
||||
1. `MeterFactory.gauge(String name, Supplier<Double> getter)` Create a new gauge builder with the meter name and supplier function, this function need to return a `double` value.
|
||||
1. `Gauge.Builder.tag(String key, String value)` Mark a tag key/value pair.
|
||||
1. `Gauge.Builder.build()` Build a new `Gauge` which is collected and reported to the backend.
|
||||
|
||||
* `Histogram` API represents a summary sample observations with customize buckets.
|
||||
```java
|
||||
import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
|
||||
|
||||
Histogram histogram = MeterFactory.histogram("test").tag("tagKey", "tagValue").steps(Arrays.asList(1, 5, 10)).minValue(0).build();
|
||||
histogram.addValue(3);
|
||||
```
|
||||
1. `MeterFactory.histogram(String name)` Create a new histogram builder with the meter name.
|
||||
1. `Histogram.Builder.tag(String key, String value)` Mark a tag key/value pair.
|
||||
1. `Histogram.Builder.steps(List<Double> steps)` Set up the max values of every histogram buckets.
|
||||
1. `Histogram.Builder.minValue(double value)` Set up the minimal value of this histogram, default is `0`.
|
||||
1. `Histogram.Builder.build()` Build a new `Histogram` which is collected and reported to the backend.
|
||||
1. `Histogram.addValue(double value)` Add value into the histogram, automatically analyze what bucket count needs to be increment. rule: count into [step1, step2).
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
* Dependency the toolkit, such as using maven or gradle
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<artifactId>apm-toolkit-micrometer-registry</artifactId>
|
||||
<version>${skywalking.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
* Using `org.apache.skywalking.apm.meter.micrometer.SkywalkingMeterRegistry` as the registry, it could forward the MicroMeter collected metrics to OAP server.
|
||||
```java
|
||||
import org.apache.skywalking.apm.meter.micrometer.SkywalkingMeterRegistry;
|
||||
|
||||
SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
|
||||
|
||||
// If you has some counter want to rate by agent side
|
||||
SkywalkingConfig config = new SkywalkingConfig(Arrays.asList("test_rate_counter"));
|
||||
new SkywalkingMeterRegistry(config);
|
||||
|
||||
// Also you could using composite registry to combine multiple meter registry, such as collect to Skywalking and prometheus
|
||||
CompositeMeterRegistry compositeRegistry = new CompositeMeterRegistry();
|
||||
compositeRegistry.add(new PrometheusMeterRegistry(PrometheusConfig.DEFAULT));
|
||||
compositeRegistry.add(new SkywalkingMeterRegistry());
|
||||
```
|
||||
|
||||
* Using snake case as the naming convention. Such as `test.meter` will be send to `test_meter`.
|
||||
|
||||
* Using `Millisecond` as the time unit.
|
||||
|
||||
* Adapt micrometer data convention.
|
||||
|
||||
|Micrometer data type|Transform to meter name|Skywalking data type| Description|
|
||||
|----- |----- |----- |----- |
|
||||
|Counter|Counter name|Counter|Same with counter|
|
||||
|Gauges|Gauges name|Gauges|Same with gauges|
|
||||
|Timer|Timer name + "_count"|Counter|Execute finished count|
|
||||
| |Timer name + "_sum"|Counter|Total execute finished duration|
|
||||
| |Timer name + "_max"|Gauges|Max duration of execute finished time|
|
||||
| |Timer name + "_histogram"|Histogram|Histogram of execute finished duration|
|
||||
|LongTaskTimer|Timer name + "_active_count"|Gauges|Executing task count|
|
||||
| |Timer name + "_duration_sum"|Counter|All of executing task sum duration|
|
||||
| |Timer name + "_max"|Counter|Current longest running task execute duration|
|
||||
|Function Timer|Timer name + "_count"|Gauges|Execute finished timer count|
|
||||
| |Timer name + "_sum"|Gauges|Execute finished timer total duration|
|
||||
|Function Counter|Counter name|Counter|Custom counter value|
|
||||
|Distribution summary|Summary name + "_count"|Counter|Total record count|
|
||||
| |Summary name + "_sum"|Counter|Total record amount sum|
|
||||
| |Summary name + "_max"|Gauges|Max record amount|
|
||||
| |Summary name + "_histogram"|Gauges|Histogram of the amount|
|
||||
|
||||
* Not Adapt data convention.
|
||||
|
||||
|Micrometer data type|Data type|
|
||||
|----- |----- |
|
||||
|LongTaskTimer|Histogram|
|
||||
|
|
@ -105,6 +105,9 @@ property key | Description | Default |
|
|||
`profile.duration`|Max monitor segment time(minutes), if current segment monitor time out of limit, then stop it.|`10`|
|
||||
`profile.dump_max_stack_depth`|Max dump thread stack depth|`500`|
|
||||
`profile.snapshot_transport_buffer_size`|Snapshot transport to backend buffer size|`50`|
|
||||
`meter.active`|If true, the agent collects and reports metrics to the backend.|`true`|
|
||||
`meter.report_interval`|Report meters interval. The unit is second|`20`|
|
||||
`meter.max_meter_size`| Max size of the meter pool |`500`|
|
||||
`plugin.peer_max_length `|Peer maximum description limit.|`200`|
|
||||
`plugin.mongodb.trace_param`|If true, trace all the parameters in MongoDB access, default is false. Only trace the operation, not include parameters.|`false`|
|
||||
`plugin.mongodb.filter_length_limit`|If set to positive number, the `WriteRequest.params` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.|`256`|
|
||||
|
|
@ -159,11 +162,13 @@ Now, we have the following known bootstrap plugins.
|
|||
* Monitor a big cluster by different SkyWalking services. Use [Namespace](Namespace.md) to isolate the context propagation.
|
||||
* Set client [token](Token-auth.md) if backend open [token authentication](../../backend/backend-token-auth.md).
|
||||
* Application Toolkit, are a collection of libraries, provided by SkyWalking APM. Using them, you have a bridge between your application and SkyWalking APM agent.
|
||||
* If you want to use OpenTracing Java APIs, try [SkyWalking OpenTracing compatible tracer](Opentracing.md). More details you could find at http://opentracing.io
|
||||
* If you want your codes to interact with SkyWalking agent, including `getting trace id`, `setting tags`, `propagating custom data` etc.. Try [SkyWalking manual APIs](Application-toolkit-trace.md).
|
||||
* If you require customized metrics, try [SkyWalking Meter System Toolkit](Application-toolkit-meter.md).
|
||||
* If you want to print trace context(e.g. traceId) in your logs, choose the log frameworks, [log4j](Application-toolkit-log4j-1.x.md),
|
||||
[log4j2](Application-toolkit-log4j-2.x.md), [logback](Application-toolkit-logback-1.x.md)
|
||||
* If you want your codes to interact with SkyWalking agent, including `getting trace id`, `setting tags`, `propagating custom data` etc.. Try [SkyWalking manual APIs](Application-toolkit-trace.md).
|
||||
* If you want to continue traces across thread manually, use [across thread solution APIs](Application-toolkit-trace-cross-thread.md).
|
||||
* If you want to forward MicroMeter/Spring Sleuth metrics to Meter System, use [SkyWalking MicroMeter Register](Application-toolkit-micrometer.md).
|
||||
* If you want to use OpenTracing Java APIs, try [SkyWalking OpenTracing compatible tracer](Opentracing.md). More details you could find at http://opentracing.io
|
||||
* If you want to specify the path of your agent.config file. Read [set config file through system properties](Specified-agent-config.md)
|
||||
|
||||
## Plugin Development Guide
|
||||
|
|
|
|||
Loading…
Reference in New Issue