Code Monkey home page Code Monkey logo

logger-java-rest-assured's Introduction

Report Portal logger for REST Assured

Maven Central CI Build codecov Join Slack chat! stackoverflow Build with Love

The latest version: 5.3.2. Please use Maven Central link above to get the logger.

Overview

REST Assured Request/Response logger for Report Portal

The logger intercept and logs all Requests and Responses issued by REST Assured into Report Portal in Markdown format, including multipart requests. It recognizes payload types and attach them in corresponding manner: image types will be logged as images with thumbnails, binary types will be logged as entry attachments, text types will be formatted and logged in Markdown code blocks.

Configuration

Build system configuration

You need to add the logger as one of your dependencies in Maven or Gradle.

Maven

pom.xml

<project>
    <!-- project declaration omitted -->

    <dependencies>
        <dependency>
            <groupId>com.epam.reportportal</groupId>
            <artifactId>logger-java-rest-assured</artifactId>
            <version>5.3.2</version>
        </dependency>
    </dependencies>

    <!-- build config omitted -->
</project>

Gradle

build.gradle

dependencies {
    testCompile 'com.epam.reportportal:logger-java-rest-assured:5.3.2'
}

REST Assured configuration

To start getting Request and Response logging in Report Portal you need to add the logger as one of your REST Assured filters. The best place for it is one which will be initialized at the earliest moment once during the test execution. E.G. a static initialization block in a base class for all tests:

public class BaseTest {
	static {
		RestAssured.filters(new ReportPortalRestAssuredLoggingFilter(42, LogLevel.INFO));
	}
}

If you don't have a base class, you can put initialization into one of the most general initialization block. E.G. for TestNG it may be @BeforeSuite:

public class ApiTest {
	@BeforeSuite
	public void setupRestAssured() {
		RestAssured.filters(new ReportPortalRestAssuredLoggingFilter(42, LogLevel.INFO));
	}
}

NOTE: If you have more than one suite in your execution then it will mean REST Assured will be initialized over and over again with the Logger and you will get log duplication in the following suites. You can apply RestAssured.reset(); before the filter adding to avoid that. But this also means you will have to configure REST Assured anew each suite.

Sanitize Request / Response data

To avoid logging sensitive data into Report Portal you can use corresponding converters:

  • Cookie converter
  • Header converter
  • URI converter
  • Content prettiers

Cookie, Header and URI converters are set in the logger constructor:

public class BaseTest {
	static {
		RestAssured.filters(new ReportPortalRestAssuredLoggingFilter(
				42,
				LogLevel.INFO,
				SanitizingHttpHeaderConverter.INSTANCE,
				DefaultHttpHeaderConverter.INSTANCE,
				DefaultCookieConverter.INSTANCE,
				DefaultUriConverter.INSTANCE
		));
	}
}

You are free to implement any converter by yourself with java.util.function.Function interface.

Content prettier are more complex, they parse data based on its content type and apply defined transformations. Default prettiers just pretty-print JSON, HTML and XML data. To apply a custom content prettier call ReportPortalRestAssuredLoggingFilter.setContentPrettiers. E.G.:

public class BaseTest {
	private static final Map<String, Function<String, String>> MY_PRETTIERS = new HashMap<String, Function<String, String>>() {{
		put(ContentType.APPLICATION_XML.getMimeType(), XmlPrettier.INSTANCE);
		put(ContentType.APPLICATION_SOAP_XML.getMimeType(), XmlPrettier.INSTANCE);
		put(ContentType.APPLICATION_ATOM_XML.getMimeType(), XmlPrettier.INSTANCE);
		put(ContentType.APPLICATION_SVG_XML.getMimeType(), XmlPrettier.INSTANCE);
		put(ContentType.APPLICATION_XHTML_XML.getMimeType(), XmlPrettier.INSTANCE);
		put(ContentType.TEXT_XML.getMimeType(), XmlPrettier.INSTANCE);
		put(ContentType.APPLICATION_JSON.getMimeType(), JsonPrettier.INSTANCE);
		put("text/json", JsonPrettier.INSTANCE);
		put(ContentType.TEXT_HTML.getMimeType(), HtmlPrettier.INSTANCE);
	}};

	static {
		RestAssured.filters(new ReportPortalRestAssuredLoggingFilter(42, LogLevel.INFO).setContentPrettiers(MY_PRETTIERS));
	}
}

logger-java-rest-assured's People

Contributors

hardnorth avatar raikbitters avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

logger-java-rest-assured's Issues

ERROR LaunchLoggingCallback : [26] ReportPortal execution error with logger-java-rest-assured

Describe the bug

We try to use logger-java-rest-assured library to log request/response logs to Report Portal, that runs in AWS. So, we need for logs to be present after pipelines run in GitLab. Without that library all works good, we have connection and reports we need, we see logs, but, obviously, not Rest-Assured requests/responses.

When we add logger-java-rest-assured, locally, all works fine. I mean, that we have connection with Report Portal instance, we have reports, logs (with all Rest-Assured request/response) and even log filter is working.

But, if we run same build on the pipelines, we got this:

14:06:35.721 [rp-io-1] ERROR LaunchLoggingCallback : [26] ReportPortal execution error [223](https://gitlab.****/dev/services/****/-/jobs/3497256#L223) retrofit2.adapter.rxjava2.HttpException: HTTP 401 [224](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L224) at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:57) [225](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L225) at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:38) [226](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L226) at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:48) [227](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L227) at io.reactivex.Observable.subscribe(Observable.java:12267) [228](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L228) at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:35) [229](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L229) at io.reactivex.Observable.subscribe(Observable.java:12267) [230](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L230) at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96) [231](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L231) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38) [232](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L232) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:26) [233](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L233) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) [234](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L234) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [235](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L235) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [236](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L236) at java.base/java.lang.Thread.run(Thread.java:829) [237](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L237) 14:06:35.723 [rp-io-1] ERROR LaunchLoggingCallback : [26] ReportPortal execution error [238](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L238) retrofit2.adapter.rxjava2.HttpException: HTTP 401 [239](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L239) at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:57) [240](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L240) at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:38) [241](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L241) at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:48) [242](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L242) at io.reactivex.Observable.subscribe(Observable.java:12267) [243](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L243) at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:35) [244](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L244) at io.reactivex.Observable.subscribe(Observable.java:12267) [245](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L245) at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96) [246](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L246) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38) [247](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L247) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:26) [248](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L248) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) [249](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L249) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [250](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L250) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [251](https://gitlab.****.systems/dev/services/****/-/jobs/3497256#L251) at java.base/java.lang.Thread.run(Thread.java:829)

As a result - no connection to Report Portal. We can't find out the reason of that 401 error and how we can fix it.
Here are what related dependencies we have in build.gradle:

compile group: 'io.rest-assured', name: 'rest-assured', version: '5.1.1' 
compile group: 'com.epam.reportportal', name: 'client-java', version: '5.1.10'
compile group: 'com.epam.reportportal', name: 'agent-java-testng', version: '5.1.0'
compile group: 'com.epam.reportportal', name: 'logger-java-log4j', version: '5.1.4'
compile group: 'com.epam.reportportal', name: 'logger-java-logback', version: '5.1.2'
compile group: 'com.google.guava', name: 'guava', version: '29.0-jre'
testCompile 'com.epam.reportportal:logger-java-rest-assured:5.2.1'
testCompile group: 'org.testng', name: 'testng', version: '7.3.0'
implementation group: 'org.apache.groovy', name: 'groovy', version: '4.0.1'

here is a listener in regression.xml:

<listeners>
        <listener class-name="com.epam.reportportal.testng.ReportPortalTestNGListener"/>
 </listeners>

Here is a webhook:

@BeforeSuite
	public void baseTestStart() {

		log.info("This is the BaseTest BeforeSuite...");
		

		// add filters to log Rest Assured calls and ignore some of them
        RestAssured.filters(new ReportPortalRestAssuredLoggingFilter(42, LogLevel.INFO)
                .addRequestFilter(requestSpec -> {
                            var pathValue = getPathValue(requestSpec);
                            return ignoredLogPathList.contains(pathValue);
                        }
                ));

	}

I've tried to "play" with different versions - same result. Locally all is good. On the pipeline job - 401 Response, no connection.

Could you please help to clarify why we got that error? If you need other details, please ask

Custom prettiers don't get registered

Describe the bug
Registered custom prettier provokes

java.lang.ClassCastException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap')
	at com.epam.reportportal.restassured.support.HttpEntityFactory.createHttpRequestFormatter(HttpEntityFactory.java:144)
	at com.epam.reportportal.restassured.ReportPortalRestAssuredLoggingFilter.filter(ReportPortalRestAssuredLoggingFilter.java:167)

Steps to Reproduce
Steps to reproduce the behavior:

  1. Register new prettier custom_type as per README.md
  2. for me it was like
public class BaseTest {
    private static final Map<String, Function<String, String>> REPORTPORTAL_PRETTIERS = Map.of(
            org.apache.http.entity.ContentType.APPLICATION_XML.getMimeType(), XmlPrettier.INSTANCE,
            org.apache.http.entity.ContentType.APPLICATION_SOAP_XML.getMimeType(), XmlPrettier.INSTANCE,
            org.apache.http.entity.ContentType.APPLICATION_ATOM_XML.getMimeType(), XmlPrettier.INSTANCE,
            org.apache.http.entity.ContentType.APPLICATION_SVG_XML.getMimeType(), XmlPrettier.INSTANCE,
            org.apache.http.entity.ContentType.APPLICATION_XHTML_XML.getMimeType(), XmlPrettier.INSTANCE,
            org.apache.http.entity.ContentType.TEXT_XML.getMimeType(), XmlPrettier.INSTANCE,
            org.apache.http.entity.ContentType.APPLICATION_JSON.getMimeType(), JsonPrettier.INSTANCE,
            "text/json", JsonPrettier.INSTANCE,
            "custom_type", JsonPrettier.INSTANCE,
            org.apache.http.entity.ContentType.TEXT_HTML.getMimeType(), HtmlPrettier.INSTANCE
    );

    static {
        RestAssured.useRelaxedHTTPSValidation();
        RestAssured.filters(
                new ReportPortalRestAssuredLoggingFilter(
                        42,
                        LogLevel.INFO)
                        .setContentPrettiers(REPORTPORTAL_PRETTIERS)
        );
    }

    public static RequestSpecification getClient(String baseUri) {
        return RestAssured
            .given()
            .baseUri(baseUri);
    }
}
  1. Send a request with a header Content-Type: custom_type and valid json in body.

Expected behavior
According to REPORTPORTAL_PRETTIERS the Content-Type: custom_type should be treated as usual JSON

Actual behavior
Unable to send a request as ReportPortal fails being unable to cast String to byte[]

java.lang.ClassCastException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap')
	at com.epam.reportportal.restassured.support.HttpEntityFactory.createHttpRequestFormatter(HttpEntityFactory.java:144)
	at com.epam.reportportal.restassured.ReportPortalRestAssuredLoggingFilter.filter(ReportPortalRestAssuredLoggingFilter.java:167)

Dependency versions

    java 11
    gradle 7.4
    implementation "com.epam.reportportal:logger-java-rest-assured:5.2.4"
    implementation "com.epam.reportportal:agent-java-cucumber6:5.1.2"

Additional context
Seems like any mimeTypes, if they are not in DEFAULT_PRETTIERS map predefined in code, lead to BodyType detected as BINARY. For BINARY body is parsed as byte[] even being String. I'd vote to detect BodyType as TEXT if a prettier is registered - as parsing logic is defined in Prettier implementation.

requests and responses get reported 8 times - the same message

Describe the bug
the rest assured request/response is getting reported 8 times, which is messy to filter a lot of logs are duplicated

Steps to Reproduce
Steps to reproduce the behavior:

  1. add logger-java-rest-assured to the project
  2. run junit5 test (rest assured) by mvn command (run in parallel)
  3. check reportportal

Expected behavior
it should logs messages just one time as it is called only one time

Actual behavior
messages reported 8 times

Dependency versions

com.epam.reportportal
logger-java-rest-assured
5.3.0


com.epam.reportportal
logger-java-log4j
5.2.0


org.apache.logging.log4j
log4j-api
2.22.1


org.apache.logging.log4j
log4j-core
2.22.1

How to mask specific data in a JSON response

Pretty novice in Java and I'm just trying to figure out how to mask sensitive data in my requests/responses so that they are not visible in ReportPortal.

Example:

{
    "username": "joetester",
    "password": "*****"
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.