-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement a request id to trace requests #586
- Loading branch information
1 parent
7063b71
commit 5f6f892
Showing
11 changed files
with
154 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
--- | ||
title: Request Id | ||
description: Request Id | ||
--- | ||
|
||
LAPIS uses a request id to identify requests. | ||
This is useful for debugging and logging purposes. | ||
|
||
:::note | ||
If you report an error that occurred in LAPIS, please include the request id. | ||
This will greatly simplify identifying the problem in our log files. | ||
::: | ||
|
||
You can provide a request id in the request as an HTTP header `X-Request-Id`. | ||
This is useful if you want to correlate requests in your own log files with the LAPIS log files | ||
to track problems across systems. | ||
|
||
:::caution | ||
If you use the `X-Request-Id` header, make sure that the value is unique. | ||
::: | ||
|
||
If you don't specify a request id, LAPIS will generate one for you. | ||
It is contained in the response header `X-Request-Id` and in `info` in the response body. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
lapis2/src/main/kotlin/org/genspectrum/lapis/logging/RequestId.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package org.genspectrum.lapis.logging | ||
|
||
import jakarta.servlet.FilterChain | ||
import jakarta.servlet.http.HttpServletRequest | ||
import jakarta.servlet.http.HttpServletResponse | ||
import org.genspectrum.lapis.openApi.REQUEST_ID_HEADER | ||
import org.slf4j.MDC | ||
import org.springframework.core.annotation.Order | ||
import org.springframework.stereotype.Component | ||
import org.springframework.web.context.annotation.RequestScope | ||
import org.springframework.web.filter.OncePerRequestFilter | ||
import java.util.UUID | ||
|
||
@Component | ||
@RequestScope | ||
class RequestIdContext { | ||
var requestId: String? = null | ||
} | ||
|
||
private const val REQUEST_ID_MDC_KEY = "RequestId" | ||
private const val HIGH_PRECEDENCE_BUT_LOW_ENOUGH_TO_HAVE_REQUEST_SCOPE_AVAILABLE = -100 | ||
|
||
@Component | ||
@Order(HIGH_PRECEDENCE_BUT_LOW_ENOUGH_TO_HAVE_REQUEST_SCOPE_AVAILABLE) | ||
class RequestIdFilter(private val requestIdContext: RequestIdContext) : OncePerRequestFilter() { | ||
override fun doFilterInternal( | ||
request: HttpServletRequest, | ||
response: HttpServletResponse, | ||
filterChain: FilterChain, | ||
) { | ||
val requestId = request.getHeader(REQUEST_ID_HEADER) ?: UUID.randomUUID().toString() | ||
|
||
MDC.put(REQUEST_ID_MDC_KEY, requestId) | ||
requestIdContext.requestId = requestId | ||
response.addHeader(REQUEST_ID_HEADER, requestId) | ||
|
||
try { | ||
filterChain.doFilter(request, response) | ||
} finally { | ||
MDC.remove(REQUEST_ID_MDC_KEY) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { expect } from 'chai'; | ||
import { lapisClient } from './common'; | ||
|
||
describe('The request id', () => { | ||
it('should be returned when explicitly specified', async () => { | ||
const requestID = 'hardcodedRequestIdInTheTest'; | ||
|
||
const result = await lapisClient.postAggregated1({ | ||
aggregatedPostRequest: {}, | ||
xRequestID: requestID, | ||
}); | ||
|
||
expect(result.info.requestId).equals(requestID); | ||
}); | ||
|
||
it('should be generated when none is specified', async () => { | ||
const result = await lapisClient.postAggregated1({ | ||
aggregatedPostRequest: {}, | ||
}); | ||
|
||
expect(result.info.requestId).length.is.at.least(1); | ||
}); | ||
}); |