Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Micrometer Observations #1760

Merged
merged 31 commits into from Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
212fdf2
WIP on Micrometer Observations
marcingrzejszczak Sep 19, 2022
5e8192c
Added verification that metrics are measured
marcingrzejszczak Sep 19, 2022
e23a805
Fixed formatting
marcingrzejszczak Sep 19, 2022
97b23e9
Fixed wrong status code method call
marcingrzejszczak Sep 19, 2022
9119a61
Converted to using around
marcingrzejszczak Sep 20, 2022
8832aff
Fixed compilation issues
marcingrzejszczak Sep 20, 2022
75f5a97
prepare release 11.10
velo Sep 21, 2022
6a213cf
[ci skip] updating versions to next development iteration 11.11-SNAPSHOT
velo Sep 21, 2022
4a9d1fb
Preparing for next development version
velo Sep 21, 2022
5afb234
build(deps): bump json from 20220320 to 20220924 (#1768)
dependabot[bot] Sep 26, 2022
f02d3ca
Updated to latest micrometer changes
marcingrzejszczak Sep 27, 2022
2551952
Enriches via clientInterceptors
marcingrzejszczak Sep 28, 2022
2392312
Fixed the error in the DEFAULT instance
marcingrzejszczak Sep 28, 2022
24ae435
Reverts enriching of CLientInterceptor to achieve observability
marcingrzejszczak Sep 28, 2022
a2c4323
build(deps): bump slf4j.version from 2.0.2 to 2.0.3 (#1769)
dependabot[bot] Sep 29, 2022
4b675d7
build(deps): bump kotlin.version from 1.7.10 to 1.7.20 (#1771)
dependabot[bot] Sep 30, 2022
258c464
build(deps): bump asm from 9.3 to 9.4 (#1777)
dependabot[bot] Oct 3, 2022
ba413e8
Applied latest changes of Micrometer
marcingrzejszczak Oct 4, 2022
734272c
Removing conflicts
marcingrzejszczak Nov 4, 2022
0421e72
Polish
marcingrzejszczak Nov 4, 2022
91ec111
Upgraded Micrometer to 1.10.0'
marcingrzejszczak Nov 7, 2022
f03f81d
Merge branch 'master' into micrometerObservations
marcingrzejszczak Nov 9, 2022
0784382
Alternative micrometer observation using capability
Nov 9, 2022
80f2e77
Ban 'repositories'
Nov 9, 2022
a2f21fa
Merge remote-tracking branch 'origin/master' into micrometerObservations
Nov 9, 2022
f1524cb
Merge branch 'master' into micrometerObservations
velo Nov 9, 2022
9f7a144
Merge branch 'master' into micrometerObservations
velo Nov 10, 2022
07b1201
Merge remote-tracking branch 'velo/micrometerObservations' into micro…
marcingrzejszczak Nov 14, 2022
96abdbd
Applied my own review suggestions ;)
marcingrzejszczak Nov 14, 2022
07d77cf
Merge branch 'master' into micrometerObservations
marcingrzejszczak Nov 14, 2022
ee58b97
Polish
marcingrzejszczak Nov 14, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion core/pom.xml
Expand Up @@ -86,7 +86,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
Expand Down
25 changes: 23 additions & 2 deletions core/src/main/java/feign/Request.java
Expand Up @@ -13,16 +13,17 @@
*/
package feign;

import static feign.Util.checkNotNull;
import static feign.Util.valuesOrEmpty;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import static feign.Util.checkNotNull;
import static feign.Util.valuesOrEmpty;

/**
* An immutable request to an http server.
Expand Down Expand Up @@ -206,6 +207,26 @@ public Map<String, Collection<String>> headers() {
return Collections.unmodifiableMap(headers);
}

/**
* Add new entries to request Headers. It overrides existing entries
*
* @param key
* @param value
*/
public void header(String key, String value) {
header(key, Arrays.asList(value));
}

/**
* Add new entries to request Headers. It overrides existing entries
*
* @param key
* @param values
*/
public void header(String key, Collection<String> values) {
headers.put(key, values);
}

/**
* Charset of the request.
*
Expand Down
34 changes: 23 additions & 11 deletions core/src/main/java/feign/RequestTemplate.java
Expand Up @@ -13,18 +13,32 @@
*/
package feign;

import static feign.Util.CONTENT_LENGTH;
import static feign.Util.checkNotNull;
import feign.Request.HttpMethod;
import feign.template.*;
import feign.template.BodyTemplate;
import feign.template.HeaderTemplate;
import feign.template.QueryTemplate;
import feign.template.UriTemplate;
import feign.template.UriUtils;
import java.io.Serializable;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static feign.Util.*;

/**
* Request Builder for an HTTP Target.
Expand Down Expand Up @@ -764,12 +778,10 @@ private RequestTemplate appendHeader(String name, Iterable<String> values, boole
} else {
return HeaderTemplate.create(headerName, values);
}
} else if (literal) {
return HeaderTemplate.appendLiteral(headerTemplate, values);
} else {
if (literal) {
return HeaderTemplate.appendLiteral(headerTemplate, values);
} else {
return HeaderTemplate.append(headerTemplate, values);
}
return HeaderTemplate.append(headerTemplate, values);
}
});
return this;
Expand All @@ -791,7 +803,7 @@ public RequestTemplate headers(Map<String, Collection<String>> headers) {
}

/**
* Returns an immutable copy of the Headers for this request.
* Returns an copy of the Headers for this request.
*
* @return the currently applied headers.
*/
Expand All @@ -802,10 +814,10 @@ public Map<String, Collection<String>> headers() {

/* add the expanded collection, but only if it has values */
if (!values.isEmpty()) {
headerMap.put(key, Collections.unmodifiableList(values));
headerMap.put(key, values);
}
});
return Collections.unmodifiableMap(headerMap);
return headerMap;
}

/**
Expand Down
20 changes: 15 additions & 5 deletions core/src/test/java/feign/RequestTemplateTest.java
Expand Up @@ -15,10 +15,13 @@

import static feign.assertj.FeignAssertions.assertThat;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.data.MapEntry.entry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import feign.Request.HttpMethod;
import feign.template.UriUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -27,8 +30,6 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import feign.Request.HttpMethod;
import feign.template.UriUtils;

public class RequestTemplateTest {

Expand Down Expand Up @@ -472,16 +473,25 @@ public void shouldRetrieveHeadersWithoutNull() {

}

@SuppressWarnings("ConstantConditions")
@Test(expected = UnsupportedOperationException.class)
public void shouldNotInsertHeadersImmutableMap() {
public void shouldNotMutateInternalHeadersMap() {
RequestTemplate template = new RequestTemplate()
.header("key1", "valid");

assertThat(template.headers()).hasSize(1);
assertThat(template.headers().keySet()).containsExactly("key1");
assertThat(template.headers().get("key1")).containsExactly("valid");

template.headers().put("key2", Collections.singletonList("other value"));
// nothing should change
assertThat(template.headers()).hasSize(1);
assertThat(template.headers().keySet()).containsExactly("key1");
assertThat(template.headers().get("key1")).containsExactly("valid");

template.headers().get("key1").add("value2");
// nothing should change either
assertThat(template.headers()).hasSize(1);
assertThat(template.headers().keySet()).containsExactly("key1");
assertThat(template.headers().get("key1")).containsExactly("valid");
}

@Test
Expand Down
16 changes: 14 additions & 2 deletions micrometer/pom.xml
Expand Up @@ -27,6 +27,7 @@

<properties>
<main.basedir>${project.basedir}/..</main.basedir>
<micrometer.version>1.10.0</micrometer.version>
</properties>

<dependencies>
Expand All @@ -42,19 +43,31 @@
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.10.0</version>
<version>${micrometer.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-test</artifactId>
<version>${micrometer.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>feign-okhttp</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand All @@ -71,5 +84,4 @@
</plugin>
</plugins>
</build>

</project>
@@ -0,0 +1,72 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* 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 feign.micrometer;

import feign.Request;
import feign.Response;
import io.micrometer.common.KeyValues;
import io.micrometer.common.lang.Nullable;

/**
* Default implementation of {@link FeignObservationConvention}.
*
* @since 12.1
* @see FeignObservationConvention
*/
public class DefaultFeignObservationConvention implements FeignObservationConvention {

/**
* Singleton instance of this convention.
*/
public static final DefaultFeignObservationConvention INSTANCE =
new DefaultFeignObservationConvention();

// There is no need to instantiate this class multiple times, but it may be extended,
// hence protected visibility.
protected DefaultFeignObservationConvention() {}

@Override
public String getName() {
return "http.client.requests";
}

@Override
public String getContextualName(FeignContext context) {
return "HTTP " + getMethodString(context.getCarrier());
}

@Override
public KeyValues getLowCardinalityKeyValues(FeignContext context) {
String templatedUrl = context.getCarrier().requestTemplate().methodMetadata().template().url();
return KeyValues.of(
FeignObservationDocumentation.HttpClientTags.METHOD
.withValue(getMethodString(context.getCarrier())),
FeignObservationDocumentation.HttpClientTags.URI
.withValue(templatedUrl),
FeignObservationDocumentation.HttpClientTags.STATUS
.withValue(getStatusValue(context.getResponse())));
}

String getStatusValue(@Nullable Response response) {
return response != null ? String.valueOf(response.status()) : "CLIENT_ERROR";
}

String getMethodString(@Nullable Request request) {
if (request == null) {
return "UNKNOWN";
}
return request.httpMethod().name();
}

}
34 changes: 34 additions & 0 deletions micrometer/src/main/java/feign/micrometer/FeignContext.java
@@ -0,0 +1,34 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* 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 feign.micrometer;

import feign.Request;
import feign.Response;
import io.micrometer.observation.transport.RequestReplySenderContext;
import io.micrometer.observation.transport.SenderContext;

/**
* A {@link SenderContext} for Feign.
*
* @author Marcin Grzejszczak
* @since 12.1
*/
public class FeignContext extends RequestReplySenderContext<Request, Response> {

public FeignContext(Request request) {
super(Request::header);
setCarrier(request);
}

}
@@ -0,0 +1,31 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* 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 feign.micrometer;

import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationConvention;

/**
* {@link ObservationConvention} for Feign.
*
* @since 12.1
*/
public interface FeignObservationConvention extends ObservationConvention<FeignContext> {

@Override
default boolean supportsContext(Observation.Context context) {
return context instanceof FeignContext;
}

}