Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add two new flags to enable HTTP Server and clients logs #166

Merged
merged 3 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 108 additions & 8 deletions source/Stargate-API-Skeleton-Tests/StargateApplicationTest.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#superclass : 'LaunchpadTest',
#instVars : [
'port',
'baseUrl'
'baseUrl',
'logger',
'logHTTPRequests'
],
#category : 'Stargate-API-Skeleton-Tests',
#package : 'Stargate-API-Skeleton-Tests'
Expand All @@ -18,6 +20,22 @@
^5 minute
]

{ #category : 'private' }
StargateApplicationTest >> assert: aString isExpectedIncomingSummaryWith: aRequestShortDescription [

self assert: ( aString matchesRegex:
( '\d{4}-\d{2}-\d{2} \d{2}\:\d{2}\:\d{2} ((\d+) (\d+))? Request Handled a\s{0,1}ZnRequest\(<1s>\) (\d+)ms'
expandMacrosWith: aRequestShortDescription ) )
]

{ #category : 'private' }
StargateApplicationTest >> assert: aString isExpectedOutgoingSummaryWith: aRequestShortDescription [

self assert: ( aString matchesRegex:
( '\d{4}-\d{2}-\d{2} \d{2}\:\d{2}\:\d{2} ((\d+) (\d+))? <1s> (\d+) (\d+)B (\d+)ms'
expandMacrosWith: aRequestShortDescription ) )
]

Check warning on line 37 in source/Stargate-API-Skeleton-Tests/StargateApplicationTest.class.st

View check run for this annotation

Codecov / codecov/patch

source/Stargate-API-Skeleton-Tests/StargateApplicationTest.class.st#L32-L37

Added lines #L32 - L37 were not covered by tests
gcotelli marked this conversation as resolved.
Show resolved Hide resolved

{ #category : 'private' }
StargateApplicationTest >> assert: string isLineEndingInsensitiveEqualsTo: anotherString [

Expand Down Expand Up @@ -85,8 +103,11 @@
StargateApplicationTest >> setUp [

super setUp.
logger := MemoryLogger new.
port := self freeListeningTCPPort.
StargateApplication logsDirectory ensureCreateDirectory
StargateApplication logsDirectory ensureCreateDirectory.

logHTTPRequests := false
]

{ #category : 'private' }
Expand All @@ -103,11 +124,14 @@
{ #category : 'private' }
StargateApplicationTest >> startPetStore [

self start: PetStoreApplication withAll: {
'--pet-store.stargate.public-url=http://localhost:<1p>' expandMacrosWith: port.
'--pet-store.stargate.port=<1p>' expandMacrosWith: port.
'--pet-store.stargate.operations-secret=<1s>' expandMacrosWith: self secret }.
baseUrl := runningApplication configuration petStore stargate publicURL
self
start: PetStoreApplication
withAll: { ( '--pet-store.stargate.public-url=http://localhost:<1p>' expandMacrosWith: port ) .
( '--pet-store.stargate.port=<1p>' expandMacrosWith: port ) .
( '--pet-store.stargate.operations-secret=<1s>' expandMacrosWith: self secret ) .
( '--pet-store.stargate.log-http-requests=<1p>' expandMacrosWith:
logHTTPRequests ) }.
baseUrl := runningApplication configuration petStore stargate publicURL
]

{ #category : 'private' }
Expand Down Expand Up @@ -264,6 +288,78 @@
assert: json links size equals: 1
]

{ #category : 'tests - logs' }
StargateApplicationTest >> testLogRequestsDuringSuccessfulGet [

| logRecord |
logger runDuring: [
logHTTPRequests := true.
self testGetPets
].

logRecord := NeoJSONObject fromString: ( String streamContents: [ :stream |
( logger recordings at: logger recordings size - 1 ) printOneLineJsonOn:
stream ] ).

self
assert: logRecord level equals: 'DEBUG';
assert: logRecord message equals: 'Incoming HTTP request responded';
assert: logRecord process equals: 'ZnManagingMultiThreadedServer HTTP worker';
assert: logRecord summary isExpectedIncomingSummaryWith: 'GET \/pets';
assert: logRecord request method equals: 'GET';
assert: logRecord request uri equals: ( 'http://localhost:<1p>/pets' expandMacrosWith: port );
assert: logRecord response code equals: 200;
assert: logRecord response totalSize equals: 59
]

{ #category : 'tests - logs' }
StargateApplicationTest >> testLogRequestsDuringSucessfulPost [

| logRecord |
logger runDuring: [
logHTTPRequests := true.
self testCreatePet
].

logRecord := NeoJSONObject fromString: ( String streamContents: [ :stream |
( logger recordings at: logger recordings size - 1 ) printOneLineJsonOn:
stream ] ).

self
assert: logRecord level equals: 'DEBUG';
assert: logRecord message equals: 'Incoming HTTP request responded';
assert: logRecord process equals: 'ZnManagingMultiThreadedServer HTTP worker';
assert: logRecord summary isExpectedIncomingSummaryWith: 'POST \/pets';
assert: logRecord request method equals: 'POST';
assert: logRecord request uri equals: ( 'http://localhost:<1p>/pets' expandMacrosWith: port );
assert: logRecord response code equals: 201;
assert: logRecord response totalSize equals: 96
]

{ #category : 'tests - logs' }
StargateApplicationTest >> testLogRequestsDuringUnsucessfulPost [

| logRecord |
logger runDuring: [
logHTTPRequests := true.
self testUnsupportedMediaType
].

logRecord := NeoJSONObject fromString: ( String streamContents: [ :stream |
( logger recordings at: logger recordings size - 1 ) printOneLineJsonOn:
stream ] ).

self
assert: logRecord level equals: 'DEBUG';
assert: logRecord message equals: 'Incoming HTTP request responded';
assert: logRecord process equals: 'ZnManagingMultiThreadedServer HTTP worker';
assert: logRecord summary isExpectedIncomingSummaryWith: 'POST \/pets';
assert: logRecord request method equals: 'POST';
assert: logRecord request uri equals: ( 'http://localhost:<1p>/pets' expandMacrosWith: port );
assert: logRecord response code equals: 415;
assert: logRecord response totalSize equals: 72
]

{ #category : 'tests - api' }
StargateApplicationTest >> testMethodNotAllowed [

Expand Down Expand Up @@ -320,14 +416,16 @@
self assert: help isLineEndingInsensitiveEqualsTo: ('NAME
pet-store [<1s>] - A RESTful API for Pet stores
SYNOPSYS
pet-store --pet-store.stargate.public-url=%<publicURL%> --pet-store.stargate.port=%<port%> --pet-store.stargate.operations-secret=%<operationsSecret%> [--pet-store.stargate.concurrent-connections-threshold=%<concurrentConnectionsThreshold%>]
pet-store --pet-store.stargate.public-url=%<publicURL%> --pet-store.stargate.port=%<port%> --pet-store.stargate.operations-secret=%<operationsSecret%> [--pet-store.stargate.log-http-requests=%<logHTTPRequests%>] [--pet-store.stargate.concurrent-connections-threshold=%<concurrentConnectionsThreshold%>]
PARAMETERS
--pet-store.stargate.public-url=%<publicURL%>
Public URL where the API is deployed. Used to create hypermedia links.
--pet-store.stargate.port=%<port%>
Listening port.
--pet-store.stargate.operations-secret=%<operationsSecret%>
Secret key for checking JWT signatures.
--pet-store.stargate.log-http-requests=%<logHTTPRequests%>
Boolean that indicates whether to log all the incoming HTTP requests. Defaults to false.
--pet-store.stargate.concurrent-connections-threshold=%<concurrentConnectionsThreshold%>
Set the maximum number of concurrent connections that I will accept. When this threshold is reached, a 503 Service Unavailable response will be sent and the connection will be closed. Defaults to 32.
ENVIRONMENT
Expand All @@ -337,6 +435,8 @@
Listening port.
PET_STORE__STARGATE__OPERATIONS_SECRET
Secret key for checking JWT signatures.
PET_STORE__STARGATE__LOG_HTTP_REQUESTS
Boolean that indicates whether to log all the incoming HTTP requests. Defaults to false.
PET_STORE__STARGATE__CONCURRENT_CONNECTIONS_THRESHOLD
Set the maximum number of concurrent connections that I will accept. When this threshold is reached, a 503 Service Unavailable response will be sent and the connection will be closed. Defaults to 32.
' expandMacrosWith: PetStoreApplication version)
Expand Down
71 changes: 42 additions & 29 deletions source/Stargate-API-Skeleton/StargateApplication.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ Class {
#name : 'StargateApplication',
#superclass : 'LaunchpadApplication',
#instVars : [
'apiOptional'
'apiOptional',
'znEventToLogRecordAdapter'
],
#classInstVars : [
'Version'
Expand Down Expand Up @@ -87,29 +88,36 @@ StargateApplication class >> stackTraceDumpExtension [
{ #category : 'private' }
StargateApplication class >> stargateConfigurationParameters [

^ Array
with: ( MandatoryConfigurationParameter
named: 'Public URL'
describedBy: 'Public URL where the API is deployed. Used to create hypermedia links'
inside: self sectionsForStargateConfiguration
convertingWith: #asUrl )
with: ( MandatoryConfigurationParameter
named: 'Port'
describedBy: 'Listening port'
inside: self sectionsForStargateConfiguration
convertingWith: #asNumber )
with: ( MandatoryConfigurationParameter
named: 'Operations Secret'
describedBy: 'Secret key for checking JWT signatures'
inside: self sectionsForStargateConfiguration
convertingWith: #asByteArray ) asSensitive
with: ( OptionalConfigurationParameter
named: 'Concurrent Connections Threshold'
describedBy:
'Set the maximum number of concurrent connections that I will accept. When this threshold is reached, a 503 Service Unavailable response will be sent and the connection will be closed'
inside: self sectionsForStargateConfiguration
defaultingTo: 32
convertingWith: #asNumber )
^ OrderedCollection new
add: ( MandatoryConfigurationParameter
named: 'Public URL'
describedBy: 'Public URL where the API is deployed. Used to create hypermedia links'
inside: self sectionsForStargateConfiguration
convertingWith: #asUrl );
add: ( MandatoryConfigurationParameter
named: 'Port'
describedBy: 'Listening port'
inside: self sectionsForStargateConfiguration
convertingWith: #asNumber );
add: ( MandatoryConfigurationParameter
named: 'Operations Secret'
describedBy: 'Secret key for checking JWT signatures'
inside: self sectionsForStargateConfiguration
convertingWith: #asByteArray ) asSensitive;
add: ( OptionalConfigurationParameter
named: 'Log HTTP Requests'
describedBy: 'Boolean that indicates whether to log all the incoming HTTP requests'
inside: self sectionsForStargateConfiguration
defaultingTo: false
convertingWith: #asBoolean );
add: ( OptionalConfigurationParameter
named: 'Concurrent Connections Threshold'
describedBy:
'Set the maximum number of concurrent connections that I will accept. When this threshold is reached, a 503 Service Unavailable response will be sent and the connection will be closed'
inside: self sectionsForStargateConfiguration
defaultingTo: 32
convertingWith: #asNumber );
yourself
]

{ #category : 'accessing' }
Expand Down Expand Up @@ -177,8 +185,9 @@ StargateApplication >> authAlgorithm [
StargateApplication >> basicStartWithin: context [

| api |

self logAPIVersion.
self configureHTTPRequestsLogging.
api := self createAPI.
self
configureGlobalErrorHandlerIn: api;
Expand All @@ -190,6 +199,7 @@ StargateApplication >> basicStartWithin: context [
StargateApplication >> basicStop [

apiOptional withContentDo: [ :api | api stop ].
znEventToLogRecordAdapter stopListeners.
super basicStop
]

Expand Down Expand Up @@ -224,10 +234,12 @@ StargateApplication >> configureGlobalErrorHandlerIn: api [
] unless: self isDebugModeEnabled
]

{ #category : 'private - accessing' }
StargateApplication >> controllersToInstall [
{ #category : 'private - activation/deactivation' }
StargateApplication >> configureHTTPRequestsLogging [

^ self subclassResponsibility
znEventToLogRecordAdapter
logIncomingRequests: self stargateConfiguration logHTTPRequests;
startUpListeners
]

{ #category : 'private - activation/deactivation' }
Expand All @@ -245,7 +257,8 @@ StargateApplication >> createAPI [
StargateApplication >> initialize [

super initialize.
apiOptional := Optional unused
apiOptional := Optional unused.
znEventToLogRecordAdapter := ZnEventToLogRecordAdapter new
]

{ #category : 'private - activation/deactivation' }
Expand Down
Loading