Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Loggning av trafik, såväl för inkommande och utgående requests och responses sker med hjälp av biblioteket Logbook.

Inställningar
(Auto-konfigurationsklass: se.sundsvall.dept44.configuration.LogbookConfiguration)

Inställningar

(Auto-konfiguration: se.sundsvall.dept44.configuration.openapi.OpenApiConfiguration)

Inställning

Default-värde

Beskrivning

openapi.enabled

true

Anger om OpenAPI-specifikation ska genereras och Swagger UI konfigureras

openapi.name (obligatorisk så länge openapi.enabled inte är false)

-

Namn som används för att generera URL till API-dokumentation. Får bara innehålla bokstäver, siffror, underscore och bindestreck

openapi.title (obligatorisk så länge openapi.enabled inte är false)

-

Titel som ska användas i OpenAPI-specifikationen

openapi.version

Inställning

Default-värde

Beskrivning

logbook.logger.name

se.sundsvall.dept44.payload

Anger den logg-kategori som trafikloggningen ska göras i

logbook.excluded.paths

/,/webjars/**,/api-docs**,/swagger-resources,/swagger-resources/**,/error,/csrf,/swagger-ui.html,/swagger-ui/**,/favicon.ico,/actuator,/actuator/**

Anger de sökvägar som ska exkluderas från trafikloggning

Viktigt att komma ihåg om man sätter om logg-kategorin är att man då även sätter om loggnivån på den konfigurerade loggkategorin till TRACE - om det inte görs kommer ingen trafikloggning att dyka upp i applikationens logg.

...

  • null-värden exkluderas vid serialisering

  • den JSON-data som genereras är indenterad, för ökad läsbarhet

  • okända attribut ignoreras vid deserialisering

Vidare används Jackson för serialisering av objekt till YAML och tillbaka.

Inställningar
(Auto-konfigurationsklass: se.sundsvall.dept44.configuration.ObjectMapperConfiguration)

...

För att generera OpenAPI v3.x-specifikation och tillhandahålla ett Swagger UI används SpringDoc.

Minimal konfiguration i application.properties:

Code Block
openapi.name=ett-api
openapi.title=Ett API
openapi.version=1.0

...

logbook.exclusionfilters.json-path

Anger de json-attribut (via JsonPath) som skall exkluderas från trafikloggning och vad som ska loggas istället. Till exempel {'$.attachments[*].base64Data' : '[base64]'} ersätter en base64-sträng med [base64] istället. Användbart när t.ex. stora filer/bilagor i base64 förekommer i anrop med json-struktur.

logbook.exclusionfilters.x-path

Anger de xml-attribut (via xPath) som ska exkluderas från trafikloggning. Användbart när t.ex. stora filer/bilagor i base64 förekommer i anrop med xml-struktur.

Viktigt att komma ihåg om man sätter om logg-kategorin är att man då även sätter om loggnivån på den konfigurerade loggkategorin till TRACE - om det inte görs kommer ingen trafikloggning att dyka upp i applikationens logg.

Anchor
jackson
jackson
Jackson (serialisering/deserialisering av JSON och YAML)


Jackson används för serialisering av objekt till JSON och tillbaka - d.v.s. deserialisering av JSON till objekt. Konfigurationen som görs i ramverket innefattar bland annat:

  • null-värden exkluderas vid serialisering

  • den JSON-data som genereras är indenterad, för ökad läsbarhet

  • okända attribut ignoreras vid deserialisering

Vidare används Jackson för serialisering av objekt till YAML och tillbaka.

Inställningar
(Auto-konfigurationsklass: se.sundsvall.dept44.configuration.ObjectMapperConfiguration)

Anchor
openapi
openapi
OpenAPI och Swagger UI

För att generera OpenAPI v3.x-specifikation och tillhandahålla ett Swagger UI används SpringDoc.

Minimal konfiguration i application.properties:

Code Block
openapi.name=ett-api
openapi.title=Ett API
openapi.version=1.0

OpenAPI-specifikationen exponeras på /api-docs. Som standard serveras OpenAPI-specifikationen som JSON, med kan även fås som YAML genom att sätta Accept-headern till application/yaml. YAML-representation av OpenAPI-specifikationen kan även nås via /api-docs.yaml.

Vidare läggs en endpoint /api-docs till i tjänstens Swagger UI som kommer att vara åtkomlig utan autentisering, där man kan hämta OpenAPI-specifikationen.

Se nedan för övriga valbara inställningar.

Inställningar

(Auto-konfiguration: se.sundsvall.dept44.configuration.openapi.OpenApiConfiguration)

Inställning

Default-värde

Beskrivning

openapi.enabled

true

Anger om OpenAPI-specifikation ska genereras och Swagger UI konfigureras

openapi.name (obligatorisk så länge openapi.enabled inte är false)

-Versionsnummer som ska användas

Namn som används för att generera URL till API-dokumentation. Får bara innehålla bokstäver, siffror, underscore och bindestreck

openapi.title (obligatorisk så länge openapi.enabled inte är false)

-

Titel som ska användas i OpenAPI-specifikationen

openapi.license.name

MIT

Namn på den licens som ska ingå version (obligatorisk så länge openapi.enabled inte är false)

-

Versionsnummer som ska användas i OpenAPI-specifikationen

openapi.license.urlname

MIT

Namn på den licens som ska ingå i OpenAPI-specifikationen

openapi.license.url

https://opensource.org/licenses/MIT

Länk till den licens som ska ingå i OpenAPI-specifikationen

openapi.contact.name

-

Namnet på den kontakt som ska ingå i OpenAPI-specifikationen

openapi.contact.email

-

E-postadressen till den kontakt som ska ingå i OpenAPI-specifikationen

openapi.contact.url

-

URL för den kontakt som ska ingå i OpenAPI-specifikationen

openapi.security-scheme.oauth2.flow.tokenUrl

-

TODO

openapi.servers[n].url

-

TODO

openapi.servers[n].description

-

TODO

openapi.extensions.<extension>.... (Map)

-

Eventuella tillägg till OpenAPI-specifikationen

(se https://swagger.io/docs/specification/openapi-extensions/)

...

Dept44 erbjuder en möjlighet att addera “circuit-breakers” och “health-indicators” på en resurs (t.ex. en integrationsklient). Dept44 använder sig av Resilience4j för detta syfte. Detta ramverk möjliggör mycket mer funktionalitet än vad som beskrivs här. T.ex. RateLimiter, TimeLimiter, Retry, osv. För ytterligare info hänvisas till dokumentationen av Resilience4j. I detta avsnitt beskrivs enbart funktionalitet kopplad till s.k. “circuit-breakers” och “health-indicators”.

...

Komma igång

Börja med att annotera din resurs.
Resursen brukar vanligtvis var t.ex. utgöras av en integrationsklient, databas-klient, etc.:, databasklient, osv. Men det kan i princip vara vilken metod eller klass som helst som man vill övervaka med en “circuit-breaker” samt tillhörande “health-indicator”.

Code Block
@FeignClient(name = "MyFeignClient", url = "${integration.backend.url}", configuration = MyFeignClientConfiguration.class)
@CircuitBreaker(name = "MyFeignClient")
public interface MyFeignClient {
...
}

[2] Skapar en “Circuit breaker” samt “Health indicator” med namnet “MyFeignClient”. Annoteringen kan placeras på både klass- och metodnivå. I detta exempel har den placerats på klassnivå och slår därför på alla metoder i klassen/interfacet.


Ovanstående är allt som krävs för att att skapa en “Circuit breaker” som bryter kretsen om resursen kastar en exception. Kretsen kommer vid dessa tillfällen att hållas öppen under en kort tidsperiod (default 60 sekunder), innan den övergår till ett “halvöppet läge”“halvöppet” läge. I det “halv-öppna” “halvöppna” läget tillåts ett konfigurerbart antal anrop (konfigurerbart) för att utvärdera resursens status. Under tiden som kretsen hålls öppen kommer den automatiskt registrerade health-indicatorn att visa “DOWN” för denna aktuell resurs. När resursen åter fungerar bra kommer kretsen att stängas helt och “health-indicatorn” visar “UP”.

...

Code Block
languagetext
resilience4j.circuitbreaker.instances.MyFeignClient.ignoreExceptions=se.sundsvall.dept44.exception.ClientProblem                   [default: ej satt]
resilience4j.circuitbreaker.instances.MyFeignClient.failureRateThreshold=60                                                        [default: 50]
resilience4j.circuitbreaker.instances.MyFeignClient.waitDurationInOpenState=200s                                                   [default: 60s]
resilience4j.circuitbreaker.instances.MyFeignClient.allowHealthIndicatorToFail=false                                               [default: true]
resilience4j.circuitbreaker.instances.MyFeignClient.slidingWindowSize=20                                                           [default: 10]
resilience4j.circuitbreaker.instances.MyFeignClient.permittedNumberOfCallsInHalfOpenState=10                                       [default: 5]

# Create common settings to be used in multiple clients.
resilience4j.circuitbreaker.configs.mySharedConfig.baseConfig=default
resilience4j.circuitbreaker.configs.mySharedConfig.slidingWindowSize=50
resilience4j.circuitbreaker.
# Assign these common settings to my client.
resilience4j.circuitbreaker.instances.MyOtherFeignClient.baseConfig=mySharedConfig

[1] Låter resursen “MyFeignClient” ignorera en lista av Exceptions. Kastas dessa fel markeras anropet som “successful”. Det torde t.ex. vara önskvärt att låta fel i HTTP-400 serien ignoreras (dessa betyder ju inte att integrationen har problem).
[2] Tröskelvärde för antal fel (inom slidingWindowSize) som skall öppna kretsen och markera “health-indicator” som “DOWN”. Anges i procent.
[3] Den tid som kretsen hålls öppen innan den övergår till ett “halv-öppet” läge.
[4] Låter applicationens “health” återspeglas av enskilda “health-indicator:s”. M.a.o. om en “health-indicator” är “DOWN” så blir applicationens health också “DOWN”, om denna property är satt till “true”.
[5] Storleken på den buffer som används för att spara och utvärdera resultatet på anropen när kretsen är sluten.
[6] Antal tillåtna anrop som tillåts när kretsen är “halv-öppen”.
[89] Skapar en egen konfigurationsprofil (mySharedConfig) som “ärver” från default (definierad i dept44).
[910] Skriver över default-värden för en property i mySharedConfig
[1012] Sätter aktuella värden i konfigurationsprofilen till en resurs (myOtherSharedConfig). Denna mekanism (d.v.s. rad: 8, 9, 10, 12) är bra smidig om man t.ex. har flera “circuit-breakers” som måste tilldelas andra värden än default , för att och man vill slippa upprepningar.

Ingorerade exceptionsUndantagna undantag

Det är viktigt att ha i åtanke att en “circuit-breaker” reagaerar reagerar på alla typer av undantag (exceptions) som inte är exkluderade via propertyn ignoreExceptions. Av den anledningen är det viktigt att särskilja på exceptions som beror på rena indata-fel (som inte betyder att resursen har problem) och på de exceptions som tyder på att tjänsten har problem.

I den Feign-klient som erbjuds av dept44 har två nya subklasser av “Zalando Problem” införts:
se.sundsvall.dept44.exception.ClientProblem: Kastas när Feign-klienten tar emot ett svar med HTTP-status i 400-serien. Dessa brukar vanligtvis bero på fel orsakade av felaktiga parametrar och betyder vanligtvis inte att tjänsten ligger nere.
se.sundsvall.dept44.exception.ServerProblem: Kastas när Feign-klienten tar emot ett svar med HTTP-status i 500-serien. Dessa brukar vanligtvis bero på att tjänsten har problem.

Använder man nämnda Feign-klient kan det alltså vara bra att ignorera exceptions av typen Ex:

Code Block
resilience4j.circuitbreaker.instances.MyFeignClient.ignoreExceptions = javax.validation.ConstraintViolationException
resilience4j.circuitbreaker.configs.default.ignoreExceptions = javax.validation.ConstraintViolationException

[1] Sätter undantaget på en specifik circuitbreaker. Gör man på detta vis blir av någon anledning cirkuitbreakern oinitierad till dess att exception av annan typ kastats.
[2] Sätter undantaget på ALLA circuitbreakers i tjänsten. Gör man på detta vis initieras de (och blir synliga) i /acutators/health direkt efter första anropet.


I den Feign-klient som erbjuds av dept44 finns två subklasser av “Zalando Problem”:
se.sundsvall.dept44.exception.ClientProblem (se exempel ovan). Gör man inte detta bör man tillse att man har en egen mekanism på plats för att uppnå samma sak. Annars kommer kretsen att bryta för t.ex. enkla “HTTP-400 Bad request”-fel, vilket sannolikt inte är önskvärt.Viktiga endpoints

...

Path

...

Beskrivning

...

Exempel

...

/actuator/health

...

Här visas alla health-indicators och deras aktuella status (hälsovärde).

...

languagejson

...

: Kastas när Feign-klienten tar emot ett svar med HTTP-status i 400-serien. Dessa brukar bero på fel orsakade av ogiltiga parametrar och betyder vanligtvis inte att tjänsten ligger nere.
se.sundsvall.dept44.exception.ServerProblem: Kastas när Feign-klienten tar emot ett svar med HTTP-status i 500-serien. Dessa brukar bero på att tjänsten har problem.


Använder man nämnda Feign-klient kan det alltså vara bra att ignorera exceptions av typen se.sundsvall.dept44.exception.ClientProblem (se exempel ovan). Gör man inte detta bör man tillse att man har en egen mekanism på plats för att uppnå samma sak. Annars kommer kretsen att bryta för t.ex. enkla “HTTP-400 Bad request”-fel, vilket sannolikt inte är önskvärt.

(info) Denna property har inga default-värden, eftersom det är upp till varje tjänst att själv styra vilka exceptions som skall undantas.


Viktiga endpoints

Path

Beskrivning

Exempel

/actuator/health

Här visas alla health-indicators och deras aktuella status (hälsovärde).

Code Block
languagejson
{
  "status" : "DOWN",
  "components" : {
    "circuitBreakers" : {
      "status" : "DOWN",
      "details" : {
        "MyOtherFeignClient" : {
          "status" : "DOWN",
          "details" : {
            "failureRate" : "50.0%",
            "failureRateThreshold" : "50.0%",
            "slowCallRate" : "0.0%",
            "slowCallRateThreshold" : "100.0%",
            "bufferedCalls" : 10,
            "slowCalls" : 0,
            "slowFailedCalls" : 0,
            "failedCalls" : 5,
            "notPermittedCalls" : 11,
            "statusstate" : "UP",OPEN"
          }
      "details" : {},
        "MyFeignClient" : {
          "status" : "UP",
          "details" : {
            "failureRate" : "-1.0%",
            "failureRateThreshold" : "50.0%",
            "slowCallRate" : "-1.0%",
            "slowCallRateThreshold" : "100.0%",
            "bufferedCalls" : 1,
            "slowCalls" : 0,
            "slowFailedCalls" : 0,
            "failedCalls" : 1,
            "notPermittedCalls" : 0,
            "state" : "CLOSED"
          }
        }
      }
    }
  }
}

/actuator/circuitbreakerevents

De senaste [n] resultaten av anrop som övervakas av en CircuitBreaker.

Storleken på event-buffern sätts via attributet “eventConsumerBufferSize”. Default är 100 50 poster per circuit-breaker.

Denna endpoint kan vara bra att använda när man vill se orsaken till att en krets öppnats och en health-indicator rapporterar “DOWN”.

Code Block
languagejson
{
  "circuitBreakerEvents" : [ {
    "circuitBreakerName" : "MyFeignClient",
    "type" : "IGNORED_ERROR",
    "creationTime" : "2022-06-14T10:45:00.967115+02:00[Europe/Stockholm]",
    "errorMessage" : "javax.validation.Exception: test.uuid: not a valid UUID",
    "durationInMs" : 16
  }, {
    "circuitBreakerName" : "MyFeignClient",
    "type" : "IGNORED_ERROR",
    "creationTime" : "2022-06-14T10:46:08.104328300+02:00[Europe/Stockholm]",
    "errorMessage" : "about:blank{502, Bad Gateway, POB error: {detail=, status=401 Unauthorized, title=Authorization has been denied for this request.}}",
    "durationInMs" : 289
  } ] 
}

/actuator/circuitbreakers

Listar alla registrerade circuitbreakers i applikationen.

Code Block
languagejson
{
  "circuitBreakers" : [ "MyFeignClient", "MyOtherFeignClient" ]
}

...