View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.rest.client;
18  
19  import static org.apache.juneau.TestUtils.*;
20  
21  import java.io.*;
22  import java.util.logging.*;
23  
24  import org.apache.http.entity.*;
25  import org.apache.juneau.*;
26  import org.apache.juneau.http.annotation.*;
27  import org.apache.juneau.rest.annotation.*;
28  import org.apache.juneau.rest.mock.*;
29  import org.apache.juneau.rest.servlet.*;
30  import org.junit.jupiter.api.*;
31  
32  class RestClient_Logging_Test extends TestBase {
33  
34  	public static class ABean {
35  		public int f;
36  		static ABean get() {
37  			var x = new ABean();
38  			x.f = 1;
39  			return x;
40  		}
41  	}
42  
43  	private static ABean bean = ABean.get();
44  
45  	@Rest
46  	public static class A extends BasicRestObject {
47  		@RestPost
48  		public ABean bean(@Content ABean b) {
49  			return b;
50  		}
51  		@RestPost
52  		public InputStream stream(@Content InputStream b, org.apache.juneau.rest.RestResponse res) {
53  			res.setHeader("Content-Encoding", "identity");
54  			return b;
55  		}
56  		@RestGet
57  		public ABean bean() {
58  			return bean;
59  		}
60  	}
61  
62  	@Test void a01_logToConsole() throws Exception {
63  		var c = MockConsole.create();
64  		var l = MockLogger.create();
65  
66  		client().logRequests(DetailLevel.NONE,Level.SEVERE,null).logToConsole().logger(l).console(c).build().post("/bean",bean).complete();
67  		c.assertContents().is("");
68  		c.reset();
69  
70  		client().logRequests(DetailLevel.SIMPLE,Level.SEVERE,null).logToConsole().logger(l).console(c).build().post("/bean",bean).complete();
71  		c.assertContents().isContains("HTTP POST http://localhost/bean, HTTP/1.1 200");
72  		c.reset();
73  
74  		client().logRequests(DetailLevel.FULL,Level.SEVERE,null).logToConsole().logger(l).console(c).build().post("/bean",bean).complete();
75  		c.assertContents().asTrimmed().isLines(
76  			"=== HTTP Call (outgoing) ======================================================",
77  			"=== REQUEST ===",
78  			"POST http://localhost/bean",
79  			"---request headers---",
80  			"	Accept: application/json5",
81  			"---request entity---",
82  			"	Content-Type: application/json5",
83  			"---request content---",
84  			"{f:1}",
85  			"=== RESPONSE ===",
86  			"HTTP/1.1 200 ",
87  			"---response headers---",
88  			"	Content-Type: application/json5",
89  			"---response content---",
90  			"{f:1}",
91  			"=== END ======================================================================="
92  		);
93  		c.reset();
94  
95  		client().logRequests(DetailLevel.FULL,Level.SEVERE,null).logToConsole().logger(l).console(c).build().get("/bean").complete();
96  		c.assertContents().asTrimmed().isLines(
97  			"=== HTTP Call (outgoing) ======================================================",
98  			"=== REQUEST ===",
99  			"GET http://localhost/bean",
100 			"---request headers---",
101 			"	Accept: application/json5",
102 			"=== RESPONSE ===",
103 			"HTTP/1.1 200 ",
104 			"---response headers---",
105 			"	Content-Type: application/json5",
106 			"---response content---",
107 			"{f:1}",
108 			"=== END ======================================================================="
109 		);
110 		c.reset();
111 
112 		clientPlain().logRequests(DetailLevel.FULL,Level.SEVERE,null).logToConsole().logger(l).console(c).build().post("/stream",new InputStreamEntity(inputStream("foo"))).complete();
113 		c.assertContents().asTrimmed().isLines(
114 			"=== HTTP Call (outgoing) ======================================================",
115 			"=== REQUEST ===",
116 			"POST http://localhost/stream",
117 			"---request headers---",
118 			"---request entity---",
119 			"=== RESPONSE ===",
120 			"HTTP/1.1 200 ",
121 			"---response headers---",
122 			"	Content-Encoding: identity",
123 			"---response content---",
124 			"foo",
125 			"=== END ======================================================================="
126 		);
127 		c.reset();
128 
129 		clientPlain().logRequests(DetailLevel.FULL,Level.SEVERE,(req,res)->false).logToConsole().logger(l).console(c).build().post("/stream",new InputStreamEntity(inputStream("foo"))).complete();
130 		c.assertContents().isEmpty();
131 		c.reset();
132 	}
133 
134 	@Test void a02_logTo() throws Exception {
135 		var l = MockLogger.create();
136 
137 		client().logRequests(DetailLevel.NONE,Level.SEVERE,null).logToConsole().logger(l).build().post("/bean",bean).complete();
138 		l.assertContents().is("");
139 		l.assertRecordCount().is(0);
140 		l.reset();
141 
142 		client().logger(l).logRequests(DetailLevel.SIMPLE,Level.WARNING,null).build().post("/bean",bean).complete();
143 		l.assertLastLevel(Level.WARNING);
144 		l.assertLastMessage().is("HTTP POST http://localhost/bean, HTTP/1.1 200 ");
145 		l.assertContents().isContains("WARNING: HTTP POST http://localhost/bean, HTTP/1.1 200");
146 		l.reset();
147 
148 		client().logger(l).logRequests(DetailLevel.FULL,Level.WARNING,null).build().post("/bean",bean).complete();
149 		l.assertLastLevel(Level.WARNING);
150 		l.assertLastMessage().asTrimmed().isLines(
151 			"=== HTTP Call (outgoing) ======================================================",
152 			"=== REQUEST ===",
153 			"POST http://localhost/bean",
154 			"---request headers---",
155 			"	Accept: application/json5",
156 			"---request entity---",
157 			"	Content-Type: application/json5",
158 			"---request content---",
159 			"{f:1}",
160 			"=== RESPONSE ===",
161 			"HTTP/1.1 200 ",
162 			"---response headers---",
163 			"	Content-Type: application/json5",
164 			"---response content---",
165 			"{f:1}",
166 			"=== END ======================================================================="
167 		);
168 		l.assertContents().asTrimmed().asJavaStrings().isContains(
169 			"WARNING: ",
170 			"=== HTTP Call (outgoing) ======================================================",
171 			"=== REQUEST ===",
172 			"POST http://localhost/bean",
173 			"---request headers---",
174 			"	Accept: application/json5",
175 			"---request entity---",
176 			"	Content-Type: application/json5",
177 			"---request content---",
178 			"{f:1}",
179 			"=== RESPONSE ===",
180 			"HTTP/1.1 200 ",
181 			"---response headers---",
182 			"	Content-Type: application/json5",
183 			"---response content---",
184 			"{f:1}",
185 			"=== END ======================================================================="
186 		);
187 	}
188 
189 	public static class A1 extends BasicRestCallInterceptor {
190 		@Override /* RestCallInterceptor */
191 		public void onConnect(RestRequest req, RestResponse res) throws Exception {
192 			super.onConnect(req,res);
193 			req.log(Level.WARNING,"Foo");
194 			req.log(Level.WARNING,new RuntimeException(),"Bar");
195 			res.log(Level.WARNING,"Baz");
196 			res.log(Level.WARNING,new RuntimeException(),"Qux");
197 			req.log(Level.WARNING,(Throwable)null,"Quux");
198 		}
199 	}
200 
201 	@Test void a04_other() throws Exception {
202 		var ml = MockLogger.create();
203 		var mc = MockConsole.create();
204 		client().logger(ml).interceptors(A1.class).build().post("/bean",bean).complete();
205 		ml.assertRecordCount().is(5);
206 		ml.reset();
207 		client().logger(ml).logToConsole().console(mc).interceptors(A1.class).build().post("/bean",bean).complete();
208 		ml.assertRecordCount().is(5);
209 		ml.assertContents().isContains(
210 			"WARNING: Foo",
211 			"WARNING: Bar",
212 			"WARNING: Baz",
213 			"WARNING: Qux",
214 			"WARNING: Quux",
215 			"at org.apache.juneau"
216 		);
217 	}
218 
219 	//------------------------------------------------------------------------------------------------------------------
220 	// Helper methods.
221 	//------------------------------------------------------------------------------------------------------------------
222 
223 	private static RestClient.Builder client() {
224 		return MockRestClient.create(A.class).json5();
225 	}
226 
227 	private static RestClient.Builder clientPlain() {
228 		return MockRestClient.create(A.class);
229 	}
230 }