I have an application running on port 7070 on my local. It exposes and endpoint /metrics and shows all the tags that are available. Prometheus is not able to get these data and it says 'expected label name, got "BCLOSE"'.
I have been trying to figure this out but not sure why this code doesn't work:
import io.micrometer.prometheus.PrometheusMeterRegistry;
import io.prometheus.client.exporter.common.TextFormat;
import metrics.PrometheusRegistry;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
#Path("/metrics")
public class MetricsController {
private final PrometheusMeterRegistry prometheusRegistry = PrometheusRegistry.INSTANCE();
#GET
public Response getMetrics(#Context HttpHeaders headers) {
Writer writer = new StringWriter();
try {
TextFormat.write004(writer, prometheusRegistry.getPrometheusRegistry().metricFamilySamples());
} catch (IOException e) {
e.printStackTrace();
}
return writer.toString();
}
}
Also, the application is neither a sprintboot nor a spring project.
Tried this:
#GET
public Response getMetrics(#Context HttpHeaders headers) {
String accept = headers.getRequestHeader("Accept").get(0);
System.out.println("Accept Header --------------------------> " + accept);
return Response.ok(prometheusRegistry.scrape(), "application/openmetrics-text").build();
}
Even then the same error as above SS.
This worked for me:
#GET
public Response getMetrics() {
return Response.ok(prometheusRegistry.scrape(), TextFormat.CONTENT_TYPE_004).build();
}
Related
I am trying to consume Braintree webhooks in a java microservice (Micronaut fwiw).
The issue that I'm having is that when I try to parse the webhook body, I get an error: " Error: payload contains illegal characters", which it does. So I'm wondering if maybe I'm casting the request body to something thats inserting the characters...? (the body is x-www-form-urlencoded)
package com.autonomy;
import com.braintreegateway.*;
import event_broker.BrokerServiceGrpc;
import event_broker.EventBroker;
import events.Events;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.micronaut.context.annotation.Value;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.Normalizer;
import java.time.Clock;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
#Controller("/webhooks")
public class WebhooksController {
private final Logger logger = LoggerFactory.getLogger("BraintreeServiceJava");
#Value("${env}") String env;
#Value("${braintree.merchant.id}") String braintreeMerchantId;
#Value("${braintree.public.key}") String braintreePublicKey;
#Value("${braintree.private.key}") String braintreePrivateKey;
#Post(consumes = MediaType.APPLICATION_FORM_URLENCODED)
public HttpResponse<?> consumeWebhook(#Body String body) {
BraintreeGateway gateway =
new BraintreeGateway(determineEnv(env),
braintreeMerchantId,
braintreePublicKey,
braintreePrivateKey
);
logger.info(body);
try {
String decodedBody = body; // was doing a decode here that didn't do anything
logger.info(decodedBody);
Map<String, String> map = new HashMap<>();
Arrays.stream(decodedBody.split("&")).toList().forEach(pair -> {
String[] param = pair.split("=");
map.put(param[0], param[1]);
});
WebhookNotification webhookNotification = gateway.webhookNotification().parse(
map.get("bt_signature"),
map.get("bt_payload")
);
..... Do stuff
} catch (Exception e) {
logger.error(String.format("Braintree webhook failed for %s. Error: %s", kind, e.getMessage()), e);
return HttpResponse.status(HttpStatus.BAD_REQUEST);
}
return HttpResponse.status(HttpStatus.OK);
}
private Environment determineEnv(String env) {
if (env.equals("beta") || env.equals("prod")) {
return Environment.PRODUCTION;
} else {
return Environment.SANDBOX;
}
}
}
Try:
#Post(consumes = MediaType.APPLICATION_FORM_URLENCODED)
public HttpResponse<?> consumeWebhook(String bt_signature, String bt_payload)
BTW: What 'illegal characters' were in the body that was logged?
When performing a POST request to the server, and I call readEntity, I am presented with the error "Premature end of Content-Length delimited message body (expected: 349; received: 0)".
At first, I thought the server was returning me 0 bytes, but when making the same request via postman, the return comes correctly. I also captured the network packets with WireShark, what I could see in the packages is that the header comes in one package and the body in another. I don't know if that would be the problem. Another thing I noticed is that the connection is terminated with an RST, as shown below:
https://i.ibb.co/MSGhHJM/Wire-Shark.png
Following is code snippets, where the line that occurs the error is: params = post.readEntity(HashMap.class);
Config class imports:
import com.google.inject.Inject;
import org.jose4j.json.internal.json_simple.JSONArray;
import javax.ws.rs.core.Response;
import java.util.HashMap;
Config class:
public void configure(SchedulerModule module, SessionInfo session) {
Response post = connection.post(session, ServiceURL.CONFIG_URL, new JSONArray());
params = post.readEntity(HashMap.class); // Linha que o erro ocorre
if ("R".equals(params.get("IE_TIPO")) && validaInteger(params.get("QT_INTERVALO")) > 0) {
module.setDelay(validaInteger(params.get("QT_INTERVALO")));
module.setRate(validaInteger(params.get("QT_INTERVALO")));
isRun = true;
} else {
isRun = false;
}
}
Connection class imports:
import com.google.inject.Inject;
import com.google.inject.name.Named;
import org.jose4j.json.internal.json_simple.JSONArray;
import org.jose4j.json.internal.json_simple.JSONObject;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.stream.Collectors;
Connection class method:
public Response post(SessionInfo sessionInfo, ServiceURL url, JSONArray array) {
Client client = ClientBuilder.newClient();
try {
Invocation.Builder builder = client.target(backendUrl).path(url.getUrl())
.request(MediaType.APPLICATION_JSON_TYPE)
.header("idSessao", sessionInfo.getIdSessao())
.header("crsfToken", sessionInfo.getCrsfToken())
.header("Cookie", sessionInfo.getCookieHeader());
return builder.post(Entity.entity(array == null ? "[]" : array.toString(), MediaType.APPLICATION_JSON_TYPE));
} catch (Exception e) {
System.out.println("Failure" + e.getMessage());
} finally {
client.close();
}
return null;
}
I need to get the return body of this request. Can you help me?
I'm trying to confirm the value of an HTTP response header with Spring 5 WebClient, but only if the web call responds with an HTTP 200 status code. In this use case if authentication is not successful, the API call returns with an HTTP 401 without the response header present. I have the following code below which functionally works, but it is making the web call twice (because I'm blocking twice). Short of just blocking on the HTTP response header only, and putting a try/catch for an NPE when the header isn't present, is there any "cleaner" way to do this?
import java.net.URI;
import java.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFunction;
import org.springframework.web.reactive.function.client.ExchangeFunctions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
#SpringBootApplication
public class ContentCheckerApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(ContentCheckerApplication.class);
private ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
public static void main(String[] args) {
SpringApplication app = new SpringApplication(ContentCheckerApplication.class);
// prevent SpringBoot from starting a web server
app.setWebApplicationType(WebApplicationType.NONE);
app.run(args);
}
#Bean
public CommandLineRunner myCommandLineRunner() {
return args -> {
// Our reactive code will be declared here
LinkedMultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
formData.add("username", args[2]);
formData.add("password", args[3]);
ClientRequest request = ClientRequest.method(HttpMethod.POST, new URI(args[0]+"/api/token"))
.body(BodyInserters.fromFormData(formData)).build();
Mono<ClientResponse> mresponse = exchange.exchange(request);
Mono<String> mnewToken = mresponse.map(response -> response.headers().asHttpHeaders().getFirst("WSToken"));
LOGGER.info("Blocking for status code...");
HttpStatus statusCode = mresponse.block(Duration.ofMillis(1500)).statusCode();
LOGGER.info("Got status code!");
if (statusCode.value() == 200) {
String newToken = mnewToken.block(Duration.ofMillis(1500));
LOGGER.info("Auth token is: " + newToken);
} else {
LOGGER.info("Unable to authenticate successfully! Status code: "+statusCode.value());
}
};
}
}
Thanks to comments from #M. Deinum to guide me, I have the following code which is workable now.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ExchangeFunction;
import org.springframework.web.reactive.function.client.ExchangeFunctions;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
#SpringBootApplication
public class ContentCheckerApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(ContentCheckerApplication.class);
private ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
public static void main(String[] args) {
SpringApplication app = new SpringApplication(ContentCheckerApplication.class);
// prevent SpringBoot from starting a web server
app.setWebApplicationType(WebApplicationType.NONE);
app.run(args);
}
#Bean
public CommandLineRunner myCommandLineRunner() {
return args -> {
// Change some Netty defaults
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(
options -> options.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
.compression(true)
.afterNettyContextInit(ctx -> {
ctx.addHandlerLast(new ReadTimeoutHandler(1500, TimeUnit.MILLISECONDS));
}));
LinkedMultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
formData.add("username", args[2]);
formData.add("password", args[3]);
WebClient webClient = WebClient.builder().clientConnector(connector).build();
Mono<String> tokenResult = webClient.post()
.uri( args[0] + "/api/token" )
.body( BodyInserters.fromFormData(formData))
.exchange()
.onErrorMap(ContentCheckerApplication::handleAuthTokenError)
.map(response -> {
if (HttpStatus.OK.equals(response.statusCode())) {
return response.headers().asHttpHeaders().getFirst("WSToken");
} else {
return "";
}
});
LOGGER.info("Subscribing for the result and then going to sleep");
tokenResult.subscribe(ContentCheckerApplication::handleAuthTokenResponse);
Thread.sleep(3600000);
};
}
private static Throwable handleAuthTokenError(Throwable e) {
LOGGER.error("Exception caught trying to process authentication token. ",e);
ContentCheckerApplication.handleAuthTokenResponse("");
return null;
}
private static void handleAuthTokenResponse(String newToken) {
LOGGER.info("Got status code!");
if (!newToken.isEmpty()) {
LOGGER.info("Auth token is: " + newToken);
} else {
LOGGER.info("Unable to authenticate successfully!");
}
System.exit(0);
}
}
I've a simple RestEasy WebServie which will take a dependency.
When I test by publishing into Wildfly server everything is working fine. But I tried to mock it using JUnit. But, it's throwing null pointer exception as the dependency isn't injected.
Following is the code which I've done. What is wrong I'm doing.
WebService;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/")
public class IlService {
#Inject
private il.helper.RequestData rData;
#GET
public Response postIds() {
return Response.status( 200 ).type( MediaType.TEXT_HTML ).entity( rData.getRequestData().get( "logicalOperator" ).asText() ).build();
}
}
JUnit Test class:
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockDispatcherFactory;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.jboss.resteasy.spi.InjectorFactory;
import org.jboss.resteasy.spi.PropertyInjector;
import org.jboss.resteasy.spi.Registry;
import org.jboss.resteasy.spi.ResourceFactory;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.junit.Before;
import org.junit.Test;
import il.helper.RequestData;
import il.services.IlService;
import junit.framework.Assert;
public class IlServiceTest {
private Dispatcher dispatcher;
ResteasyProviderFactory resteasyProviderFactory;
ResourceFactory factory;
InjectorFactory injectorFactory;
PropertyInjector propertyInjector;
#Before
public void setUpResource() {
dispatcher = MockDispatcherFactory.createDispatcher();
resteasyProviderFactory = dispatcher.getProviderFactory();
injectorFactory = resteasyProviderFactory.getInjectorFactory();
propertyInjector = injectorFactory.createPropertyInjector( IlService.class, resteasyProviderFactory );
propertyInjector.inject( new RequestData() );
resteasyProviderFactory.setInjectorFactory( injectorFactory );
Registry registry = dispatcher.getRegistry();
registry.addSingletonResource( new IlService() );
}
#Test
public void IlServicePost() {
try {
MockHttpRequest request = MockHttpRequest.create( "get", "" );
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke( request, response );
Assert.assertEquals( 200, response.getStatus() );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
Hello I have a class for doing webdav related operations such as creating a directory, Implementatiion can be seen below (the createDir method). The question is how to test it nicely, perhaps using EasyMock or a similar lib. Any ideas? thanks!
package foobar;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.jackrabbit.webdav.client.methods.DavMethod;
import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import mypackage.httpdclient.util.URLHandler;
public class WebDavImpl{
private static final String SEPARATOR = " ----- ";
private HttpClient httpClient;
public StorageSpaceClientImpl() {
httpClient = new HttpClient();
}
public String createDir(String dirName) {
String response = null;
String url = URLHandler.getInstance().getDirectoryUrl(dirName);
DavMethod mkcol = new MkColMethod(url);
try {
httpClient.executeMethod(mkcol);
response = mkcol.getStatusCode() + SEPARATOR + mkcol.getStatusText();
} catch (IOException ex) {
} finally {
mkcol.releaseConnection();
}
return response;
}
}