Ich arbeite an Rest API mit Spring Boot. Ich muss alle Anforderungen mit Eingabeparametern (mit Methoden, z. B. GET, POST usw.), Anforderungspfad, Abfragezeichenfolge, entsprechender Klassenmethode dieser Anforderung sowie Antwort auf diese Aktion, sowohl Erfolg als auch Fehler, protokollieren.
Zum Beispiel:
erfolgreiche Anfrage:
http://example.com/api/users/1
Das Protokoll sollte ungefähr so aussehen:
{
HttpStatus: 200,
path: "api/users/1",
method: "GET",
clientIp: "0.0.0.0",
accessToken: "XHGu6as5dajshdgau6i6asdjhgjhg",
method: "UsersController.getUser",
arguments: {
id: 1
},
response: {
user: {
id: 1,
username: "user123",
email: "[email protected]"
}
},
exceptions: []
}
Oder Anfrage mit Fehler:
http://example.com/api/users/9999
Das Protokoll sollte ungefähr so aussehen:
{
HttpStatus: 404,
errorCode: 101,
path: "api/users/9999",
method: "GET",
clientIp: "0.0.0.0",
accessToken: "XHGu6as5dajshdgau6i6asdjhgjhg",
method: "UsersController.getUser",
arguments: {
id: 9999
},
returns: {
},
exceptions: [
{
exception: "UserNotFoundException",
message: "User with id 9999 not found",
exceptionId: "adhaskldjaso98d7324kjh989",
stacktrace: ...................
]
}
Ich möchte, dass Request / Response eine einzelne Entität mit benutzerdefinierten Informationen zu dieser Entität ist, sowohl in erfolgreichen als auch in Fehlerfällen.
Was ist die beste Vorgehensweise im Frühjahr, um dies zu erreichen, möglicherweise mit Filtern? Wenn ja, können Sie ein konkretes Beispiel geben?
(Ich habe mit @ControllerAdvice und @ExceptionHandler gespielt, aber wie bereits erwähnt, muss ich alle Erfolgs- und Fehleranforderungen an einem einzigen Ort (und in einem einzigen Protokoll) bearbeiten.)
quelle
HandlerInterceptor
aber das ist nicht gut funktionieren kann mit der Anmeldung der Antwort , wie in der Antwort erwähnt: concretepage.com/spring/spring-mvc/... - HandlerInterceptor hat Zugang auf die Methode (Methode: "UsersController.getUser"). Das ist bei einem Servlet-Filter nicht bekannt.LogClass{ getRequestAndSaveIt()} Gson.toJson(LogClass)
als PseudocodeAntworten:
Schreiben Sie keine Interceptors, Filter, Komponenten, Aspekte usw., dies ist ein sehr häufiges Problem und wurde mehrfach gelöst.
Spring Boot verfügt über ein Modul namens Actuator , das die sofortige Protokollierung von HTTP-Anforderungen ermöglicht. Es gibt einen Endpunkt, der
/trace
(SB1.x) oder/actuator/httptrace
(SB2.0 +) zugeordnet ist und der Ihnen die letzten 100 HTTP-Anforderungen anzeigt. Sie können es anpassen, um jede Anforderung zu protokollieren oder in eine Datenbank zu schreiben.Um die gewünschten Endpunkte zu erhalten, benötigen Sie die Spring-Boot-Starter-Actuator-Abhängigkeit sowie die "Whitelist" der gesuchten Endpunkte und möglicherweise das Einrichten oder Deaktivieren der Sicherheit dafür.
Wo wird diese Anwendung ausgeführt? Verwenden Sie ein PaaS? Hosting-Anbieter, beispielsweise Heroku, bieten die Anforderungsprotokollierung als Teil ihres Dienstes an, und Sie müssen dann überhaupt keine Codierung vornehmen.
quelle
Spring bietet bereits einen Filter, der diese Aufgabe übernimmt. Fügen Sie Ihrer Konfiguration die folgende Bean hinzu
Vergessen Sie nicht, die Protokollstufe von
org.springframework.web.filter.CommonsRequestLoggingFilter
auf zu ändernDEBUG
.quelle
Sie können verwenden,
javax.servlet.Filter
wenn die ausgeführte Java-Methode nicht protokolliert werden muss.Aber mit dieser Anforderung haben Sie den Zugriff auf gespeicherte Informationen in
handlerMapping
derDispatcherServlet
. Sie können jedoch überschreibenDispatcherServlet
, um die Protokollierung des Anforderungs- / Antwortpaars durchzuführen.Im Folgenden finden Sie ein Beispiel für eine Idee, die weiter verbessert und an Ihre Bedürfnisse angepasst werden kann.
HandlerExecutionChain
- enthält die Informationen zum Request Handler.Sie können diesen Dispatcher dann wie folgt registrieren:
Und hier ist das Beispiel von Protokollen:
AKTUALISIEREN
Im Fehlerfall führt Spring eine automatische Fehlerbehandlung durch. Daher
BasicErrorController#error
wird als Anforderungshandler angezeigt. Wenn Sie den ursprünglichen Anforderungshandler beibehalten möchten, können Sie dieses Verhalten überschreiben,spring-webmvc-4.2.5.RELEASE-sources.jar!/org/springframework/web/servlet/DispatcherServlet.java:971
bevor#processDispatchResult
es aufgerufen wird, um den ursprünglichen Handler zwischenzuspeichern.quelle
Die Logbuchbibliothek wurde speziell zum Protokollieren von HTTP-Anforderungen und -Antworten erstellt. Es unterstützt Spring Boot mithilfe einer speziellen Starterbibliothek.
Um die Anmeldung bei Spring Boot zu aktivieren, müssen Sie lediglich die Bibliothek zu den Abhängigkeiten Ihres Projekts hinzufügen. Angenommen, Sie verwenden Maven:
Standardmäßig sieht die Protokollausgabe folgendermaßen aus:
Es wird jedoch nicht der Klassenname ausgegeben, der die Anforderung verarbeitet. Die Bibliothek verfügt über einige Schnittstellen zum Schreiben von benutzerdefinierten Loggern.
quelle
logging.level.org.zalando.logbook=TRACE
Ihremapplication.properties
(wie in derReadme
)Ich hatte die Anmeldeebene
application.properties
für das Drucken von Anforderungen / Antworten und die Methoden-URL in der Protokolldatei definiertIch hatte Spring Boot benutzt.
quelle
Hier ist, wie ich es im Frühjahr mache Daten ruhen mit
org.springframework.web.util.ContentCachingRequestWrapper
undorg.springframework.web.util.ContentCachingResponseWrapper
quelle
Wenn es Ihnen nichts ausmacht, Spring AOP auszuprobieren, habe ich dies zu Protokollierungszwecken untersucht und es funktioniert ziemlich gut für mich. Nicht definierte Anforderungen und fehlgeschlagene Anforderungsversuche werden jedoch nicht protokolliert.
Fügen Sie diese drei Abhängigkeiten hinzu
Fügen Sie dies Ihrer XML-Konfigurationsdatei hinzu
<aop:aspectj-autoproxy/>
Erstellen Sie eine Anmerkung, die als Pointcut verwendet werden kann
Kommentieren Sie nun alle Ihre Rest-API-Methoden, die Sie protokollieren möchten
Nun zum Aspekt. Komponenten-Scan des Pakets, in dem sich diese Klasse befindet.
Wenn Sie im Detail lesen möchten, lesen Sie dies durch. http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html
quelle
Nach dem Hinzufügen von Aktoren zur Spring Boot Bassed-Anwendung steht Ihnen ein
/trace
Endpunkt mit den neuesten Anforderungsinformationen zur Verfügung. Dieser Endpunkt basiert auf TraceRepository und die Standardimplementierung ist InMemoryTraceRepository , das die letzten 100 Aufrufe speichert. Sie können dies ändern, indem Sie diese Schnittstelle selbst implementieren und als Spring Bean verfügbar machen. Zum Beispiel, um alle zu protokollierenden Anforderungen zu protokollieren (und weiterhin die Standardimplementierung als Basisspeicher zum Bereitstellen von Informationen auf dem/trace
Endpunkt zu verwenden), verwende ich diese Art der Implementierung:Diese
traceInfo
Karte enthält grundlegende Informationen zu Anfrage und Antwort in folgender Form :{method=GET, path=/api/hello/John, headers={request={host=localhost:8080, user-agent=curl/7.51.0, accept=*/*}, response={X-Application-Context=application, Content-Type=text/plain;charset=UTF-8, Content-Length=10, Date=Wed, 29 Mar 2017 20:41:21 GMT, status=200}}}
. Hier gibt es KEINEN Antwortinhalt.BEARBEITEN! POST-Daten protokollieren
Sie können auf POST-Daten zugreifen , indem Sie WebRequestTraceFilter überschreiben. Dies ist jedoch keine gute Idee (z. B. werden alle hochgeladenen Dateiinhalte in Protokollen gespeichert). Hier ist Beispielcode, aber verwenden Sie ihn nicht :
quelle
TraceRepository
ist. Wie können wir darauf zugreifen?protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
aber ich bin nicht sicher, wann dieser Filter ausgeführt wird - möglicherweise in der Anforderungsphase, sodass der Antworttext dort nicht bereit ist.Dieser Code funktioniert für mich in einer Spring Boot-Anwendung - registrieren Sie ihn einfach als Filter
quelle
Hier meine Lösung (Spring 2.0.x)
Fügen Sie die Maven-Abhängigkeit hinzu:
Bearbeiten Sie die application.properties und fügen Sie die folgende Zeile hinzu:
Sobald Ihre Spring Boot-Anwendung gestartet ist, können Sie die letzten 100 http-Anforderungen verfolgen, indem Sie diese URL aufrufen: http: // localhost: 8070 / actuator / httptrace
quelle
Derzeit verfügt Spring Boot über die Actuator-Funktion, um die Protokolle von Anforderungen und Antworten abzurufen.
Sie können die Protokolle aber auch mit Aspect (AOP) abrufen.
Aspect bietet Ihnen mit Anmerkungen wie:
@Before
,@AfterReturning
,@AfterThrowing
usw.@Before
Protokolliert die Anforderung,@AfterReturning
protokolliert die Antwort und@AfterThrowing
protokolliert die Fehlermeldung. Möglicherweise benötigen Sie nicht das Protokoll aller Endpunkte, sodass Sie einige Filter auf die Pakete anwenden können.Hier einige Beispiele :
Für Anfrage:
Hier
@Before("within(your.package.where.endpoints.are..*)")
hat der Paketpfad. Alle Endpunkte in diesem Paket generieren das Protokoll.Zur Antwort:
Hier
@AfterReturning("within(your.package.where.endpoints.are..*)")
hat der Paketpfad. Alle Endpunkte in diesem Paket generieren das Protokoll. AuchObject returnValue
enthält die Antwort.Ausnahme:
Hier
@AfterThrowing(pointcut = ("within(your.package.where.endpoints.are..*)"), throwing = "e")
hat der Paketpfad. Alle Endpunkte in diesem Paket generieren das Protokoll. AuchException e
enthält die Fehlerreaktion.Hier ist der vollständige Code:
Hier können
@ConditionalOnExpression("${endpoint.aspect.enabled:true}")
Sie das Protokoll aktivieren / deaktivieren. fügen Sie einfachendpoint.aspect.enabled:true
in dieapplication.property
und das Protokoll steuernWeitere Infos zum AOP-Besuch hier:
Spring Docks über AOP
Beispielartikel über AOP
quelle
new ObjectMapper()
ist teuer, teilen Sie besser einen Mapper für alleSie können auch einen benutzerdefinierten Spring-Interceptor
HandlerInterceptorAdapter
für eine vereinfachte Implementierung von Pre-Only- / Post-Only-Interceptors konfigurieren :Dann registrieren Sie so viele Abfangjäger, wie Sie möchten:
Hinweis: Wie von @Robert angegeben , müssen Sie auf die spezifischen Implementierungen von und Ihre Anwendung achten .
HttpServletRequest
HttpServletResponse
Für Apps, die das verwenden
ShallowEtagHeaderFilter
, lautet die Antwortimplementierung beispielsweise aContentCachingResponseWrapper
, sodass Sie Folgendes haben:quelle
@ hahns Antwort erforderte ein wenig Modifikation, damit es für mich funktioniert, aber es ist bei weitem das anpassbarste, was ich bekommen konnte.
Es hat bei mir nicht funktioniert, wahrscheinlich weil ich auch einen HandlerInterceptorAdapter [??] habe, aber in dieser Version erhielt ich immer wieder eine schlechte Antwort vom Server. Hier ist meine Modifikation davon.
quelle
Wenn jemand es hier noch braucht, ist eine einfache Implementierung mit Spring HttpTrace Actuator. Aber wie sie oben gesagt haben, protokolliert es keine Körper.
quelle
Die aktuelle Antwort finden Sie unter dem folgenden Link: https://gist.github.com/int128/e47217bebdb4c402b2ffa7cc199307ba
Bei einigen Änderungen gegenüber der oben genannten Lösung werden Anforderung und Antwort in der Konsole und auch in der Datei protokolliert, wenn die Protokollierungsstufe info ist. Wir können entweder in der Konsole oder in der Datei drucken.
Ausgabe in Datei:
quelle
Wenn Sie nur einen Teil Ihrer Anforderungsnutzlast sehen, müssen Sie die
setMaxPayloadLength
Funktion aufrufen , da standardmäßig nur 50 Zeichen in Ihrem Anforderungshauptteil angezeigt werden. Die EinstellungsetIncludeHeaders
auf false ist auch eine gute Idee, wenn Sie Ihre Auth-Header nicht protokollieren möchten!quelle
Wenn Sie Tomcat in Ihrer Boot-App verwenden, befindet sich hier
org.apache.catalina.filters.RequestDumperFilter
ein Klassenpfad für Sie. (aber es wird Ihnen nicht "Ausnahmen an einem Ort" geben).quelle
Der unten eingefügte Code funktioniert mit meinen Tests und kann von meinem [Github-Projekt] [1] heruntergeladen werden, nachdem eine auf diesem Produktionsprojekt basierende Lösung angewendet wurde.
quelle
Um alle Anforderungen mit Eingabeparametern und Body zu protokollieren, können wir Filter und Interceptors verwenden . Bei Verwendung eines Filters oder Interceptors können wir den Anforderungshauptteil jedoch nicht mehrmals drucken. Der bessere Weg ist, dass wir Spring-AOP verwenden können. Auf diese Weise können wir den Protokollierungsmechanismus von der Anwendung entkoppeln. AOP kann für die Protokollierung verwendet werden Eingang und Ausgang von jeder Methode in der Anwendung.
Meine Lösung ist:
}}
quelle
Wenn Sie den Spring Boot Config-Server konfiguriert haben, aktivieren Sie einfach den Debug-Logger für die Klasse:
Http11InputBuffer.Http11InputBuffer.java
Debugs protokollieren alle Anforderungen und Antworten für jede Anforderung
quelle
So protokollieren Sie Anforderungen, die nur zu 400 führen:
quelle