From 48cb246f7c8f662c0790459967b1acd90aa1fb22 Mon Sep 17 00:00:00 2001 From: Vitalij Berdinskih Date: Sun, 18 Feb 2024 22:52:13 +0200 Subject: [PATCH] Initial import --- .codenarcrc | 438 ++++++ .editorconfig | 1194 +++++++++++++++++ .github/ISSUE_TEMPLATE/bug_report.yml | 68 + .github/ISSUE_TEMPLATE/feature_request.yml | 44 + .github/funding.yml | 5 + .github/workflows/codeql.yml | 40 + .gitignore | 35 + .markdownlint.json | 12 + .mvn/ci_settings.xml | 12 + .mvn/maven.config | 7 + .mvn/wrapper/.gitignore | 1 + .mvn/wrapper/MavenWrapperDownloader.java | 99 ++ .mvn/wrapper/maven-wrapper.properties | 18 + LICENSE | 201 +++ NOTICE | 39 + changelog.md | 140 ++ contributing.md | 25 + core/pom.xml | 101 ++ .../aws_lambda/slf4j/AWSLambdaLogger.java | 427 ++++++ .../slf4j/AWSLambdaLoggerConfiguration.java | 270 ++++ .../AWSLambdaLoggerConfigurationProperty.java | 116 ++ .../slf4j/AWSLambdaLoggerFactory.java | 338 +++++ .../slf4j/AWSLambdaLoggerLevel.java | 88 ++ .../slf4j/AWSLambdaLoggerOutput.java | 40 + .../slf4j/AWSLambdaServiceProvider.java | 69 + .../bot_by/aws_lambda/slf4j/package-info.java | 8 + .../org.slf4j.spi.SLF4JServiceProvider | 1 + .../java/org/example/ServiceProvider.java | 9 + .../java/org/example/TestServiceProvider.java | 22 + .../AWSLambdaLoggerConfigurationTest.java | 291 ++++ .../slf4j/AWSLambdaLoggerFactoryTest.java | 37 + .../slf4j/AWSLambdaLoggerLevelTest.java | 84 ++ .../aws_lambda/slf4j/AWSLambdaLoggerTest.java | 571 ++++++++ .../slf4j/AWSLambdaServiceProviderTest.java | 32 + .../slf4j/EnvironmentVariablesTest.java | 219 +++ .../bot_by/aws_lambda/slf4j/MarkedTest.java | 686 ++++++++++ .../aws_lambda/slf4j/PropertiesTest.java | 447 ++++++ .../services/org.example.ServiceProvider | 1 + .../class-log-level-debug.properties | 2 + .../class-log-level-error.properties | 2 + .../resources/class-log-level-info.properties | 2 + .../class-log-level-marker.properties | 2 + .../class-log-level-multi.properties | 2 + .../resources/class-log-level-none.properties | 2 + .../class-log-level-trace.properties | 2 + .../resources/class-log-level-warn.properties | 2 + .../resources/custom-separators.properties | 5 + .../default-log-level-debug.properties | 1 + .../default-log-level-error.properties | 1 + .../default-log-level-info.properties | 1 + .../default-log-level-marker.properties | 1 + .../default-log-level-multi.properties | 1 + .../default-log-level-none.properties | 1 + .../default-log-level-trace.properties | 1 + .../default-log-level-warn.properties | 1 + .../test/resources/lambda-logger.properties | 9 + .../parent-log-level-debug.properties | 2 + .../parent-log-level-error.properties | 2 + .../parent-log-level-info.properties | 2 + .../parent-log-level-marker.properties | 2 + .../parent-log-level-multi.properties | 2 + .../parent-log-level-none.properties | 2 + .../parent-log-level-trace.properties | 2 + .../parent-log-level-warn.properties | 2 + .../wrong-date-time-format.properties | 9 + .../wrong-default-logger-level.properties | 8 + .../resources/wrong-logger-level.properties | 9 + json-logger/pom.xml | 82 ++ .../slf4j/json_output/JSONLoggerOutput.java | 169 +++ .../slf4j/json_output/package-info.java | 7 + ..._by.aws_lambda.slf4j.AWSLambdaLoggerOutput | 1 + .../json_output/JSONLoggerOutputTest.java | 354 +++++ logger/pom.xml | 87 ++ .../lambda_logger/LambdaLoggerOutput.java | 149 ++ .../slf4j/lambda_logger/package-info.java | 7 + ..._by.aws_lambda.slf4j.AWSLambdaLoggerOutput | 1 + .../lambda_logger/LambdaLoggerOutputTest.java | 271 ++++ mvnw | 308 +++++ mvnw.cmd | 205 +++ pom.xml | 456 +++++++ readme.md | 259 ++++ src/site/resources/cloudwatch-screenshot.png | Bin 0 -> 208866 bytes .../environment-variable-screenshot.png | Bin 0 -> 23979 bytes 83 files changed, 8671 insertions(+) create mode 100644 .codenarcrc create mode 100644 .editorconfig create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/funding.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .gitignore create mode 100644 .markdownlint.json create mode 100644 .mvn/ci_settings.xml create mode 100644 .mvn/maven.config create mode 100644 .mvn/wrapper/.gitignore create mode 100644 .mvn/wrapper/MavenWrapperDownloader.java create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 LICENSE create mode 100644 NOTICE create mode 100644 changelog.md create mode 100644 contributing.md create mode 100644 core/pom.xml create mode 100644 core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLogger.java create mode 100644 core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfiguration.java create mode 100644 core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfigurationProperty.java create mode 100644 core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerFactory.java create mode 100644 core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerLevel.java create mode 100644 core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerOutput.java create mode 100644 core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaServiceProvider.java create mode 100644 core/src/main/java/uk/bot_by/aws_lambda/slf4j/package-info.java create mode 100644 core/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider create mode 100644 core/src/test/java/org/example/ServiceProvider.java create mode 100644 core/src/test/java/org/example/TestServiceProvider.java create mode 100644 core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfigurationTest.java create mode 100644 core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerFactoryTest.java create mode 100644 core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerLevelTest.java create mode 100644 core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerTest.java create mode 100644 core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaServiceProviderTest.java create mode 100644 core/src/test/java/uk/bot_by/aws_lambda/slf4j/EnvironmentVariablesTest.java create mode 100644 core/src/test/java/uk/bot_by/aws_lambda/slf4j/MarkedTest.java create mode 100644 core/src/test/java/uk/bot_by/aws_lambda/slf4j/PropertiesTest.java create mode 100644 core/src/test/resources/META-INF/services/org.example.ServiceProvider create mode 100644 core/src/test/resources/class-log-level-debug.properties create mode 100644 core/src/test/resources/class-log-level-error.properties create mode 100644 core/src/test/resources/class-log-level-info.properties create mode 100644 core/src/test/resources/class-log-level-marker.properties create mode 100644 core/src/test/resources/class-log-level-multi.properties create mode 100644 core/src/test/resources/class-log-level-none.properties create mode 100644 core/src/test/resources/class-log-level-trace.properties create mode 100644 core/src/test/resources/class-log-level-warn.properties create mode 100644 core/src/test/resources/custom-separators.properties create mode 100644 core/src/test/resources/default-log-level-debug.properties create mode 100644 core/src/test/resources/default-log-level-error.properties create mode 100644 core/src/test/resources/default-log-level-info.properties create mode 100644 core/src/test/resources/default-log-level-marker.properties create mode 100644 core/src/test/resources/default-log-level-multi.properties create mode 100644 core/src/test/resources/default-log-level-none.properties create mode 100644 core/src/test/resources/default-log-level-trace.properties create mode 100644 core/src/test/resources/default-log-level-warn.properties create mode 100644 core/src/test/resources/lambda-logger.properties create mode 100644 core/src/test/resources/parent-log-level-debug.properties create mode 100644 core/src/test/resources/parent-log-level-error.properties create mode 100644 core/src/test/resources/parent-log-level-info.properties create mode 100644 core/src/test/resources/parent-log-level-marker.properties create mode 100644 core/src/test/resources/parent-log-level-multi.properties create mode 100644 core/src/test/resources/parent-log-level-none.properties create mode 100644 core/src/test/resources/parent-log-level-trace.properties create mode 100644 core/src/test/resources/parent-log-level-warn.properties create mode 100644 core/src/test/resources/wrong-date-time-format.properties create mode 100644 core/src/test/resources/wrong-default-logger-level.properties create mode 100644 core/src/test/resources/wrong-logger-level.properties create mode 100644 json-logger/pom.xml create mode 100644 json-logger/src/main/java/uk/bot_by/aws_lambda/slf4j/json_output/JSONLoggerOutput.java create mode 100644 json-logger/src/main/java/uk/bot_by/aws_lambda/slf4j/json_output/package-info.java create mode 100644 json-logger/src/main/resources/META-INF/services/uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput create mode 100644 json-logger/src/test/java/uk/bot_by/aws_lambda/slf4j/json_output/JSONLoggerOutputTest.java create mode 100644 logger/pom.xml create mode 100644 logger/src/main/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/LambdaLoggerOutput.java create mode 100644 logger/src/main/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/package-info.java create mode 100644 logger/src/main/resources/META-INF/services/uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput create mode 100644 logger/src/test/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/LambdaLoggerOutputTest.java create mode 100755 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 readme.md create mode 100644 src/site/resources/cloudwatch-screenshot.png create mode 100644 src/site/resources/environment-variable-screenshot.png diff --git a/.codenarcrc b/.codenarcrc new file mode 100644 index 0000000..51d37a7 --- /dev/null +++ b/.codenarcrc @@ -0,0 +1,438 @@ +ruleset { + // rulesets/basic.xml + AssertWithinFinallyBlock + AssignmentInConditional + BigDecimalInstantiation + BitwiseOperatorInConditional + BooleanGetBoolean + BrokenNullCheck + BrokenOddnessCheck + ClassForName + ComparisonOfTwoConstants + ComparisonWithSelf + ConstantAssertExpression + ConstantIfExpression + ConstantTernaryExpression + DeadCode + DoubleNegative + DuplicateCaseStatement + DuplicateMapKey + DuplicateSetValue + EmptyCatchBlock + EmptyClass + EmptyElseBlock + EmptyFinallyBlock + EmptyForStatement + EmptyIfStatement + EmptyInstanceInitializer + EmptyMethod + EmptyStaticInitializer + EmptySwitchStatement + EmptySynchronizedStatement + EmptyTryBlock + EmptyWhileStatement + EqualsAndHashCode + EqualsOverloaded + ExplicitGarbageCollection + ForLoopShouldBeWhileLoop + HardCodedWindowsFileSeparator + HardCodedWindowsRootDirectory + IntegerGetInteger + MultipleUnaryOperators + ParameterAssignmentInFilterClosure + RandomDoubleCoercedToZero + RemoveAllOnSelf + ReturnFromFinallyBlock + ThrowExceptionFromFinallyBlock + + // rulesets/braces.xml + ElseBlockBraces + ForStatementBraces + IfStatementBraces + WhileStatementBraces + + // rulesets/comments.xml + ClassJavadoc + JavadocConsecutiveEmptyLines + JavadocEmptyAuthorTag + JavadocEmptyExceptionTag + JavadocEmptyFirstLine + JavadocEmptyLastLine + JavadocEmptyParamTag + JavadocEmptyReturnTag + JavadocEmptySeeTag + JavadocEmptySinceTag + JavadocEmptyThrowsTag + JavadocEmptyVersionTag + JavadocMissingExceptionDescription + JavadocMissingParamDescription + JavadocMissingThrowsDescription + + // rulesets/concurrency.xml + BusyWait + DoubleCheckedLocking + InconsistentPropertyLocking + InconsistentPropertySynchronization + NestedSynchronization + StaticCalendarField + StaticConnection + StaticDateFormatField + StaticMatcherField + StaticSimpleDateFormatField + SynchronizedMethod + SynchronizedOnBoxedPrimitive + SynchronizedOnGetClass + SynchronizedOnReentrantLock + SynchronizedOnString + SynchronizedOnThis + SynchronizedReadObjectMethod + SystemRunFinalizersOnExit + ThisReferenceEscapesConstructor + ThreadGroup + ThreadLocalNotStaticFinal + ThreadYield + UseOfNotifyMethod + VolatileArrayField + VolatileLongOrDoubleField + WaitOutsideOfWhileLoop + + // rulesets/convention.xml + ConfusingTernary + CouldBeElvis + CouldBeSwitchStatement + FieldTypeRequired + HashtableIsObsolete + IfStatementCouldBeTernary + ImplicitClosureParameter + ImplicitReturnStatement + InvertedCondition + InvertedIfElse + LongLiteralWithLowerCaseL + MethodParameterTypeRequired + MethodReturnTypeRequired + NoDef + NoDouble + NoFloat + NoJavaUtilDate + NoTabCharacter + ParameterReassignment + PublicMethodsBeforeNonPublicMethods + StaticFieldsBeforeInstanceFields + StaticMethodsBeforeInstanceMethods + TernaryCouldBeElvis + TrailingComma + VariableTypeRequired + VectorIsObsolete + + // rulesets/design.xml + AbstractClassWithPublicConstructor + AbstractClassWithoutAbstractMethod + AssignmentToStaticFieldFromInstanceMethod + BooleanMethodReturnsNull + BuilderMethodWithSideEffects + CloneableWithoutClone + CloseWithoutCloseable + CompareToWithoutComparable + ConstantsOnlyInterface + EmptyMethodInAbstractClass + FinalClassWithProtectedMember + ImplementationAsType + Instanceof + LocaleSetDefault + NestedForLoop + OptionalCollectionReturnType + OptionalField + OptionalMethodParameter + PrivateFieldCouldBeFinal + PublicInstanceField + ReturnsNullInsteadOfEmptyArray + ReturnsNullInsteadOfEmptyCollection + SimpleDateFormatMissingLocale + StatelessSingleton + ToStringReturnsNull + + // rulesets/dry.xml + DuplicateListLiteral + DuplicateMapLiteral + DuplicateNumberLiteral + DuplicateStringLiteral + + // rulesets/enhanced.xml + CloneWithoutCloneable + JUnitAssertEqualsConstantActualValue + MissingOverrideAnnotation + UnsafeImplementationAsMap + + // rulesets/exceptions.xml + CatchArrayIndexOutOfBoundsException + CatchError + CatchException + CatchIllegalMonitorStateException + CatchIndexOutOfBoundsException + CatchNullPointerException + CatchRuntimeException + CatchThrowable + ConfusingClassNamedException + ExceptionExtendsError + ExceptionExtendsThrowable + ExceptionNotThrown + MissingNewInThrowStatement + ReturnNullFromCatchBlock + SwallowThreadDeath + ThrowError + ThrowException + ThrowNullPointerException + ThrowRuntimeException + ThrowThrowable + + // rulesets/formatting.xml + BlankLineBeforePackage + BlockEndsWithBlankLine + BlockStartsWithBlankLine + BracesForClass + BracesForForLoop + BracesForIfElse + BracesForMethod + BracesForTryCatchFinally + ClassEndsWithBlankLine + ClassStartsWithBlankLine + ClosureStatementOnOpeningLineOfMultipleLineClosure + ConsecutiveBlankLines + FileEndsWithoutNewline + Indentation + LineLength + MissingBlankLineAfterImports + MissingBlankLineAfterPackage + MissingBlankLineBeforeAnnotatedField + SpaceAfterCatch + SpaceAfterClosingBrace + SpaceAfterComma + SpaceAfterFor + SpaceAfterIf + SpaceAfterMethodCallName + SpaceAfterMethodDeclarationName + SpaceAfterNotOperator + SpaceAfterOpeningBrace + SpaceAfterSemicolon + SpaceAfterSwitch + SpaceAfterWhile + SpaceAroundClosureArrow + SpaceAroundMapEntryColon + SpaceAroundOperator + SpaceBeforeClosingBrace + SpaceBeforeOpeningBrace + SpaceInsideParentheses + TrailingWhitespace + + // rulesets/generic.xml + IllegalClassMember + IllegalClassReference + IllegalPackageReference + IllegalRegex + IllegalString + IllegalSubclass + RequiredRegex + RequiredString + StatelessClass + + // rulesets/grails.xml + GrailsDomainGormMethods + GrailsDomainHasEquals + GrailsDomainHasToString + GrailsDomainReservedSqlKeywordName + GrailsDomainStringPropertyMaxSize + GrailsDomainWithServiceReference + GrailsDuplicateConstraint + GrailsDuplicateMapping + GrailsMassAssignment + GrailsPublicControllerMethod + GrailsServletContextReference + GrailsStatelessService + + // rulesets/groovyism.xml + AssignCollectionSort + AssignCollectionUnique + ClosureAsLastMethodParameter + CollectAllIsDeprecated + ConfusingMultipleReturns + ExplicitArrayListInstantiation + ExplicitCallToAndMethod + ExplicitCallToCompareToMethod + ExplicitCallToDivMethod + ExplicitCallToEqualsMethod + ExplicitCallToGetAtMethod + ExplicitCallToLeftShiftMethod + ExplicitCallToMinusMethod + ExplicitCallToModMethod + ExplicitCallToMultiplyMethod + ExplicitCallToOrMethod + ExplicitCallToPlusMethod + ExplicitCallToPowerMethod + ExplicitCallToPutAtMethod + ExplicitCallToRightShiftMethod + ExplicitCallToXorMethod + ExplicitHashMapInstantiation + ExplicitHashSetInstantiation + ExplicitLinkedHashMapInstantiation + ExplicitLinkedListInstantiation + ExplicitStackInstantiation + ExplicitTreeSetInstantiation + GStringAsMapKey + GStringExpressionWithinString + GetterMethodCouldBeProperty + GroovyLangImmutable + UseCollectMany + UseCollectNested + + // rulesets/imports.xml + DuplicateImport + ImportFromSamePackage + ImportFromSunPackages + MisorderedStaticImports + NoWildcardImports + UnnecessaryGroovyImport + UnusedImport + + // rulesets/jdbc.xml + DirectConnectionManagement + JdbcConnectionReference + JdbcResultSetReference + JdbcStatementReference + + // rulesets/junit.xml + ChainedTest + CoupledTestCase + JUnitAssertAlwaysFails + JUnitAssertAlwaysSucceeds + JUnitFailWithoutMessage + JUnitLostTest + JUnitPublicField + JUnitPublicNonTestMethod + JUnitPublicProperty + JUnitSetUpCallsSuper + JUnitStyleAssertions + JUnitTearDownCallsSuper + JUnitTestMethodWithoutAssert + JUnitUnnecessarySetUp + JUnitUnnecessaryTearDown + JUnitUnnecessaryThrowsException + SpockIgnoreRestUsed + UnnecessaryFail + UseAssertEqualsInsteadOfAssertTrue + UseAssertFalseInsteadOfNegation + UseAssertNullInsteadOfAssertEquals + UseAssertSameInsteadOfAssertTrue + UseAssertTrueInsteadOfAssertEquals + UseAssertTrueInsteadOfNegation + + // rulesets/logging.xml + LoggerForDifferentClass + LoggerWithWrongModifiers + LoggingSwallowsStacktrace + MultipleLoggers + PrintStackTrace + Println + SystemErrPrint + SystemOutPrint + + // rulesets/naming.xml + AbstractClassName + ClassName + ClassNameSameAsFilename + ClassNameSameAsSuperclass + ConfusingMethodName + FactoryMethodName + FieldName + InterfaceName + InterfaceNameSameAsSuperInterface + MethodName + ObjectOverrideMisspelledMethodName + PackageName + PackageNameMatchesFilePath + ParameterName + PropertyName + VariableName + + // rulesets/security.xml + FileCreateTempFile + InsecureRandom + NonFinalPublicField + NonFinalSubclassOfSensitiveInterface + ObjectFinalize + PublicFinalizeMethod + SystemExit + UnsafeArrayDeclaration + + // rulesets/serialization.xml + EnumCustomSerializationIgnored + SerialPersistentFields + SerialVersionUID + SerializableClassMustDefineSerialVersionUID + + // rulesets/size.xml + AbcMetric // Requires the GMetrics jar + ClassSize + CrapMetric // Requires the GMetrics jar and a Cobertura coverage file + CyclomaticComplexity // Requires the GMetrics jar + MethodCount + MethodSize + NestedBlockDepth + ParameterCount + + // rulesets/unnecessary.xml + AddEmptyString + ConsecutiveLiteralAppends + ConsecutiveStringConcatenation + UnnecessaryBigDecimalInstantiation + UnnecessaryBigIntegerInstantiation + UnnecessaryBooleanExpression + UnnecessaryBooleanInstantiation + UnnecessaryCallForLastElement + UnnecessaryCallToSubstring + UnnecessaryCast + UnnecessaryCatchBlock + UnnecessaryCollectCall + UnnecessaryCollectionCall + UnnecessaryConstructor + UnnecessaryDefInFieldDeclaration + UnnecessaryDefInMethodDeclaration + UnnecessaryDefInVariableDeclaration + UnnecessaryDotClass + UnnecessaryDoubleInstantiation + UnnecessaryElseStatement + UnnecessaryFinalOnPrivateMethod + UnnecessaryFloatInstantiation + UnnecessaryGString + UnnecessaryGetter + UnnecessaryIfStatement + UnnecessaryInstanceOfCheck + UnnecessaryInstantiationToGetClass + UnnecessaryIntegerInstantiation + UnnecessaryLongInstantiation + UnnecessaryModOne + UnnecessaryNullCheck + UnnecessaryNullCheckBeforeInstanceOf + UnnecessaryObjectReferences + UnnecessaryOverridingMethod + UnnecessaryPackageReference + UnnecessaryParenthesesForMethodCallWithClosure + UnnecessaryPublicModifier + UnnecessaryReturnKeyword + UnnecessarySafeNavigationOperator + UnnecessarySelfAssignment + UnnecessarySemicolon + UnnecessarySetter + UnnecessaryStringInstantiation + UnnecessaryTernaryExpression + UnnecessaryToString + UnnecessaryTransientModifier + + // rulesets/unused.xml + UnusedArray + UnusedMethodParameter + UnusedObject + UnusedPrivateField + UnusedPrivateMethod + UnusedPrivateMethodParameter + UnusedVariable +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..cbb750d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,1194 @@ +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = false +max_line_length = 100 +tab_width = 2 +trim_trailing_whitespace = true +ij_continuation_indent_size = 4 +ij_formatter_off_tag = @formatter:off +ij_formatter_on_tag = @formatter:on +ij_formatter_tags_enabled = true +ij_smart_tabs = false +ij_visual_guides = +ij_wrap_on_typing = false + +[*.css] +ij_css_align_closing_brace_with_properties = false +ij_css_blank_lines_around_nested_selector = 1 +ij_css_blank_lines_between_blocks = 1 +ij_css_block_comment_add_space = false +ij_css_brace_placement = end_of_line +ij_css_enforce_quotes_on_format = false +ij_css_hex_color_long_format = false +ij_css_hex_color_lower_case = false +ij_css_hex_color_short_format = false +ij_css_hex_color_upper_case = false +ij_css_keep_blank_lines_in_code = 2 +ij_css_keep_indents_on_empty_lines = false +ij_css_keep_single_line_blocks = false +ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow +ij_css_space_after_colon = true +ij_css_space_before_opening_brace = true +ij_css_use_double_quotes = true +ij_css_value_alignment = do_not_align + +[*.feature] +tab_width = 4 +ij_continuation_indent_size = 8 +ij_gherkin_keep_indents_on_empty_lines = false + +[*.java] +ij_java_align_consecutive_assignments = false +ij_java_align_consecutive_variable_declarations = false +ij_java_align_group_field_declarations = false +ij_java_align_multiline_annotation_parameters = false +ij_java_align_multiline_array_initializer_expression = false +ij_java_align_multiline_assignment = false +ij_java_align_multiline_binary_operation = false +ij_java_align_multiline_chained_methods = false +ij_java_align_multiline_deconstruction_list_components = true +ij_java_align_multiline_extends_list = false +ij_java_align_multiline_for = false +ij_java_align_multiline_method_parentheses = false +ij_java_align_multiline_parameters = false +ij_java_align_multiline_parameters_in_calls = false +ij_java_align_multiline_parenthesized_expression = false +ij_java_align_multiline_records = true +ij_java_align_multiline_resources = false +ij_java_align_multiline_ternary_operation = false +ij_java_align_multiline_text_blocks = false +ij_java_align_multiline_throws_list = false +ij_java_align_subsequent_simple_methods = false +ij_java_align_throws_keyword = false +ij_java_align_types_in_multi_catch = true +ij_java_annotation_parameter_wrap = off +ij_java_array_initializer_new_line_after_left_brace = false +ij_java_array_initializer_right_brace_on_new_line = false +ij_java_array_initializer_wrap = normal +ij_java_assert_statement_colon_on_next_line = false +ij_java_assert_statement_wrap = off +ij_java_assignment_wrap = off +ij_java_binary_operation_sign_on_next_line = true +ij_java_binary_operation_wrap = normal +ij_java_blank_lines_after_anonymous_class_header = 0 +ij_java_blank_lines_after_class_header = 1 +ij_java_blank_lines_after_imports = 1 +ij_java_blank_lines_after_package = 1 +ij_java_blank_lines_around_class = 1 +ij_java_blank_lines_around_field = 0 +ij_java_blank_lines_around_field_in_interface = 0 +ij_java_blank_lines_around_initializer = 1 +ij_java_blank_lines_around_method = 1 +ij_java_blank_lines_around_method_in_interface = 1 +ij_java_blank_lines_before_class_end = 0 +ij_java_blank_lines_before_imports = 1 +ij_java_blank_lines_before_method_body = 0 +ij_java_blank_lines_before_package = 0 +ij_java_block_brace_style = end_of_line +ij_java_block_comment_add_space = false +ij_java_block_comment_at_first_column = true +ij_java_builder_methods = +ij_java_call_parameters_new_line_after_left_paren = false +ij_java_call_parameters_right_paren_on_new_line = false +ij_java_call_parameters_wrap = normal +ij_java_case_statement_on_separate_line = true +ij_java_catch_on_new_line = false +ij_java_class_annotation_wrap = split_into_lines +ij_java_class_brace_style = end_of_line +ij_java_class_count_to_use_import_on_demand = 999 +ij_java_class_names_in_javadoc = 1 +ij_java_deconstruction_list_wrap = normal +ij_java_do_not_indent_top_level_class_members = false +ij_java_do_not_wrap_after_single_annotation = false +ij_java_do_not_wrap_after_single_annotation_in_parameter = false +ij_java_do_while_brace_force = always +ij_java_doc_add_blank_line_after_description = true +ij_java_doc_add_blank_line_after_param_comments = false +ij_java_doc_add_blank_line_after_return = false +ij_java_doc_add_p_tag_on_empty_lines = true +ij_java_doc_align_exception_comments = true +ij_java_doc_align_param_comments = true +ij_java_doc_do_not_wrap_if_one_line = false +ij_java_doc_enable_formatting = true +ij_java_doc_enable_leading_asterisks = true +ij_java_doc_indent_on_continuation = false +ij_java_doc_keep_empty_lines = true +ij_java_doc_keep_empty_parameter_tag = true +ij_java_doc_keep_empty_return_tag = true +ij_java_doc_keep_empty_throws_tag = true +ij_java_doc_keep_invalid_tags = true +ij_java_doc_param_description_on_new_line = false +ij_java_doc_preserve_line_breaks = false +ij_java_doc_use_throws_not_exception_tag = true +ij_java_else_on_new_line = false +ij_java_entity_dd_prefix = +ij_java_entity_dd_suffix = EJB +ij_java_entity_eb_prefix = +ij_java_entity_eb_suffix = Bean +ij_java_entity_hi_prefix = +ij_java_entity_hi_suffix = Home +ij_java_entity_lhi_prefix = Local +ij_java_entity_lhi_suffix = Home +ij_java_entity_li_prefix = Local +ij_java_entity_li_suffix = +ij_java_entity_pk_class = java.lang.String +ij_java_entity_ri_prefix = +ij_java_entity_ri_suffix = +ij_java_entity_vo_prefix = +ij_java_entity_vo_suffix = VO +ij_java_enum_constants_wrap = off +ij_java_extends_keyword_wrap = off +ij_java_extends_list_wrap = normal +ij_java_field_annotation_wrap = split_into_lines +ij_java_field_name_prefix = +ij_java_field_name_suffix = +ij_java_filter_class_prefix = +ij_java_filter_class_suffix = +ij_java_filter_dd_prefix = +ij_java_filter_dd_suffix = +ij_java_finally_on_new_line = false +ij_java_for_brace_force = always +ij_java_for_statement_new_line_after_left_paren = false +ij_java_for_statement_right_paren_on_new_line = false +ij_java_for_statement_wrap = normal +ij_java_generate_final_locals = false +ij_java_generate_final_parameters = false +ij_java_if_brace_force = always +ij_java_imports_layout = $*,|,* +ij_java_indent_case_from_switch = true +ij_java_insert_inner_class_imports = true +ij_java_insert_override_annotation = true +ij_java_keep_blank_lines_before_right_brace = 2 +ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +ij_java_keep_blank_lines_in_code = 1 +ij_java_keep_blank_lines_in_declarations = 2 +ij_java_keep_builder_methods_indents = false +ij_java_keep_control_statement_in_one_line = false +ij_java_keep_first_column_comment = true +ij_java_keep_indents_on_empty_lines = false +ij_java_keep_line_breaks = true +ij_java_keep_multiple_expressions_in_one_line = false +ij_java_keep_simple_blocks_in_one_line = false +ij_java_keep_simple_classes_in_one_line = false +ij_java_keep_simple_lambdas_in_one_line = false +ij_java_keep_simple_methods_in_one_line = false +ij_java_label_indent_absolute = false +ij_java_label_indent_size = 0 +ij_java_lambda_brace_style = end_of_line +ij_java_layout_static_imports_separately = true +ij_java_line_comment_add_space = false +ij_java_line_comment_add_space_on_reformat = false +ij_java_line_comment_at_first_column = true +ij_java_listener_class_prefix = +ij_java_listener_class_suffix = +ij_java_local_variable_name_prefix = +ij_java_local_variable_name_suffix = +ij_java_message_dd_prefix = +ij_java_message_dd_suffix = EJB +ij_java_message_eb_prefix = +ij_java_message_eb_suffix = Bean +ij_java_method_annotation_wrap = split_into_lines +ij_java_method_brace_style = end_of_line +ij_java_method_call_chain_wrap = normal +ij_java_method_parameters_new_line_after_left_paren = false +ij_java_method_parameters_right_paren_on_new_line = false +ij_java_method_parameters_wrap = normal +ij_java_modifier_list_wrap = false +ij_java_multi_catch_types_wrap = normal +ij_java_names_count_to_use_import_on_demand = 999 +ij_java_new_line_after_lparen_in_annotation = false +ij_java_new_line_after_lparen_in_deconstruction_pattern = true +ij_java_new_line_after_lparen_in_record_header = false +ij_java_packages_to_use_import_on_demand = +ij_java_parameter_annotation_wrap = off +ij_java_parameter_name_prefix = +ij_java_parameter_name_suffix = +ij_java_parentheses_expression_new_line_after_left_paren = false +ij_java_parentheses_expression_right_paren_on_new_line = false +ij_java_place_assignment_sign_on_next_line = false +ij_java_prefer_longer_names = true +ij_java_prefer_parameters_wrap = false +ij_java_record_components_wrap = normal +ij_java_repeat_annotations = +ij_java_repeat_synchronized = true +ij_java_replace_instanceof_and_cast = false +ij_java_replace_null_check = true +ij_java_replace_sum_lambda_with_method_ref = true +ij_java_resource_list_new_line_after_left_paren = false +ij_java_resource_list_right_paren_on_new_line = false +ij_java_resource_list_wrap = off +ij_java_rparen_on_new_line_in_annotation = false +ij_java_rparen_on_new_line_in_deconstruction_pattern = true +ij_java_rparen_on_new_line_in_record_header = false +ij_java_servlet_class_prefix = +ij_java_servlet_class_suffix = +ij_java_servlet_dd_prefix = +ij_java_servlet_dd_suffix = +ij_java_session_dd_prefix = +ij_java_session_dd_suffix = EJB +ij_java_session_eb_prefix = +ij_java_session_eb_suffix = Bean +ij_java_session_hi_prefix = +ij_java_session_hi_suffix = Home +ij_java_session_lhi_prefix = Local +ij_java_session_lhi_suffix = Home +ij_java_session_li_prefix = Local +ij_java_session_li_suffix = +ij_java_session_ri_prefix = +ij_java_session_ri_suffix = +ij_java_session_si_prefix = +ij_java_session_si_suffix = Service +ij_java_space_after_closing_angle_bracket_in_type_argument = false +ij_java_space_after_colon = true +ij_java_space_after_comma = true +ij_java_space_after_comma_in_type_arguments = true +ij_java_space_after_for_semicolon = true +ij_java_space_after_quest = true +ij_java_space_after_type_cast = true +ij_java_space_before_annotation_array_initializer_left_brace = false +ij_java_space_before_annotation_parameter_list = false +ij_java_space_before_array_initializer_left_brace = false +ij_java_space_before_catch_keyword = true +ij_java_space_before_catch_left_brace = true +ij_java_space_before_catch_parentheses = true +ij_java_space_before_class_left_brace = true +ij_java_space_before_colon = true +ij_java_space_before_colon_in_foreach = true +ij_java_space_before_comma = false +ij_java_space_before_deconstruction_list = false +ij_java_space_before_do_left_brace = true +ij_java_space_before_else_keyword = true +ij_java_space_before_else_left_brace = true +ij_java_space_before_finally_keyword = true +ij_java_space_before_finally_left_brace = true +ij_java_space_before_for_left_brace = true +ij_java_space_before_for_parentheses = true +ij_java_space_before_for_semicolon = false +ij_java_space_before_if_left_brace = true +ij_java_space_before_if_parentheses = true +ij_java_space_before_method_call_parentheses = false +ij_java_space_before_method_left_brace = true +ij_java_space_before_method_parentheses = false +ij_java_space_before_opening_angle_bracket_in_type_parameter = false +ij_java_space_before_quest = true +ij_java_space_before_switch_left_brace = true +ij_java_space_before_switch_parentheses = true +ij_java_space_before_synchronized_left_brace = true +ij_java_space_before_synchronized_parentheses = true +ij_java_space_before_try_left_brace = true +ij_java_space_before_try_parentheses = true +ij_java_space_before_type_parameter_list = false +ij_java_space_before_while_keyword = true +ij_java_space_before_while_left_brace = true +ij_java_space_before_while_parentheses = true +ij_java_space_inside_one_line_enum_braces = false +ij_java_space_within_empty_array_initializer_braces = false +ij_java_space_within_empty_method_call_parentheses = false +ij_java_space_within_empty_method_parentheses = false +ij_java_spaces_around_additive_operators = true +ij_java_spaces_around_annotation_eq = true +ij_java_spaces_around_assignment_operators = true +ij_java_spaces_around_bitwise_operators = true +ij_java_spaces_around_equality_operators = true +ij_java_spaces_around_lambda_arrow = true +ij_java_spaces_around_logical_operators = true +ij_java_spaces_around_method_ref_dbl_colon = false +ij_java_spaces_around_multiplicative_operators = true +ij_java_spaces_around_relational_operators = true +ij_java_spaces_around_shift_operators = true +ij_java_spaces_around_type_bounds_in_type_parameters = true +ij_java_spaces_around_unary_operator = false +ij_java_spaces_within_angle_brackets = false +ij_java_spaces_within_annotation_parentheses = false +ij_java_spaces_within_array_initializer_braces = false +ij_java_spaces_within_braces = false +ij_java_spaces_within_brackets = false +ij_java_spaces_within_cast_parentheses = false +ij_java_spaces_within_catch_parentheses = false +ij_java_spaces_within_deconstruction_list = false +ij_java_spaces_within_for_parentheses = false +ij_java_spaces_within_if_parentheses = false +ij_java_spaces_within_method_call_parentheses = false +ij_java_spaces_within_method_parentheses = false +ij_java_spaces_within_parentheses = false +ij_java_spaces_within_record_header = false +ij_java_spaces_within_switch_parentheses = false +ij_java_spaces_within_synchronized_parentheses = false +ij_java_spaces_within_try_parentheses = false +ij_java_spaces_within_while_parentheses = false +ij_java_special_else_if_treatment = true +ij_java_static_field_name_prefix = +ij_java_static_field_name_suffix = +ij_java_subclass_name_prefix = +ij_java_subclass_name_suffix = Impl +ij_java_ternary_operation_signs_on_next_line = true +ij_java_ternary_operation_wrap = normal +ij_java_test_name_prefix = +ij_java_test_name_suffix = Test +ij_java_throws_keyword_wrap = normal +ij_java_throws_list_wrap = off +ij_java_use_external_annotations = false +ij_java_use_fq_class_names = false +ij_java_use_relative_indents = false +ij_java_use_single_class_imports = true +ij_java_variable_annotation_wrap = off +ij_java_visibility = public +ij_java_while_brace_force = always +ij_java_while_on_new_line = false +ij_java_wrap_comments = true +ij_java_wrap_first_method_in_call_chain = false +ij_java_wrap_long_lines = false + +[*.less] +tab_width = 4 +ij_continuation_indent_size = 8 +ij_less_align_closing_brace_with_properties = false +ij_less_blank_lines_around_nested_selector = 1 +ij_less_blank_lines_between_blocks = 1 +ij_less_block_comment_add_space = false +ij_less_brace_placement = 0 +ij_less_enforce_quotes_on_format = false +ij_less_hex_color_long_format = false +ij_less_hex_color_lower_case = false +ij_less_hex_color_short_format = false +ij_less_hex_color_upper_case = false +ij_less_keep_blank_lines_in_code = 2 +ij_less_keep_indents_on_empty_lines = false +ij_less_keep_single_line_blocks = false +ij_less_line_comment_add_space = false +ij_less_line_comment_at_first_column = false +ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow +ij_less_space_after_colon = true +ij_less_space_before_opening_brace = true +ij_less_use_double_quotes = true +ij_less_value_alignment = 0 + +[*.proto] +max_line_length = 80 +ij_continuation_indent_size = 2 +ij_protobuf_keep_blank_lines_in_code = 2 +ij_protobuf_keep_indents_on_empty_lines = false +ij_protobuf_keep_line_breaks = true +ij_protobuf_space_after_comma = true +ij_protobuf_space_before_comma = false +ij_protobuf_spaces_around_assignment_operators = true +ij_protobuf_spaces_within_braces = false +ij_protobuf_spaces_within_brackets = false + +[*.sass] +ij_sass_align_closing_brace_with_properties = false +ij_sass_blank_lines_around_nested_selector = 1 +ij_sass_blank_lines_between_blocks = 1 +ij_sass_brace_placement = 0 +ij_sass_enforce_quotes_on_format = false +ij_sass_hex_color_long_format = false +ij_sass_hex_color_lower_case = false +ij_sass_hex_color_short_format = false +ij_sass_hex_color_upper_case = false +ij_sass_keep_blank_lines_in_code = 2 +ij_sass_keep_indents_on_empty_lines = false +ij_sass_keep_single_line_blocks = false +ij_sass_line_comment_add_space = false +ij_sass_line_comment_at_first_column = false +ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow +ij_sass_space_after_colon = true +ij_sass_space_before_opening_brace = true +ij_sass_use_double_quotes = true +ij_sass_value_alignment = 0 + +[*.scss] +ij_scss_align_closing_brace_with_properties = false +ij_scss_blank_lines_around_nested_selector = 1 +ij_scss_blank_lines_between_blocks = 1 +ij_scss_block_comment_add_space = false +ij_scss_brace_placement = 0 +ij_scss_enforce_quotes_on_format = false +ij_scss_hex_color_long_format = false +ij_scss_hex_color_lower_case = false +ij_scss_hex_color_short_format = false +ij_scss_hex_color_upper_case = false +ij_scss_keep_blank_lines_in_code = 2 +ij_scss_keep_indents_on_empty_lines = false +ij_scss_keep_single_line_blocks = false +ij_scss_line_comment_add_space = false +ij_scss_line_comment_at_first_column = false +ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow +ij_scss_space_after_colon = true +ij_scss_space_before_opening_brace = true +ij_scss_use_double_quotes = true +ij_scss_value_alignment = 0 + +[*.vue] +ij_vue_indent_children_of_top_level = template +ij_vue_interpolation_new_line_after_start_delimiter = true +ij_vue_interpolation_new_line_before_end_delimiter = true +ij_vue_interpolation_wrap = off +ij_vue_keep_indents_on_empty_lines = false +ij_vue_spaces_within_interpolation_expressions = true + +[.editorconfig] +ij_editorconfig_align_group_field_declarations = false +ij_editorconfig_space_after_colon = false +ij_editorconfig_space_after_comma = true +ij_editorconfig_space_before_colon = false +ij_editorconfig_space_before_comma = false +ij_editorconfig_spaces_around_assignment_operators = true + +[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.pom,*.rng,*.tld,*.wadl,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}] +ij_continuation_indent_size = 2 +ij_xml_align_attributes = false +ij_xml_align_text = false +ij_xml_attribute_wrap = normal +ij_xml_block_comment_add_space = false +ij_xml_block_comment_at_first_column = true +ij_xml_keep_blank_lines = 2 +ij_xml_keep_indents_on_empty_lines = false +ij_xml_keep_line_breaks = true +ij_xml_keep_line_breaks_in_text = true +ij_xml_keep_whitespaces = false +ij_xml_keep_whitespaces_around_cdata = preserve +ij_xml_keep_whitespaces_inside_cdata = false +ij_xml_line_comment_at_first_column = true +ij_xml_space_after_tag_name = false +ij_xml_space_around_equals_in_attribute = false +ij_xml_space_inside_empty_tag = false +ij_xml_text_wrap = normal +ij_xml_use_custom_settings = true + +[{*.ats,*.cts,*.mts,*.ts}] +ij_typescript_align_imports = false +ij_typescript_align_multiline_array_initializer_expression = false +ij_typescript_align_multiline_binary_operation = false +ij_typescript_align_multiline_chained_methods = false +ij_typescript_align_multiline_extends_list = false +ij_typescript_align_multiline_for = true +ij_typescript_align_multiline_parameters = true +ij_typescript_align_multiline_parameters_in_calls = false +ij_typescript_align_multiline_ternary_operation = false +ij_typescript_align_object_properties = 0 +ij_typescript_align_union_types = false +ij_typescript_align_var_statements = 0 +ij_typescript_array_initializer_new_line_after_left_brace = false +ij_typescript_array_initializer_right_brace_on_new_line = false +ij_typescript_array_initializer_wrap = off +ij_typescript_assignment_wrap = off +ij_typescript_binary_operation_sign_on_next_line = false +ij_typescript_binary_operation_wrap = off +ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/** +ij_typescript_blank_lines_after_imports = 1 +ij_typescript_blank_lines_around_class = 1 +ij_typescript_blank_lines_around_field = 0 +ij_typescript_blank_lines_around_field_in_interface = 0 +ij_typescript_blank_lines_around_function = 1 +ij_typescript_blank_lines_around_method = 1 +ij_typescript_blank_lines_around_method_in_interface = 1 +ij_typescript_block_brace_style = end_of_line +ij_typescript_block_comment_add_space = false +ij_typescript_block_comment_at_first_column = true +ij_typescript_call_parameters_new_line_after_left_paren = false +ij_typescript_call_parameters_right_paren_on_new_line = false +ij_typescript_call_parameters_wrap = off +ij_typescript_catch_on_new_line = false +ij_typescript_chained_call_dot_on_new_line = true +ij_typescript_class_brace_style = end_of_line +ij_typescript_comma_on_new_line = false +ij_typescript_do_while_brace_force = never +ij_typescript_else_on_new_line = false +ij_typescript_enforce_trailing_comma = keep +ij_typescript_enum_constants_wrap = on_every_item +ij_typescript_extends_keyword_wrap = off +ij_typescript_extends_list_wrap = off +ij_typescript_field_prefix = _ +ij_typescript_file_name_style = relaxed +ij_typescript_finally_on_new_line = false +ij_typescript_for_brace_force = never +ij_typescript_for_statement_new_line_after_left_paren = false +ij_typescript_for_statement_right_paren_on_new_line = false +ij_typescript_for_statement_wrap = off +ij_typescript_force_quote_style = false +ij_typescript_force_semicolon_style = false +ij_typescript_function_expression_brace_style = end_of_line +ij_typescript_if_brace_force = never +ij_typescript_import_merge_members = global +ij_typescript_import_prefer_absolute_path = global +ij_typescript_import_sort_members = true +ij_typescript_import_sort_module_name = false +ij_typescript_import_use_node_resolution = true +ij_typescript_imports_wrap = on_every_item +ij_typescript_indent_case_from_switch = true +ij_typescript_indent_chained_calls = false +ij_typescript_indent_package_children = 0 +ij_typescript_jsdoc_include_types = false +ij_typescript_jsx_attribute_value = braces +ij_typescript_keep_blank_lines_in_code = 2 +ij_typescript_keep_first_column_comment = true +ij_typescript_keep_indents_on_empty_lines = false +ij_typescript_keep_line_breaks = true +ij_typescript_keep_simple_blocks_in_one_line = false +ij_typescript_keep_simple_methods_in_one_line = false +ij_typescript_line_comment_add_space = true +ij_typescript_line_comment_at_first_column = false +ij_typescript_method_brace_style = end_of_line +ij_typescript_method_call_chain_wrap = off +ij_typescript_method_parameters_new_line_after_left_paren = false +ij_typescript_method_parameters_right_paren_on_new_line = false +ij_typescript_method_parameters_wrap = off +ij_typescript_object_literal_wrap = on_every_item +ij_typescript_object_types_wrap = on_every_item +ij_typescript_parentheses_expression_new_line_after_left_paren = false +ij_typescript_parentheses_expression_right_paren_on_new_line = false +ij_typescript_place_assignment_sign_on_next_line = false +ij_typescript_prefer_as_type_cast = false +ij_typescript_prefer_explicit_types_function_expression_returns = false +ij_typescript_prefer_explicit_types_function_returns = false +ij_typescript_prefer_explicit_types_vars_fields = false +ij_typescript_prefer_parameters_wrap = false +ij_typescript_property_prefix = +ij_typescript_reformat_c_style_comments = false +ij_typescript_space_after_colon = true +ij_typescript_space_after_comma = true +ij_typescript_space_after_dots_in_rest_parameter = false +ij_typescript_space_after_generator_mult = true +ij_typescript_space_after_property_colon = true +ij_typescript_space_after_quest = true +ij_typescript_space_after_type_colon = true +ij_typescript_space_after_unary_not = false +ij_typescript_space_before_async_arrow_lparen = true +ij_typescript_space_before_catch_keyword = true +ij_typescript_space_before_catch_left_brace = true +ij_typescript_space_before_catch_parentheses = true +ij_typescript_space_before_class_lbrace = true +ij_typescript_space_before_class_left_brace = true +ij_typescript_space_before_colon = true +ij_typescript_space_before_comma = false +ij_typescript_space_before_do_left_brace = true +ij_typescript_space_before_else_keyword = true +ij_typescript_space_before_else_left_brace = true +ij_typescript_space_before_finally_keyword = true +ij_typescript_space_before_finally_left_brace = true +ij_typescript_space_before_for_left_brace = true +ij_typescript_space_before_for_parentheses = true +ij_typescript_space_before_for_semicolon = false +ij_typescript_space_before_function_left_parenth = true +ij_typescript_space_before_generator_mult = false +ij_typescript_space_before_if_left_brace = true +ij_typescript_space_before_if_parentheses = true +ij_typescript_space_before_method_call_parentheses = false +ij_typescript_space_before_method_left_brace = true +ij_typescript_space_before_method_parentheses = false +ij_typescript_space_before_property_colon = false +ij_typescript_space_before_quest = true +ij_typescript_space_before_switch_left_brace = true +ij_typescript_space_before_switch_parentheses = true +ij_typescript_space_before_try_left_brace = true +ij_typescript_space_before_type_colon = false +ij_typescript_space_before_unary_not = false +ij_typescript_space_before_while_keyword = true +ij_typescript_space_before_while_left_brace = true +ij_typescript_space_before_while_parentheses = true +ij_typescript_spaces_around_additive_operators = true +ij_typescript_spaces_around_arrow_function_operator = true +ij_typescript_spaces_around_assignment_operators = true +ij_typescript_spaces_around_bitwise_operators = true +ij_typescript_spaces_around_equality_operators = true +ij_typescript_spaces_around_logical_operators = true +ij_typescript_spaces_around_multiplicative_operators = true +ij_typescript_spaces_around_relational_operators = true +ij_typescript_spaces_around_shift_operators = true +ij_typescript_spaces_around_unary_operator = false +ij_typescript_spaces_within_array_initializer_brackets = false +ij_typescript_spaces_within_brackets = false +ij_typescript_spaces_within_catch_parentheses = false +ij_typescript_spaces_within_for_parentheses = false +ij_typescript_spaces_within_if_parentheses = false +ij_typescript_spaces_within_imports = false +ij_typescript_spaces_within_interpolation_expressions = false +ij_typescript_spaces_within_method_call_parentheses = false +ij_typescript_spaces_within_method_parentheses = false +ij_typescript_spaces_within_object_literal_braces = false +ij_typescript_spaces_within_object_type_braces = true +ij_typescript_spaces_within_parentheses = false +ij_typescript_spaces_within_switch_parentheses = false +ij_typescript_spaces_within_type_assertion = false +ij_typescript_spaces_within_union_types = true +ij_typescript_spaces_within_while_parentheses = false +ij_typescript_special_else_if_treatment = true +ij_typescript_ternary_operation_signs_on_next_line = false +ij_typescript_ternary_operation_wrap = off +ij_typescript_union_types_wrap = on_every_item +ij_typescript_use_chained_calls_group_indents = false +ij_typescript_use_double_quotes = true +ij_typescript_use_explicit_js_extension = auto +ij_typescript_use_path_mapping = always +ij_typescript_use_public_modifier = false +ij_typescript_use_semicolon_after_statement = true +ij_typescript_var_declaration_wrap = normal +ij_typescript_while_brace_force = never +ij_typescript_while_on_new_line = false +ij_typescript_wrap_comments = false + +[{*.bash,*.sh,*.zsh}] +ij_shell_binary_ops_start_line = false +ij_shell_keep_column_alignment_padding = false +ij_shell_minify_program = false +ij_shell_redirect_followed_by_space = false +ij_shell_switch_cases_indented = false +ij_shell_use_unix_line_separator = true + +[{*.cjs,*.js}] +max_line_length = 80 +ij_javascript_align_imports = false +ij_javascript_align_multiline_array_initializer_expression = false +ij_javascript_align_multiline_binary_operation = false +ij_javascript_align_multiline_chained_methods = false +ij_javascript_align_multiline_extends_list = false +ij_javascript_align_multiline_for = false +ij_javascript_align_multiline_parameters = false +ij_javascript_align_multiline_parameters_in_calls = false +ij_javascript_align_multiline_ternary_operation = false +ij_javascript_align_object_properties = 0 +ij_javascript_align_union_types = false +ij_javascript_align_var_statements = 0 +ij_javascript_array_initializer_new_line_after_left_brace = false +ij_javascript_array_initializer_right_brace_on_new_line = false +ij_javascript_array_initializer_wrap = normal +ij_javascript_assignment_wrap = off +ij_javascript_binary_operation_sign_on_next_line = true +ij_javascript_binary_operation_wrap = normal +ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/** +ij_javascript_blank_lines_after_imports = 1 +ij_javascript_blank_lines_around_class = 1 +ij_javascript_blank_lines_around_field = 0 +ij_javascript_blank_lines_around_function = 1 +ij_javascript_blank_lines_around_method = 1 +ij_javascript_block_brace_style = end_of_line +ij_javascript_block_comment_add_space = false +ij_javascript_block_comment_at_first_column = true +ij_javascript_call_parameters_new_line_after_left_paren = false +ij_javascript_call_parameters_right_paren_on_new_line = false +ij_javascript_call_parameters_wrap = normal +ij_javascript_catch_on_new_line = false +ij_javascript_chained_call_dot_on_new_line = true +ij_javascript_class_brace_style = end_of_line +ij_javascript_comma_on_new_line = false +ij_javascript_do_while_brace_force = always +ij_javascript_else_on_new_line = false +ij_javascript_enforce_trailing_comma = keep +ij_javascript_extends_keyword_wrap = off +ij_javascript_extends_list_wrap = off +ij_javascript_field_prefix = _ +ij_javascript_file_name_style = relaxed +ij_javascript_finally_on_new_line = false +ij_javascript_for_brace_force = always +ij_javascript_for_statement_new_line_after_left_paren = false +ij_javascript_for_statement_right_paren_on_new_line = false +ij_javascript_for_statement_wrap = normal +ij_javascript_force_quote_style = false +ij_javascript_force_semicolon_style = false +ij_javascript_function_expression_brace_style = end_of_line +ij_javascript_if_brace_force = always +ij_javascript_import_merge_members = global +ij_javascript_import_prefer_absolute_path = global +ij_javascript_import_sort_members = true +ij_javascript_import_sort_module_name = false +ij_javascript_import_use_node_resolution = true +ij_javascript_imports_wrap = on_every_item +ij_javascript_indent_case_from_switch = true +ij_javascript_indent_chained_calls = false +ij_javascript_indent_package_children = 0 +ij_javascript_jsx_attribute_value = braces +ij_javascript_keep_blank_lines_in_code = 1 +ij_javascript_keep_first_column_comment = true +ij_javascript_keep_indents_on_empty_lines = false +ij_javascript_keep_line_breaks = true +ij_javascript_keep_simple_blocks_in_one_line = false +ij_javascript_keep_simple_methods_in_one_line = false +ij_javascript_line_comment_add_space = true +ij_javascript_line_comment_at_first_column = false +ij_javascript_method_brace_style = end_of_line +ij_javascript_method_call_chain_wrap = off +ij_javascript_method_parameters_new_line_after_left_paren = false +ij_javascript_method_parameters_right_paren_on_new_line = false +ij_javascript_method_parameters_wrap = normal +ij_javascript_object_literal_wrap = on_every_item +ij_javascript_object_types_wrap = on_every_item +ij_javascript_parentheses_expression_new_line_after_left_paren = false +ij_javascript_parentheses_expression_right_paren_on_new_line = false +ij_javascript_place_assignment_sign_on_next_line = false +ij_javascript_prefer_as_type_cast = false +ij_javascript_prefer_explicit_types_function_expression_returns = false +ij_javascript_prefer_explicit_types_function_returns = false +ij_javascript_prefer_explicit_types_vars_fields = false +ij_javascript_prefer_parameters_wrap = false +ij_javascript_property_prefix = +ij_javascript_reformat_c_style_comments = false +ij_javascript_space_after_colon = true +ij_javascript_space_after_comma = true +ij_javascript_space_after_dots_in_rest_parameter = false +ij_javascript_space_after_generator_mult = true +ij_javascript_space_after_property_colon = true +ij_javascript_space_after_quest = true +ij_javascript_space_after_type_colon = true +ij_javascript_space_after_unary_not = false +ij_javascript_space_before_async_arrow_lparen = true +ij_javascript_space_before_catch_keyword = true +ij_javascript_space_before_catch_left_brace = true +ij_javascript_space_before_catch_parentheses = true +ij_javascript_space_before_class_lbrace = true +ij_javascript_space_before_class_left_brace = true +ij_javascript_space_before_colon = true +ij_javascript_space_before_comma = false +ij_javascript_space_before_do_left_brace = true +ij_javascript_space_before_else_keyword = true +ij_javascript_space_before_else_left_brace = true +ij_javascript_space_before_finally_keyword = true +ij_javascript_space_before_finally_left_brace = true +ij_javascript_space_before_for_left_brace = true +ij_javascript_space_before_for_parentheses = true +ij_javascript_space_before_for_semicolon = false +ij_javascript_space_before_function_left_parenth = true +ij_javascript_space_before_generator_mult = false +ij_javascript_space_before_if_left_brace = true +ij_javascript_space_before_if_parentheses = true +ij_javascript_space_before_method_call_parentheses = false +ij_javascript_space_before_method_left_brace = true +ij_javascript_space_before_method_parentheses = false +ij_javascript_space_before_property_colon = false +ij_javascript_space_before_quest = true +ij_javascript_space_before_switch_left_brace = true +ij_javascript_space_before_switch_parentheses = true +ij_javascript_space_before_try_left_brace = true +ij_javascript_space_before_type_colon = false +ij_javascript_space_before_unary_not = false +ij_javascript_space_before_while_keyword = true +ij_javascript_space_before_while_left_brace = true +ij_javascript_space_before_while_parentheses = true +ij_javascript_spaces_around_additive_operators = true +ij_javascript_spaces_around_arrow_function_operator = true +ij_javascript_spaces_around_assignment_operators = true +ij_javascript_spaces_around_bitwise_operators = true +ij_javascript_spaces_around_equality_operators = true +ij_javascript_spaces_around_logical_operators = true +ij_javascript_spaces_around_multiplicative_operators = true +ij_javascript_spaces_around_relational_operators = true +ij_javascript_spaces_around_shift_operators = true +ij_javascript_spaces_around_unary_operator = false +ij_javascript_spaces_within_array_initializer_brackets = false +ij_javascript_spaces_within_brackets = false +ij_javascript_spaces_within_catch_parentheses = false +ij_javascript_spaces_within_for_parentheses = false +ij_javascript_spaces_within_if_parentheses = false +ij_javascript_spaces_within_imports = false +ij_javascript_spaces_within_interpolation_expressions = false +ij_javascript_spaces_within_method_call_parentheses = false +ij_javascript_spaces_within_method_parentheses = false +ij_javascript_spaces_within_object_literal_braces = false +ij_javascript_spaces_within_object_type_braces = true +ij_javascript_spaces_within_parentheses = false +ij_javascript_spaces_within_switch_parentheses = false +ij_javascript_spaces_within_type_assertion = false +ij_javascript_spaces_within_union_types = true +ij_javascript_spaces_within_while_parentheses = false +ij_javascript_special_else_if_treatment = true +ij_javascript_ternary_operation_signs_on_next_line = true +ij_javascript_ternary_operation_wrap = normal +ij_javascript_union_types_wrap = on_every_item +ij_javascript_use_chained_calls_group_indents = false +ij_javascript_use_double_quotes = true +ij_javascript_use_explicit_js_extension = auto +ij_javascript_use_path_mapping = always +ij_javascript_use_public_modifier = false +ij_javascript_use_semicolon_after_statement = true +ij_javascript_var_declaration_wrap = normal +ij_javascript_while_brace_force = always +ij_javascript_while_on_new_line = false +ij_javascript_wrap_comments = false + +[{*.gant,*.groovy,*.gy}] +indent_size = 4 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_groovy_align_group_field_declarations = false +ij_groovy_align_multiline_array_initializer_expression = false +ij_groovy_align_multiline_assignment = false +ij_groovy_align_multiline_binary_operation = false +ij_groovy_align_multiline_chained_methods = false +ij_groovy_align_multiline_extends_list = false +ij_groovy_align_multiline_for = true +ij_groovy_align_multiline_list_or_map = true +ij_groovy_align_multiline_method_parentheses = false +ij_groovy_align_multiline_parameters = true +ij_groovy_align_multiline_parameters_in_calls = false +ij_groovy_align_multiline_resources = true +ij_groovy_align_multiline_ternary_operation = false +ij_groovy_align_multiline_throws_list = false +ij_groovy_align_named_args_in_map = true +ij_groovy_align_throws_keyword = false +ij_groovy_array_initializer_new_line_after_left_brace = false +ij_groovy_array_initializer_right_brace_on_new_line = false +ij_groovy_array_initializer_wrap = off +ij_groovy_assert_statement_wrap = off +ij_groovy_assignment_wrap = off +ij_groovy_binary_operation_wrap = off +ij_groovy_blank_lines_after_class_header = 0 +ij_groovy_blank_lines_after_imports = 1 +ij_groovy_blank_lines_after_package = 1 +ij_groovy_blank_lines_around_class = 1 +ij_groovy_blank_lines_around_field = 0 +ij_groovy_blank_lines_around_field_in_interface = 0 +ij_groovy_blank_lines_around_method = 1 +ij_groovy_blank_lines_around_method_in_interface = 1 +ij_groovy_blank_lines_before_imports = 1 +ij_groovy_blank_lines_before_method_body = 0 +ij_groovy_blank_lines_before_package = 0 +ij_groovy_block_brace_style = end_of_line +ij_groovy_block_comment_add_space = false +ij_groovy_block_comment_at_first_column = true +ij_groovy_call_parameters_new_line_after_left_paren = false +ij_groovy_call_parameters_right_paren_on_new_line = false +ij_groovy_call_parameters_wrap = off +ij_groovy_catch_on_new_line = false +ij_groovy_class_annotation_wrap = split_into_lines +ij_groovy_class_brace_style = end_of_line +ij_groovy_class_count_to_use_import_on_demand = 5 +ij_groovy_do_while_brace_force = never +ij_groovy_else_on_new_line = false +ij_groovy_enable_groovydoc_formatting = true +ij_groovy_enum_constants_wrap = off +ij_groovy_extends_keyword_wrap = off +ij_groovy_extends_list_wrap = off +ij_groovy_field_annotation_wrap = split_into_lines +ij_groovy_finally_on_new_line = false +ij_groovy_for_brace_force = never +ij_groovy_for_statement_new_line_after_left_paren = false +ij_groovy_for_statement_right_paren_on_new_line = false +ij_groovy_for_statement_wrap = off +ij_groovy_ginq_general_clause_wrap_policy = 2 +ij_groovy_ginq_having_wrap_policy = 1 +ij_groovy_ginq_indent_having_clause = true +ij_groovy_ginq_indent_on_clause = true +ij_groovy_ginq_on_wrap_policy = 1 +ij_groovy_ginq_space_after_keyword = true +ij_groovy_if_brace_force = never +ij_groovy_import_annotation_wrap = 2 +ij_groovy_imports_layout = *,|,javax.**,java.**,|,$* +ij_groovy_indent_case_from_switch = true +ij_groovy_indent_label_blocks = true +ij_groovy_insert_inner_class_imports = false +ij_groovy_keep_blank_lines_before_right_brace = 2 +ij_groovy_keep_blank_lines_in_code = 2 +ij_groovy_keep_blank_lines_in_declarations = 2 +ij_groovy_keep_control_statement_in_one_line = true +ij_groovy_keep_first_column_comment = true +ij_groovy_keep_indents_on_empty_lines = false +ij_groovy_keep_line_breaks = true +ij_groovy_keep_multiple_expressions_in_one_line = false +ij_groovy_keep_simple_blocks_in_one_line = false +ij_groovy_keep_simple_classes_in_one_line = true +ij_groovy_keep_simple_lambdas_in_one_line = true +ij_groovy_keep_simple_methods_in_one_line = true +ij_groovy_label_indent_absolute = false +ij_groovy_label_indent_size = 0 +ij_groovy_lambda_brace_style = end_of_line +ij_groovy_layout_static_imports_separately = true +ij_groovy_line_comment_add_space = false +ij_groovy_line_comment_add_space_on_reformat = false +ij_groovy_line_comment_at_first_column = true +ij_groovy_method_annotation_wrap = split_into_lines +ij_groovy_method_brace_style = end_of_line +ij_groovy_method_call_chain_wrap = off +ij_groovy_method_parameters_new_line_after_left_paren = false +ij_groovy_method_parameters_right_paren_on_new_line = false +ij_groovy_method_parameters_wrap = off +ij_groovy_modifier_list_wrap = false +ij_groovy_names_count_to_use_import_on_demand = 3 +ij_groovy_packages_to_use_import_on_demand = java.awt.*,javax.swing.* +ij_groovy_parameter_annotation_wrap = off +ij_groovy_parentheses_expression_new_line_after_left_paren = false +ij_groovy_parentheses_expression_right_paren_on_new_line = false +ij_groovy_prefer_parameters_wrap = false +ij_groovy_resource_list_new_line_after_left_paren = false +ij_groovy_resource_list_right_paren_on_new_line = false +ij_groovy_resource_list_wrap = off +ij_groovy_space_after_assert_separator = true +ij_groovy_space_after_colon = true +ij_groovy_space_after_comma = true +ij_groovy_space_after_comma_in_type_arguments = true +ij_groovy_space_after_for_semicolon = true +ij_groovy_space_after_quest = true +ij_groovy_space_after_type_cast = true +ij_groovy_space_before_annotation_parameter_list = false +ij_groovy_space_before_array_initializer_left_brace = false +ij_groovy_space_before_assert_separator = false +ij_groovy_space_before_catch_keyword = true +ij_groovy_space_before_catch_left_brace = true +ij_groovy_space_before_catch_parentheses = true +ij_groovy_space_before_class_left_brace = true +ij_groovy_space_before_closure_left_brace = true +ij_groovy_space_before_colon = true +ij_groovy_space_before_comma = false +ij_groovy_space_before_do_left_brace = true +ij_groovy_space_before_else_keyword = true +ij_groovy_space_before_else_left_brace = true +ij_groovy_space_before_finally_keyword = true +ij_groovy_space_before_finally_left_brace = true +ij_groovy_space_before_for_left_brace = true +ij_groovy_space_before_for_parentheses = true +ij_groovy_space_before_for_semicolon = false +ij_groovy_space_before_if_left_brace = true +ij_groovy_space_before_if_parentheses = true +ij_groovy_space_before_method_call_parentheses = false +ij_groovy_space_before_method_left_brace = true +ij_groovy_space_before_method_parentheses = false +ij_groovy_space_before_quest = true +ij_groovy_space_before_record_parentheses = false +ij_groovy_space_before_switch_left_brace = true +ij_groovy_space_before_switch_parentheses = true +ij_groovy_space_before_synchronized_left_brace = true +ij_groovy_space_before_synchronized_parentheses = true +ij_groovy_space_before_try_left_brace = true +ij_groovy_space_before_try_parentheses = true +ij_groovy_space_before_while_keyword = true +ij_groovy_space_before_while_left_brace = true +ij_groovy_space_before_while_parentheses = true +ij_groovy_space_in_named_argument = true +ij_groovy_space_in_named_argument_before_colon = false +ij_groovy_space_within_empty_array_initializer_braces = false +ij_groovy_space_within_empty_method_call_parentheses = false +ij_groovy_spaces_around_additive_operators = true +ij_groovy_spaces_around_assignment_operators = true +ij_groovy_spaces_around_bitwise_operators = true +ij_groovy_spaces_around_equality_operators = true +ij_groovy_spaces_around_lambda_arrow = true +ij_groovy_spaces_around_logical_operators = true +ij_groovy_spaces_around_multiplicative_operators = true +ij_groovy_spaces_around_regex_operators = true +ij_groovy_spaces_around_relational_operators = true +ij_groovy_spaces_around_shift_operators = true +ij_groovy_spaces_within_annotation_parentheses = false +ij_groovy_spaces_within_array_initializer_braces = false +ij_groovy_spaces_within_braces = true +ij_groovy_spaces_within_brackets = false +ij_groovy_spaces_within_cast_parentheses = false +ij_groovy_spaces_within_catch_parentheses = false +ij_groovy_spaces_within_for_parentheses = false +ij_groovy_spaces_within_gstring_injection_braces = false +ij_groovy_spaces_within_if_parentheses = false +ij_groovy_spaces_within_list_or_map = false +ij_groovy_spaces_within_method_call_parentheses = false +ij_groovy_spaces_within_method_parentheses = false +ij_groovy_spaces_within_parentheses = false +ij_groovy_spaces_within_switch_parentheses = false +ij_groovy_spaces_within_synchronized_parentheses = false +ij_groovy_spaces_within_try_parentheses = false +ij_groovy_spaces_within_tuple_expression = false +ij_groovy_spaces_within_while_parentheses = false +ij_groovy_special_else_if_treatment = true +ij_groovy_ternary_operation_wrap = off +ij_groovy_throws_keyword_wrap = off +ij_groovy_throws_list_wrap = off +ij_groovy_use_flying_geese_braces = false +ij_groovy_use_fq_class_names = false +ij_groovy_use_fq_class_names_in_javadoc = true +ij_groovy_use_relative_indents = false +ij_groovy_use_single_class_imports = true +ij_groovy_variable_annotation_wrap = off +ij_groovy_while_brace_force = never +ij_groovy_while_on_new_line = false +ij_groovy_wrap_chain_calls_after_dot = false +ij_groovy_wrap_long_lines = false + +[{*.gradle.kts,*.kt,*.kts,*.main.kts,*.space.kts}] +indent_size = 4 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_kotlin_align_in_columns_case_branch = false +ij_kotlin_align_multiline_binary_operation = false +ij_kotlin_align_multiline_extends_list = false +ij_kotlin_align_multiline_method_parentheses = false +ij_kotlin_align_multiline_parameters = true +ij_kotlin_align_multiline_parameters_in_calls = false +ij_kotlin_allow_trailing_comma = false +ij_kotlin_allow_trailing_comma_on_call_site = false +ij_kotlin_assignment_wrap = off +ij_kotlin_blank_lines_after_class_header = 0 +ij_kotlin_blank_lines_around_block_when_branches = 0 +ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1 +ij_kotlin_block_comment_add_space = false +ij_kotlin_block_comment_at_first_column = true +ij_kotlin_call_parameters_new_line_after_left_paren = false +ij_kotlin_call_parameters_right_paren_on_new_line = false +ij_kotlin_call_parameters_wrap = off +ij_kotlin_catch_on_new_line = false +ij_kotlin_class_annotation_wrap = split_into_lines +ij_kotlin_continuation_indent_for_chained_calls = true +ij_kotlin_continuation_indent_for_expression_bodies = true +ij_kotlin_continuation_indent_in_argument_lists = true +ij_kotlin_continuation_indent_in_elvis = true +ij_kotlin_continuation_indent_in_if_conditions = true +ij_kotlin_continuation_indent_in_parameter_lists = true +ij_kotlin_continuation_indent_in_supertype_lists = true +ij_kotlin_else_on_new_line = false +ij_kotlin_enum_constants_wrap = off +ij_kotlin_extends_list_wrap = off +ij_kotlin_field_annotation_wrap = split_into_lines +ij_kotlin_finally_on_new_line = false +ij_kotlin_if_rparen_on_new_line = false +ij_kotlin_import_nested_classes = false +ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^ +ij_kotlin_insert_whitespaces_in_simple_one_line_method = true +ij_kotlin_keep_blank_lines_before_right_brace = 2 +ij_kotlin_keep_blank_lines_in_code = 2 +ij_kotlin_keep_blank_lines_in_declarations = 2 +ij_kotlin_keep_first_column_comment = true +ij_kotlin_keep_indents_on_empty_lines = false +ij_kotlin_keep_line_breaks = true +ij_kotlin_lbrace_on_next_line = false +ij_kotlin_line_break_after_multiline_when_entry = true +ij_kotlin_line_comment_add_space = false +ij_kotlin_line_comment_add_space_on_reformat = false +ij_kotlin_line_comment_at_first_column = true +ij_kotlin_method_annotation_wrap = split_into_lines +ij_kotlin_method_call_chain_wrap = off +ij_kotlin_method_parameters_new_line_after_left_paren = false +ij_kotlin_method_parameters_right_paren_on_new_line = false +ij_kotlin_method_parameters_wrap = off +ij_kotlin_name_count_to_use_star_import = 5 +ij_kotlin_name_count_to_use_star_import_for_members = 3 +ij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlinx.android.synthetic.**,io.ktor.** +ij_kotlin_parameter_annotation_wrap = off +ij_kotlin_space_after_comma = true +ij_kotlin_space_after_extend_colon = true +ij_kotlin_space_after_type_colon = true +ij_kotlin_space_before_catch_parentheses = true +ij_kotlin_space_before_comma = false +ij_kotlin_space_before_extend_colon = true +ij_kotlin_space_before_for_parentheses = true +ij_kotlin_space_before_if_parentheses = true +ij_kotlin_space_before_lambda_arrow = true +ij_kotlin_space_before_type_colon = false +ij_kotlin_space_before_when_parentheses = true +ij_kotlin_space_before_while_parentheses = true +ij_kotlin_spaces_around_additive_operators = true +ij_kotlin_spaces_around_assignment_operators = true +ij_kotlin_spaces_around_equality_operators = true +ij_kotlin_spaces_around_function_type_arrow = true +ij_kotlin_spaces_around_logical_operators = true +ij_kotlin_spaces_around_multiplicative_operators = true +ij_kotlin_spaces_around_range = false +ij_kotlin_spaces_around_relational_operators = true +ij_kotlin_spaces_around_unary_operator = false +ij_kotlin_spaces_around_when_arrow = true +ij_kotlin_variable_annotation_wrap = off +ij_kotlin_while_on_new_line = false +ij_kotlin_wrap_elvis_expressions = 1 +ij_kotlin_wrap_expression_body_functions = 0 +ij_kotlin_wrap_first_method_in_call_chain = false + +[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}] +ij_json_array_wrapping = split_into_lines +ij_json_keep_blank_lines_in_code = 0 +ij_json_keep_indents_on_empty_lines = false +ij_json_keep_line_breaks = true +ij_json_keep_trailing_comma = false +ij_json_object_wrapping = split_into_lines +ij_json_property_alignment = do_not_align +ij_json_space_after_colon = true +ij_json_space_after_comma = true +ij_json_space_before_colon = false +ij_json_space_before_comma = false +ij_json_spaces_within_braces = false +ij_json_spaces_within_brackets = false +ij_json_wrap_long_lines = false + +[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}] +ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3 +ij_html_align_attributes = true +ij_html_align_text = false +ij_html_attribute_wrap = normal +ij_html_block_comment_add_space = false +ij_html_block_comment_at_first_column = true +ij_html_do_not_align_children_of_min_lines = 0 +ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p +ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot +ij_html_enforce_quotes = false +ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var +ij_html_keep_blank_lines = 2 +ij_html_keep_indents_on_empty_lines = false +ij_html_keep_line_breaks = true +ij_html_keep_line_breaks_in_text = true +ij_html_keep_whitespaces = false +ij_html_keep_whitespaces_inside = span,pre,textarea +ij_html_line_comment_at_first_column = true +ij_html_new_line_after_last_attribute = never +ij_html_new_line_before_first_attribute = never +ij_html_quote_style = double +ij_html_remove_new_line_before_tags = br +ij_html_space_after_tag_name = false +ij_html_space_around_equality_in_attribute = false +ij_html_space_inside_empty_tag = false +ij_html_text_wrap = normal + +[{*.http,*.rest}] +indent_size = 0 +ij_http-request_call_parameters_wrap = normal +ij_http-request_method_parameters_wrap = split_into_lines +ij_http-request_space_before_comma = true +ij_http-request_spaces_around_assignment_operators = true + +[{*.jsf,*.jsp,*.jspf,*.tag,*.tagf,*.xjsp}] +indent_size = 4 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_jsp_jsp_prefer_comma_separated_import_list = false +ij_jsp_keep_indents_on_empty_lines = false + +[{*.jspx,*.tagx}] +indent_size = 4 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_jspx_keep_indents_on_empty_lines = false + +[{*.pb,*.textproto}] +ij_prototext_keep_blank_lines_in_code = 2 +ij_prototext_keep_indents_on_empty_lines = false +ij_prototext_keep_line_breaks = true +ij_prototext_space_after_colon = true +ij_prototext_space_after_comma = true +ij_prototext_space_before_colon = false +ij_prototext_space_before_comma = false +ij_prototext_spaces_within_braces = true +ij_prototext_spaces_within_brackets = false + +[{*.properties,spring.handlers,spring.schemas}] +ij_properties_align_group_field_declarations = false +ij_properties_keep_blank_lines = false +ij_properties_key_value_delimiter = equals +ij_properties_spaces_around_key_value_delimiter = false + +[{*.qute.htm,*.qute.html,*.qute.json,*.qute.txt,*.qute.yaml,*.qute.yml}] +indent_size = 4 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_qute_keep_indents_on_empty_lines = false + +[{*.toml,Cargo.lock,Cargo.toml.orig,Gopkg.lock,Pipfile,poetry.lock}] +indent_size = 4 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_toml_keep_indents_on_empty_lines = false + +[{*.yaml,*.yml}] +ij_yaml_align_values_properties = do_not_align +ij_yaml_autoinsert_sequence_marker = true +ij_yaml_block_mapping_on_new_line = false +ij_yaml_indent_sequence_value = true +ij_yaml_keep_indents_on_empty_lines = false +ij_yaml_keep_line_breaks = true +ij_yaml_sequence_on_new_line = false +ij_yaml_space_before_colon = false +ij_yaml_spaces_within_braces = true +ij_yaml_spaces_within_brackets = true diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..e3d7801 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,68 @@ +name: Bug report +description: Create a report to help me improve +labels: + - bug +assignees: [ "vitalijr2" ] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + **Before opening a new issue**, make sure to search for keywords in the issues + filtered by the "bug" label: + + * https://github.com/vitalijr2/aws-lambda-slf4j/issues?q=is%3Aissue+label%3Abug+ + + and verify the issue you're about to submit isn't a duplicate. + - type: input + id: summary + validations: + required: true + attributes: + label: Summary + description: A clear and concise description of what the bug is. + - type: textarea + id: what-happened + validations: + required: true + attributes: + label: What is the current bug behavior? + description: Describe what actually happens. + placeholder: Tell us what you do and what you see! + - type: textarea + id: steps + attributes: + label: Steps to reproduce + value: | + 1. ... + 2. ... + 3. ... + ... + - type: textarea + id: expected + validations: + required: true + attributes: + label: What is the expected correct behavior? + description: Describe what you should see instead. + placeholder: Tell us what you expected to get! + - type: textarea + id: misc + attributes: + label: Additional context + description: Add any other context about the problem here. + - type: textarea + id: fixes + attributes: + label: Possible fixes + description: If you can, link to the line of code that might be responsible for the problem. + - type: markdown + attributes: + value: | + Paste any relevant logs - please use code blocks (```) + to format console output, logs, and code as it's tough + to read otherwise. + + **Do not attach ZIP files** of your code or compiled projects - instead, + please publish your code to a public GitHub repo & post a link to it. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..ae2c04d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,44 @@ +name: Feature request +description: Suggest an idea for this project +labels: + - enhancement +assignees: [ "vitalijr2" ] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this feature request! + + **Before opening a new issue**, make sure to search for keywords in the issues + filtered by the "enhancement" and "suggestion" labels: + + * https://github.com/vitalijr2/aws-lambda-slf4j/issues?q=is%3Aissue+label%3Aenhancement+ + * https://github.com/vitalijr2/aws-lambda-slf4j/issues?q=is%3Aissue+label%3Asuggestion+ + + and verify the issue you're about to submit isn't a duplicate. + - type: input + id: summary + validations: + required: true + attributes: + label: Summary + description: A clear and concise description of what the bug is. + - type: textarea + id: expected + validations: + required: true + attributes: + label: What is the expected correct behavior? + description: Describe what you should see instead. + placeholder: Tell us what you expected to get! + - type: textarea + id: implementation + attributes: + label: Possible implementations + description: If you can, link to the line of code that might be responsible for the feature. + - type: markdown + attributes: + value: | + Paste any relevant logs - please use code blocks (```) + to format console output, logs, and code as it's tough + to read otherwise. diff --git a/.github/funding.yml b/.github/funding.yml new file mode 100644 index 0000000..1366850 --- /dev/null +++ b/.github/funding.yml @@ -0,0 +1,5 @@ +# These are supported funding model platforms + +ko_fi: vitalij_r2 +liberapay: vitalij_r2 +custom: [ "https://send.monobank.ua/jar/9r5bd6ejUC?f=enabled&t=aws-lambda-slf4j", "https://buymeacoffee.com/vitalij_r2" ] diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..fe7cb54 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,40 @@ +name: "CodeQL" + +on: + push: + branches: [ "**" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "**" ] + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Setup Java JDK + uses: actions/setup-java@v4 + with: + distribution: 'corretto' + java-version: 11 + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..35fb6ac --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +/public/ +target/ +.flattened-pom.xml + +*~ +### IntelliJ IDEA ### +.idea/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..d6c9350 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,12 @@ +{ + "line-length": { + "headings": false, + "line_length": 80, + "code_blocks": false, + "tables": false + }, + "no-duplicate-heading": { + "siblings_only": true + }, + "required-headings": false +} \ No newline at end of file diff --git a/.mvn/ci_settings.xml b/.mvn/ci_settings.xml new file mode 100644 index 0000000..26d30e8 --- /dev/null +++ b/.mvn/ci_settings.xml @@ -0,0 +1,12 @@ + + + + + central + ${env.SONATYPE_TOKEN_USERNAME} + ${env.SONATYPE_TOKEN_PASSWORD} + + + diff --git a/.mvn/maven.config b/.mvn/maven.config new file mode 100644 index 0000000..d0f3015 --- /dev/null +++ b/.mvn/maven.config @@ -0,0 +1,7 @@ +--fail-at-end +--show-version +-Djava.awt.headless=true +-DinstallAtEnd=true +-DdeployAtEnd=true +-Dhttps.protocols=TLSv1.2 +-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN diff --git a/.mvn/wrapper/.gitignore b/.mvn/wrapper/.gitignore new file mode 100644 index 0000000..e72f5e8 --- /dev/null +++ b/.mvn/wrapper/.gitignore @@ -0,0 +1 @@ +maven-wrapper.jar diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..7e1aec2 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +@SuppressWarnings("PMD.NoPackage") +public final class MavenWrapperDownloader +{ + private static final String WRAPPER_VERSION = "3.2.0"; + + private static final boolean VERBOSE = Boolean.parseBoolean( System.getenv( "MVNW_VERBOSE" ) ); + + public static void main( String[] args ) + { + log( "Apache Maven Wrapper Downloader " + WRAPPER_VERSION ); + + if ( args.length != 2 ) + { + System.err.println( " - ERROR wrapperUrl or wrapperJarPath parameter missing" ); + System.exit( 1 ); + } + + try + { + log( " - Downloader started" ); + final URL wrapperUrl = new URL( args[0] ); + final String jarPath = args[1].replace( "..", "" ); // Sanitize path + final Path wrapperJarPath = Paths.get( jarPath ).toAbsolutePath().normalize(); + downloadFileFromURL( wrapperUrl, wrapperJarPath ); + log( "Done" ); + } + catch ( IOException e ) + { + System.err.println( "- Error downloading: " + e.getMessage() ); + if ( VERBOSE ) + { + e.printStackTrace(); + } + System.exit( 1 ); + } + } + + private static void downloadFileFromURL( URL wrapperUrl, Path wrapperJarPath ) + throws IOException + { + log( " - Downloading to: " + wrapperJarPath ); + if ( System.getenv( "MVNW_USERNAME" ) != null && System.getenv( "MVNW_PASSWORD" ) != null ) + { + final String username = System.getenv( "MVNW_USERNAME" ); + final char[] password = System.getenv( "MVNW_PASSWORD" ).toCharArray(); + Authenticator.setDefault( new Authenticator() + { + @Override + protected PasswordAuthentication getPasswordAuthentication() + { + return new PasswordAuthentication( username, password ); + } + } ); + } + try ( InputStream inStream = wrapperUrl.openStream() ) + { + Files.copy( inStream, wrapperJarPath, StandardCopyOption.REPLACE_EXISTING ); + } + log( " - Downloader complete" ); + } + + private static void log( String msg ) + { + if ( VERBOSE ) + { + System.out.println( msg ); + } + } + +} diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..346d645 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..e6ba8c0 --- /dev/null +++ b/NOTICE @@ -0,0 +1,39 @@ +slf4j-aws-lambda +Copyright 2022-2024 Vitalij Berdinskih + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +This software uses slf4j, see license +------------------------------------------------------------------------ +Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland) +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------ diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..6485606 --- /dev/null +++ b/changelog.md @@ -0,0 +1,140 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +### Changed + +- Update dependencies +- Update project + +## 1.1.0 - 2024-01-16 + +### Changed + +- Update dependencies +- **core:** replace `Util.report` with `Reporter.warn`, was changed in SLF4J 2.0.10 + +## 1.0.2 - 2023-10-16 + +### Changed + +- Update dependencies +- Resolve issue CVE-2023-5072 + +## 1.0.1 - 2023-09-13 + +### Changed + +- Update dependencies, especially SLF4J 2.0.9 +- Update the site: how to set up a provider by a system property + +## 1.0.0 - 2023-04-19 + +### Added + +- The regular provider **slf4j-aws-lambda-logger** who copy + the old library **slf4j-aws-lambda**. +- The JSON output provider **slf4j-aws-lambda-json-logger** who prints JSON + instead plain text. +- Markers are available in output providers: they could be print out + in logs too. + +### Changed + +- There are output providers who print out text or send it to third-party services. + +## 3.1.0 - 2023-03-22 + +## Changed + +- Replace the custom output to stdout with AWS LambdaLogger + +## 3.0.6 - 2023-03-17 + +### Changed + +- Update plugins and dependencies + +## 3.0.5 - 2023-02-11 + +### Changed + +- Downgrade slf4j-api to 2.0.5 because of javadocs + +## 3.0.4 - 2023-02-07 - not published + +### Fixed + +- Update dependencies. +- Properties throws NPE if the lambda-logger.properties is missed + then initialisation fails. + +## 3.0.3 - 2022-09-10 + +- Update dependencies +- Remove all static binders + +## 3.0.2 - 2022-08-22 + +This version is not released, just update documentation. + +- Fix documentation's issue + +## 3.0.1 - 2022-08-22 + +This version is not released, just update documentation. + +- Update the [example](example-lambda) +- Update documentation +- Update dependencies + +## 3.0.0 - 2022-08-21 + +- **Add a module** +- Update dependencies +- Update documentation + +## 2.1.0 - 2022-08-01 + +### Changed + +- Custom level and marker separators +- Update example + +## 2.0.0 - 2022-08-01 + +### Added + +- Support Markers +- Update dependencies +- Update javadocs and site +- Multi-level and multi-marker configuration + +## 1.1.0 - 2022-06-29 + +### Added + +- Name of AWS request ID is configurable + +### Fixed + +- CRLF injection issue #2 + +## 1.0.1 - 2022-05-06 + +### Changed + +- Publish to Maven Central instead of GitLab. + +## 1.0.0 - 2022-05-04 + +### Added + +- Implement a logger. +- Add Javadocs. +- Add the site. diff --git a/contributing.md b/contributing.md new file mode 100644 index 0000000..1d8f611 --- /dev/null +++ b/contributing.md @@ -0,0 +1,25 @@ +# Contributing to SLF4J for AWS Lambda + +**SLF4J for AWS Lambda** is an open-source project and all contributions +are welcome to assist with its development and maintenance. + +## Issues (bug and feature tracker) + +Please report any bugs found, feature requests or other issues on +**SLF4J for AWS Lambda** [GitHub tracker][github-issues]. + +When creating a new issue, +try following [necolas's guidelines][issue-guidelines]. + +## Fork, patch and contribute code + +Feel free to fork **SLF4J for AWS Lambda**'s repository +at [GitHub][bot-github] for your own use and updates. + +Contribute your fixes and new features back to the main codebase using +[GitHub pull requests][github-pull-requests]. + +[github-issues]: https://github.com/vitalijr2/aws-lambda-slf4j/issues +[issue-guidelines]: http://github.com/necolas/issue-guidelines/#readme +[bot-github]: https://github.com/vitalijr2/aws-lambda-slf4j +[github-pull-requests]: https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..b22d270 --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,101 @@ + + + + aws-lambda-slf4j-core + + + + maven-surefire-plugin + org.apache.maven.plugins + + + maven-failsafe-plugin + org.apache.maven.plugins + + + jacoco-maven-plugin + org.jacoco + + + + + + annotations + org.jetbrains + provided + + + aws-lambda-java-core + com.amazonaws + + + slf4j-api + org.slf4j + + + + junit-jupiter-api + org.junit.jupiter + test + + + junit-jupiter-engine + org.junit.jupiter + test + + + junit-jupiter-params + org.junit.jupiter + test + + + mockito-core + org.mockito + test + + + mockito-junit-jupiter + org.mockito + test + + + hamcrest + org.hamcrest + test + + + system-stubs-core + uk.org.webcompere + test + + + system-stubs-jupiter + uk.org.webcompere + test + + + An SLF4J Logger implementation for AWS Lambda, code module + 4.0.0 + SLF4J for AWS Lambda : Core + + aws-lambda-slf4j + io.github.vitalijr2.aws-lambda + 1.1.1 + + diff --git a/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLogger.java b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLogger.java new file mode 100644 index 0000000..ee2213f --- /dev/null +++ b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLogger.java @@ -0,0 +1,427 @@ +/* + * Copyright 2022-2024 Vitalij Berdinskih + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.bot_by.aws_lambda.slf4j; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.VisibleForTesting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; + +/** + * An SLF4J {@link org.slf4j.Logger} implementation for AWS + * Lambda. + *

+ * This is common with SLF4J Simple but supports MDC. You could put AWS request ID to MDC then it is + * printed out in start every log line: + *


+ *   {@literal @}Override
+ *   public String handleRequest({@literal Map} input, Context context) {
+ *     MDC.put("AWS_REQUEST_ID", context.getAwsRequestId());
+ *     ...
+ *     logger.info("info message");
+ *     ...
+ *     return "done";
+ *   }
+ * 
+ * The log: + *

+ * START RequestId: cc4eb5aa-66b4-42fc-b27a-138bd672b38a Version: $LATEST
+ * cc4eb5aa-66b4-42fc-b27a-138bd672b38a INFO uk.bot_by.bot.slf4j_demo.BotHandler - info message
+ * END RequestId: cc4eb5aa-66b4-42fc-b27a-138bd672b38a
+ * 
+ * + * @see AWSLambdaLoggerConfiguration AWSLambdaLogger's configuration + */ +public class AWSLambdaLogger implements Logger, Serializable { + + private static final long serialVersionUID = 7893093825483346807L; + + /** + * Logger configuration. + */ + private final AWSLambdaLoggerConfiguration configuration; + /** + * Logger output provider. + */ + private final AWSLambdaLoggerOutput output; + + AWSLambdaLogger(@NotNull AWSLambdaLoggerConfiguration configuration, + @NotNull AWSLambdaLoggerOutput output) { + this.configuration = configuration; + this.output = output; + } + + public String getName() { + return configuration.name(); + } + + @Override + public boolean isTraceEnabled() { + return isLevelEnabled(Level.TRACE); + } + + @Override + public boolean isTraceEnabled(Marker marker) { + return isLevelEnabled(Level.TRACE, marker); + } + + @Override + public void trace(String message) { + log(Level.TRACE, message, null); + } + + @Override + public void trace(Marker marker, String message) { + log(Level.TRACE, marker, message, null); + } + + @Override + public void trace(String format, Object argument) { + trace(format, argument, null); + } + + @Override + public void trace(Marker marker, String format, Object argument) { + trace(marker, format, argument, null); + } + + @Override + public void trace(String format, Object argument1, Object argument2) { + formatAndLog(Level.TRACE, format, argument1, argument2); + } + + @Override + public void trace(Marker marker, String format, Object argument1, Object argument2) { + formatAndLog(Level.TRACE, marker, format, argument1, argument2); + } + + @Override + public void trace(String format, Object... arguments) { + formatAndLog(Level.TRACE, format, arguments); + } + + @Override + public void trace(Marker marker, String format, Object... arguments) { + formatAndLog(Level.TRACE, marker, format, arguments); + } + + @Override + public void trace(String message, Throwable throwable) { + log(Level.TRACE, message, throwable); + } + + @Override + public void trace(Marker marker, String message, Throwable throwable) { + log(Level.TRACE, marker, message, throwable); + } + + @Override + public boolean isDebugEnabled() { + return isLevelEnabled(Level.DEBUG); + } + + @Override + public boolean isDebugEnabled(Marker marker) { + return isLevelEnabled(Level.DEBUG, marker); + } + + @Override + public void debug(String message) { + log(Level.DEBUG, message, null); + } + + @Override + public void debug(Marker marker, String message) { + log(Level.DEBUG, marker, message, null); + } + + @Override + public void debug(String format, Object argument) { + debug(format, argument, null); + } + + @Override + public void debug(Marker marker, String format, Object argument) { + debug(marker, format, argument, null); + } + + @Override + public void debug(String format, Object argument1, Object argument2) { + formatAndLog(Level.DEBUG, format, argument1, argument2); + } + + @Override + public void debug(Marker marker, String format, Object argument1, Object argument2) { + formatAndLog(Level.DEBUG, marker, format, argument1, argument2); + } + + @Override + public void debug(String format, Object... arguments) { + formatAndLog(Level.DEBUG, format, arguments); + } + + @Override + public void debug(Marker marker, String format, Object... arguments) { + formatAndLog(Level.DEBUG, marker, format, arguments); + } + + @Override + public void debug(String message, Throwable throwable) { + log(Level.DEBUG, message, throwable); + } + + @Override + public void debug(Marker marker, String message, Throwable throwable) { + log(Level.DEBUG, marker, message, throwable); + } + + @Override + public boolean isInfoEnabled() { + return isLevelEnabled(Level.INFO); + } + + @Override + public boolean isInfoEnabled(Marker marker) { + return isLevelEnabled(Level.INFO, marker); + } + + @Override + public void info(String message) { + log(Level.INFO, message, null); + } + + @Override + public void info(Marker marker, String message) { + log(Level.INFO, marker, message, null); + } + + @Override + public void info(String format, Object argument) { + info(format, argument, null); + } + + @Override + public void info(Marker marker, String format, Object argument) { + info(marker, format, argument, null); + } + + @Override + public void info(String format, Object argument1, Object argument2) { + formatAndLog(Level.INFO, format, argument1, argument2); + } + + @Override + public void info(Marker marker, String format, Object argument1, Object argument2) { + formatAndLog(Level.INFO, marker, format, argument1, argument2); + } + + @Override + public void info(String format, Object... arguments) { + formatAndLog(Level.INFO, format, arguments); + } + + @Override + public void info(Marker marker, String format, Object... arguments) { + formatAndLog(Level.INFO, marker, format, arguments); + } + + @Override + public void info(String message, Throwable throwable) { + log(Level.INFO, message, throwable); + } + + @Override + public void info(Marker marker, String message, Throwable throwable) { + log(Level.INFO, marker, message, throwable); + } + + @Override + public boolean isWarnEnabled() { + return isLevelEnabled(Level.WARN); + } + + @Override + public boolean isWarnEnabled(Marker marker) { + return isLevelEnabled(Level.WARN, marker); + } + + @Override + public void warn(String message) { + log(Level.WARN, message, null); + } + + @Override + public void warn(Marker marker, String message) { + log(Level.WARN, marker, message, null); + } + + @Override + public void warn(String format, Object argument) { + warn(format, argument, null); + } + + @Override + public void warn(Marker marker, String format, Object argument) { + warn(marker, format, argument, null); + } + + @Override + public void warn(String format, Object argument1, Object argument2) { + formatAndLog(Level.WARN, format, argument1, argument2); + } + + @Override + public void warn(Marker marker, String format, Object argument1, Object argument2) { + formatAndLog(Level.WARN, marker, format, argument1, argument2); + } + + @Override + public void warn(String format, Object... arguments) { + formatAndLog(Level.WARN, format, arguments); + } + + @Override + public void warn(Marker marker, String format, Object... arguments) { + formatAndLog(Level.WARN, marker, format, arguments); + } + + @Override + public void warn(String message, Throwable throwable) { + log(Level.WARN, message, throwable); + } + + @Override + public void warn(Marker marker, String message, Throwable throwable) { + log(Level.WARN, marker, message, throwable); + } + + @Override + public boolean isErrorEnabled() { + return isLevelEnabled(Level.ERROR); + } + + @Override + public boolean isErrorEnabled(Marker marker) { + return isLevelEnabled(Level.ERROR, marker); + } + + @Override + public void error(String message) { + log(Level.ERROR, message, null); + } + + @Override + public void error(Marker marker, String message) { + log(Level.ERROR, marker, message, null); + } + + @Override + public void error(String format, Object argument) { + error(format, argument, null); + } + + @Override + public void error(Marker marker, String format, Object argument) { + error(marker, format, argument, null); + } + + @Override + public void error(String format, Object argument1, Object argument2) { + formatAndLog(Level.ERROR, format, argument1, argument2); + } + + @Override + public void error(Marker marker, String format, Object argument1, Object argument2) { + formatAndLog(Level.ERROR, marker, format, argument1, argument2); + } + + @Override + public void error(String format, Object... arguments) { + formatAndLog(Level.ERROR, format, arguments); + } + + @Override + public void error(Marker marker, String format, Object... arguments) { + formatAndLog(Level.ERROR, marker, format, arguments); + } + + @Override + public void error(String message, Throwable throwable) { + log(Level.ERROR, message, throwable); + } + + @Override + public void error(Marker marker, String message, Throwable throwable) { + log(Level.ERROR, marker, message, throwable); + } + + @VisibleForTesting + void log(Level level, String message, Throwable throwable) { + if (!isLevelEnabled(level)) { + return; + } + output.log(configuration, null, level, message, throwable); + } + + @VisibleForTesting + void log(Level level, Marker marker, String message, Throwable throwable) { + if (!isLevelEnabled(level, marker)) { + return; + } + output.log(configuration, marker, level, message, throwable); + } + + private void formatAndLog(Level level, String format, Object... arguments) { + if (!isLevelEnabled(level)) { + return; + } + FormattingTuple formattingTuple = MessageFormatter.arrayFormat(format, arguments); + log(level, formattingTuple.getMessage(), formattingTuple.getThrowable()); + } + + private void formatAndLog(Level level, Marker marker, String format, Object... arguments) { + if (!isLevelEnabled(level, marker)) { + return; + } + FormattingTuple formattingTuple = MessageFormatter.arrayFormat(format, arguments); + log(level, marker, formattingTuple.getMessage(), formattingTuple.getThrowable()); + } + + private boolean isLevelEnabled(Level level) { + return configuration.isLevelEnabled(level); + } + + private boolean isLevelEnabled(Level level, Marker marker) { + return configuration.isLevelEnabled(level, marker); + } + + /** + * Replace a serialized logger with new singleton one. + * + * @return logger + * @throws ObjectStreamException never is thrown + */ + private Object readResolve() throws ObjectStreamException { + return LoggerFactory.getLogger(getName()); + } + +} diff --git a/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfiguration.java b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfiguration.java new file mode 100644 index 0000000..c65e150 --- /dev/null +++ b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfiguration.java @@ -0,0 +1,270 @@ +/* + * Copyright 2022-2024 Vitalij Berdinskih + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.bot_by.aws_lambda.slf4j; + +import static java.util.Objects.isNull; +import static java.util.Objects.nonNull; +import static java.util.Objects.requireNonNull; + +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiPredicate; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Marker; +import org.slf4j.event.Level; + +/** + * The configuration container. + * + * @see AWSLambdaLoggerFactory + */ +public class AWSLambdaLoggerConfiguration { + + private static final String DOT = "."; + + private final DateFormat dateTimeFormat; + private final boolean levelInBrackets; + private final List> loggerPredicates; + private final String logName; + private final String name; + private final String requestId; + private final boolean showDateTime; + private final boolean showThreadId; + private final boolean showThreadName; + + private AWSLambdaLoggerConfiguration(Builder builder) { + dateTimeFormat = builder.dateTimeFormat; + levelInBrackets = builder.levelInBrackets; + loggerPredicates = List.copyOf(builder.loggerPredicates); + name = builder.name; + if (builder.showShortLogName) { + logName = name.substring(name.lastIndexOf(DOT) + 1); + } else if (builder.showLogName) { + logName = name; + } else { + logName = null; + } + requestId = builder.requestId; + showDateTime = builder.showDateTime; + showThreadId = builder.showThreadId; + showThreadName = builder.showThreadName; + } + + static Builder builder() { + return new Builder(); + } + + /** + * The date and time format to be used in the output messages. The pattern describing the date and + * time format is defined by {@link java.text.SimpleDateFormat}. + *

+ * If the format is not specified or is invalid, the number of milliseconds since start up will be + * output. + * + * @return date and time format + * @see #showDateTime() + */ + @Nullable + public DateFormat dateTimeFormat() { + return dateTimeFormat; + } + + /** + * Test if the logging level is enabled. + * + * @param level logging level + * @return true if this logging level is enabled + */ + public boolean isLevelEnabled(Level level) { + return isLevelEnabled(level, null); + } + + /** + * Test if the logging level with the marker is enabled. + * + * @param level logging level + * @param marker logging marker + * @return true if this logging level with the marker is enabled + */ + public boolean isLevelEnabled(Level level, Marker marker) { + return loggerPredicates.stream() + .anyMatch(loggerPredicate -> loggerPredicate.test(level, marker)); + } + + /** + * Should the level string be output in brackets? + * + * @return true if the level string should be in brackets + */ + public boolean levelInBrackets() { + return levelInBrackets; + } + + /** + * The logger name. + * + * @return logger name + */ + public String logName() { + return logName; + } + + /** + * The full logger name. + * + * @return full logger name + */ + public String name() { + return name; + } + + /** + * The request ID. + * + * @return request ID + */ + public String requestId() { + return requestId; + } + + /** + * Should the date-time or timestamp be output? + * + * @return true if date-time or timestamp be output + * @see #dateTimeFormat() + */ + public boolean showDateTime() { + return showDateTime; + } + + /** + * Should the thread ID be output? + * + * @return true if thread ID be output + */ + public boolean showThreadId() { + return showThreadId; + } + + /** + * Should the thread name be output? + * + * @return true if thread name be output + */ + public boolean showThreadName() { + return showThreadName; + } + + static class Builder { + + private DateFormat dateTimeFormat; + private boolean levelInBrackets; + private List> loggerPredicates; + private String name; + private String requestId; + private boolean showDateTime; + private boolean showLogName; + private boolean showShortLogName; + private boolean showThreadId; + private boolean showThreadName; + + private Builder() { + } + + AWSLambdaLoggerConfiguration build() { + requireNonNull(loggerPredicates, "Logger level is null"); + requireNonNull(name, "Logger name is null"); + requireNonNull(requestId, "AWS request ID is null"); + return new AWSLambdaLoggerConfiguration(this); + } + + Builder dateTimeFormat(@Nullable DateFormat dateTimeFormat) { + this.dateTimeFormat = dateTimeFormat; + return this; + } + + Builder levelInBrackets(boolean levelInBrackets) { + this.levelInBrackets = levelInBrackets; + return this; + } + + Builder loggerLevel(@NotNull Level loggerLevel) { + if (isNull(loggerPredicates)) { + loggerPredicates = new ArrayList<>(); + } + loggerPredicates.add((level, marker) -> level.toInt() >= loggerLevel.toInt()); + return this; + } + + Builder loggerLevel(@NotNull Level loggerLevel, @NotNull Marker... loggerMarkers) { + if (isNull(loggerPredicates)) { + loggerPredicates = new ArrayList<>(); + } + this.loggerPredicates.add((level, marker) -> { + if (level.toInt() >= loggerLevel.toInt()) { + if (loggerMarkers.length == 0) { + return true; + } + if (nonNull(marker)) { + return Arrays.stream(loggerMarkers).anyMatch(marker::contains); + } + } + return false; + }); + return this; + } + + Builder name(@NotNull String name) { + this.name = name; + return this; + } + + Builder requestId(@NotNull String requestId) { + this.requestId = requestId; + return this; + } + + Builder showDateTime(boolean showDateTime) { + this.showDateTime = showDateTime; + return this; + } + + Builder showLogName(boolean showLogName) { + this.showLogName = showLogName; + return this; + } + + Builder showShortLogName(boolean showShortLogName) { + this.showShortLogName = showShortLogName; + return this; + } + + Builder showThreadId(boolean showThreadId) { + this.showThreadId = showThreadId; + return this; + } + + Builder showThreadName(boolean showThreadName) { + this.showThreadName = showThreadName; + return this; + } + + } + +} diff --git a/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfigurationProperty.java b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfigurationProperty.java new file mode 100644 index 0000000..bdb7fd3 --- /dev/null +++ b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfigurationProperty.java @@ -0,0 +1,116 @@ +package uk.bot_by.aws_lambda.slf4j; + +/** + * The configuration properties and environment variables. + * + * @see AWSLambdaLoggerFactory + */ +public enum AWSLambdaLoggerConfigurationProperty { + + /** + * dateTimeFormat - The date and time format to be used in the output messages. + * The pattern describing the date and time format is defined by + * {@link java.text.SimpleDateFormat}. + *

+ * If the format is not specified or is invalid, the number of milliseconds since start up will be + * output. + *

+ * The environment variable is LOG_DATE_TIME_FORMAT. + */ + DateTimeFormat("dateTimeFormat", "LOG_DATE_TIME_FORMAT", null), + /** + * defaultLogLevel - Default log level for all instances of LambdaLogger. Must + * be one of (trace, debug, info, warn, error), a + * value is case-insensitive. If not specified, defaults to info. + *

+ * The environment variable is LOG_DEFAULT_LEVEL. + */ + DefaultLogLevel("defaultLogLevel", "LOG_DEFAULT_LEVEL", "INFO"), + /** + * levelInBrackets - Should the level string be output in brackets? Defaults to + * {@code false}. + *

+ * The environment variable is LOG_LEVEL_IN_BRACKETS. + */ + LevelInBrackets("levelInBrackets", "LOG_LEVEL_IN_BRACKETS", "false"), + /** + * log.a.b.c - Logging detail level for a LambdaLogger instance named. + * a.b.c + */ + LogLevel("log.", "LOG_", null), + /** + * logLevelSeparator - Customize the level separator. + *

+ * The environment variable is LOG_LEVEL_SEPARATOR + */ + LogLevelSeparator("logLevelSeparator", "LOG_LEVEL_SEPARATOR", ","), + /** + * markerSeparator - Customize the marker separator. + *

+ * The environment variable is LOG_MARKER_SEPARATOR + */ + MarkerSeparator("markerSeparator", "LOG_MARKER_SEPARATOR", ":"), + /** + * requestId - Set the context name of AWS request ID. + * Defaults to {@code AWS_REQUEST_ID}. + *

+ * The environment variable is LOG_AWS_REQUEST_ID. + */ + RequestId("requestId", "LOG_AWS_REQUEST_ID", "AWS_REQUEST_ID"), + /** + * showDateTime - Set to {@code true} if you want the current date and time + * to be included in output messages. Defaults to {@code false}. + *

+ * The environment variable is LOG_SHOW_DATE_TIME. + */ + ShowDateTime("showDateTime", "LOG_SHOW_DATE_TIME", "false"), + /** + * showLogName - Set to {@code true} if you want the Logger instance name + * to be included in output messages. Defaults to {@code true}. + *

+ * The environment variable is LOG_SHOW_NAME. + */ + ShowLogName("showLogName", "LOG_SHOW_NAME", "true"), + /** + * showShortLogName - Set to {@code true} if you want the last component of the + * name to be included in output messages. Defaults to {@code false}. + *

+ * The environment variable is LOG_SHOW_SHORT_NAME. + */ + ShowShortLogName("showShortLogName", "LOG_SHOW_SHORT_NAME", "false"), + /** + * showThreadId - If you would like to output the current thread id, + * then set to {@code true}. Defaults to {@code false}. + *

+ * The environment variable is LOG_SHOW_THREAD_ID. + */ + ShowThreadId("showThreadId", "LOG_SHOW_THREAD_ID", "false"), + /** + * showThreadName - Set to {@code true} if you want to output + * the current thread name. Defaults to {@code false}. + *

+ * The environment variable is LOG_SHOW_THREAD_NAME. + */ + ShowThreadName("showThreadName", "LOG_SHOW_THREAD_NAME", "false"); + + /** + * Default value of the property. + */ + public final String defaultValue; + /** + * Property name. + */ + public final String propertyName; + /** + * Environment variable name. + */ + public final String variableName; + + AWSLambdaLoggerConfigurationProperty(String propertyName, String variableName, + String defaultValue) { + this.propertyName = propertyName; + this.variableName = variableName; + this.defaultValue = defaultValue; + } + +} diff --git a/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerFactory.java b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerFactory.java new file mode 100644 index 0000000..2d66eba --- /dev/null +++ b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerFactory.java @@ -0,0 +1,338 @@ +/* + * Copyright 2022-2024 Vitalij Berdinskih + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.bot_by.aws_lambda.slf4j; + +import static java.util.Objects.isNull; +import static java.util.Objects.nonNull; + +import java.io.IOException; +import java.io.InputStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.VisibleForTesting; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.event.Level; +import org.slf4j.helpers.Reporter; + +/** + * Responsible for building {@link Logger} using the {@link AWSLambdaLogger} implementation. + *

+ * The configuration is similar to SLF4J Simple. + *

+ * It looks for the {@code lambda-logger.properties} resource and read properties: + *

+ *

+ * The environment variables overrides the properties: LOG_AWS_REQUEST_ID, + * LOG_DATE_TIME_FORMAT, LOG_DEFAULT_LEVEL, + * LOG_LEVEL_IN_BRACKETS, LOG_SHOW_DATE_TIME, + * LOG_SHOW_NAME, LOG_SHOW_SHORT_NAME, + * LOG_SHOW_THREAD_ID, LOG_SHOW_THREAD_NAME. + *

+ * Fine-grained configuration with markers + *

+ * The AWS Lambda Logger supports markers since v2.0.0. + * The log level (default or detail) can have some log level and each level can have some markers. + *

+ * Example: + *


+ * log.org.test.Class=warn,info@iAmMarker,trace@important:notify-admin
+ * 
+ * The logger for {@code org.test.Class} has the common warn log level. + * Also, it has additional levels info with the marker iAmMarker + * and trace with markers important and notify-admin. + *

+ * You can customize level and marker separators with properties logLevelSeparator + * and markerSeparator. Remember that separators are not a single characters but + * regular expressions. The environment variables are LOG_LEVEL_SEPARATOR and + * LOG_MARKER_SEPARATOR accordingly. + *

+ * Example: + *


+ * log.org.test.Class=warn  info@iAmMarker trace@important|notify-admin
+ * # multi-space
+ * logLevelSeparator=\\s+
+ * # single pipe symbol
+ * markerSeparator=\\|
+ * 
+ * + * @see AWSLambdaLoggerConfigurationProperty + */ +public class AWSLambdaLoggerFactory implements ILoggerFactory { + + private static final String AT = "@"; + private static final String CONFIGURATION_FILE = "lambda-logger.properties"; + private static final char DOT = '.'; + private static final String DOTS = "\\.+"; + private static final String NONE = ""; + private static final String UNDERSCORE = "_"; + private static final String SPACES = "\\s+"; + + private final ConcurrentMap loggers; + private final DateFormat dateTimeFormat; + private final List defaultLoggerLevel; + private final boolean levelInBrackets; + private final String logLevelSeparator; + private final String markerSeparator; + private final Properties properties; + private final String requestId; + private final boolean showDateTime; + private final boolean showLogName; + private final boolean showShortLogName; + private final boolean showThreadId; + private final boolean showThreadName; + + /** + * AWS Lambda Logger Factory. + *

+ * Looking for a configuration file lambda-logger.properties. + */ + public AWSLambdaLoggerFactory() { + this(CONFIGURATION_FILE); + } + + @VisibleForTesting + AWSLambdaLoggerFactory(String configurationFile) { + loggers = new ConcurrentHashMap<>(); + properties = loadProperties(configurationFile); + dateTimeFormat = getDateTimeFormat(); + // logLevelSeparator and markerSeparator should be resolved before defaultLoggerLevel + logLevelSeparator = getStringProperty(AWSLambdaLoggerConfigurationProperty.LogLevelSeparator); + markerSeparator = getStringProperty(AWSLambdaLoggerConfigurationProperty.MarkerSeparator); + defaultLoggerLevel = getLoggerLevelProperty(); + levelInBrackets = getBooleanProperty(AWSLambdaLoggerConfigurationProperty.LevelInBrackets); + requestId = getStringProperty(AWSLambdaLoggerConfigurationProperty.RequestId); + showDateTime = getBooleanProperty(AWSLambdaLoggerConfigurationProperty.ShowDateTime); + showLogName = getBooleanProperty(AWSLambdaLoggerConfigurationProperty.ShowLogName); + showShortLogName = getBooleanProperty(AWSLambdaLoggerConfigurationProperty.ShowShortLogName); + showThreadId = getBooleanProperty(AWSLambdaLoggerConfigurationProperty.ShowThreadId); + showThreadName = getBooleanProperty(AWSLambdaLoggerConfigurationProperty.ShowThreadName); + } + + @VisibleForTesting + static AWSLambdaLoggerOutput getOutputServiceProvider() { + return getOutputServiceProvider(AWSLambdaLoggerOutput.class); + } + + @SuppressWarnings("SameParameterValue") + @VisibleForTesting + static AWSLambdaLoggerOutput getOutputServiceProvider( + Class clazz) { + var serviceProviders = ServiceLoader.load(clazz, AWSLambdaLoggerFactory.class.getClassLoader()) + .iterator(); + if (serviceProviders.hasNext()) { + return serviceProviders.next(); + } else { + throw new IllegalStateException("No AWS Lambda Logger providers were found"); + } + } + + @Override + public Logger getLogger(@NotNull String name) { + return loggers.computeIfAbsent(name, loggerName -> { + var configuration = AWSLambdaLoggerConfiguration.builder().name(loggerName) + .dateTimeFormat(dateTimeFormat).levelInBrackets(levelInBrackets).requestId(requestId) + .showDateTime(showDateTime).showLogName(showLogName).showShortLogName(showShortLogName) + .showThreadId(showThreadId).showThreadName(showThreadName); + + for (AWSLambdaLoggerLevel loggerLevel : getLoggerLevels(name)) { + configuration.loggerLevel(loggerLevel.getLevel(), loggerLevel.getMarkers()); + } + + return new AWSLambdaLogger(configuration.build(), getOutput()); + }); + } + + @VisibleForTesting + AWSLambdaLoggerOutput getOutput() { + return getOutputServiceProvider(); + } + + private boolean getBooleanProperty(AWSLambdaLoggerConfigurationProperty configurationProperty) { + return Boolean.parseBoolean(getStringProperty(configurationProperty)); + } + + private DateFormat getDateTimeFormat() { + var dateTimeFormatString = getStringProperty( + AWSLambdaLoggerConfigurationProperty.DateTimeFormat); + + if (nonNull(dateTimeFormatString)) { + try { + return new SimpleDateFormat(dateTimeFormatString); + } catch (IllegalArgumentException exception) { + Reporter.warn( + "Bad date-time format in " + CONFIGURATION_FILE + "; will output relative time"); + } + } + + return null; + } + + private List getLoggerLevelProperty() { + var defaultLogLevelProperty = AWSLambdaLoggerConfigurationProperty.DefaultLogLevel; + var value = System.getenv(defaultLogLevelProperty.variableName); + + if (nonNull(value)) { + try { + return parseLoggerLevelString(value); + } catch (IllegalArgumentException exception) { + Reporter.warn("Bad log level in the variable " + defaultLogLevelProperty.variableName); + } + } + + value = getProperties().getProperty(defaultLogLevelProperty.propertyName); + if (nonNull(value)) { + try { + return parseLoggerLevelString(value); + } catch (IllegalArgumentException exception) { + Reporter.warn( + "Bad log level in the property " + defaultLogLevelProperty.propertyName + " of " + + CONFIGURATION_FILE); + } + } + + return List.of( + AWSLambdaLoggerLevel.builder().level(Level.valueOf(defaultLogLevelProperty.defaultValue)) + .build()); + } + + private List getLoggerLevels(String loggerName) { + var name = loggerName; + int indexOfLastDot = name.length(); + String loggerLevelString = null; + + while (isNull(loggerLevelString) && indexOfLastDot > -1) { + name = name.substring(0, indexOfLastDot); + loggerLevelString = getStringProperty(AWSLambdaLoggerConfigurationProperty.LogLevel, name); + indexOfLastDot = name.lastIndexOf(DOT); + } + + List loggerLevels = null; + + if (nonNull(loggerLevelString)) { + try { + loggerLevels = parseLoggerLevelString(loggerLevelString); + } catch (IllegalArgumentException exception) { + Reporter.warn("Bad log level of the logger " + loggerName); + } + } + + if (isNull(loggerLevels)) { + loggerLevels = defaultLoggerLevel; + } + + return loggerLevels; + } + + private String getStringProperty(AWSLambdaLoggerConfigurationProperty configurationProperty) { + String value = System.getenv(configurationProperty.variableName); + + if (isNull(value)) { + value = getProperties().getProperty(configurationProperty.propertyName); + } + if (isNull(value)) { + value = configurationProperty.defaultValue; + } + + return value; + } + + private String getStringProperty(AWSLambdaLoggerConfigurationProperty configurationProperty, + String name) { + var normalizedName = name.replaceAll(SPACES, NONE); + var value = System.getenv(configurationProperty.variableName + normalizedName.toUpperCase() + .replaceAll(DOTS, UNDERSCORE)); + + if (isNull(value)) { + value = getProperties().getProperty(configurationProperty.propertyName + normalizedName); + } + if (isNull(value)) { + value = configurationProperty.defaultValue; + } + + return value; + } + + private Properties getProperties() { + return properties; + } + + private Properties loadProperties(String configurationFile) { + var properties = new Properties(); + + try (InputStream configurationInputStream = Thread.currentThread().getContextClassLoader() + .getResourceAsStream(configurationFile)) { + properties.load(configurationInputStream); + } catch (IOException | NullPointerException e) { + // ignored + Reporter.warn(CONFIGURATION_FILE + " is missed"); + } + + return properties; + } + + private List parseLoggerLevelString(String loggerLevelString) + throws IllegalArgumentException { + var loggerLevels = new ArrayList(); + + for (String loggerLevel : loggerLevelString.split(logLevelSeparator)) { + var loggerLevelBuilder = AWSLambdaLoggerLevel.builder(); + var loggerLevelWithMarkers = loggerLevel.split(AT); + + loggerLevelBuilder.level(Level.valueOf(loggerLevelWithMarkers[0].toUpperCase())); + if (loggerLevelWithMarkers.length > 1) { + for (String markerName : loggerLevelWithMarkers[1].split(markerSeparator)) { + loggerLevelBuilder.marker(markerName); + } + } + loggerLevels.add(loggerLevelBuilder.build()); + } + + return loggerLevels; + } + +} diff --git a/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerLevel.java b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerLevel.java new file mode 100644 index 0000000..dcf3104 --- /dev/null +++ b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerLevel.java @@ -0,0 +1,88 @@ +/* + * Copyright 2022-2024 Vitalij Berdinskih + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.bot_by.aws_lambda.slf4j; + +import static java.util.Objects.requireNonNull; + +import java.util.ArrayList; +import java.util.List; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.helpers.BasicMarkerFactory; + +/** + * The logger level container. + */ +public class AWSLambdaLoggerLevel { + + private final Level level; + private final Marker[] markers; + + private AWSLambdaLoggerLevel(Builder builder) { + level = builder.level; + markers = builder.markers.toArray(new Marker[0]); + } + + static Builder builder() { + return new Builder(); + } + + /** + * The logger level. + * + * @return logger level + */ + public Level getLevel() { + return level; + } + + /** + * The logger markers. + * + * @return logger markers + */ + public Marker[] getMarkers() { + return markers; + } + + static class Builder { + + private final BasicMarkerFactory markerFactory = new BasicMarkerFactory(); + private final List markers; + private Level level; + + private Builder() { + markers = new ArrayList<>(); + } + + AWSLambdaLoggerLevel build() { + requireNonNull(level, "Logger level is null"); + return new AWSLambdaLoggerLevel(this); + } + + Builder level(Level level) { + this.level = level; + return this; + } + + Builder marker(String markerName) { + markers.add(markerFactory.getMarker(markerName)); + return this; + } + + } + +} diff --git a/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerOutput.java b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerOutput.java new file mode 100644 index 0000000..0a8d7c3 --- /dev/null +++ b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerOutput.java @@ -0,0 +1,40 @@ +/* + * Copyright 2022-2024 Vitalij Berdinskih + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.bot_by.aws_lambda.slf4j; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Marker; +import org.slf4j.event.Level; + +/** + * The logger output. + */ +public interface AWSLambdaLoggerOutput { + + /** + * Write a message to the log. + * + * @param configuration logging configuration + * @param marker logging marker + * @param level logging level + * @param message logging message + * @param throwable exception + */ + void log(@NotNull AWSLambdaLoggerConfiguration configuration, @Nullable Marker marker, + @NotNull Level level, @NotNull String message, @Nullable Throwable throwable); + +} diff --git a/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaServiceProvider.java b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaServiceProvider.java new file mode 100644 index 0000000..7fc1252 --- /dev/null +++ b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaServiceProvider.java @@ -0,0 +1,69 @@ +/* + * Copyright 2022-2024 Vitalij Berdinskih + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.bot_by.aws_lambda.slf4j; + +import org.slf4j.ILoggerFactory; +import org.slf4j.IMarkerFactory; +import org.slf4j.helpers.BasicMDCAdapter; +import org.slf4j.helpers.BasicMarkerFactory; +import org.slf4j.spi.MDCAdapter; +import org.slf4j.spi.SLF4JServiceProvider; + +/** + * Responsible for binding the {@link AWSLambdaLoggerFactory}, the {@link BasicMarkerFactory} and + * the {@link BasicMDCAdapter}. This is used by the SLF4J API. + * + * @author Vitalij Berdinskih + * @since 3.0.0 + */ +public class AWSLambdaServiceProvider implements SLF4JServiceProvider { + + private static final ILoggerFactory loggerFactory = new AWSLambdaLoggerFactory(); + private static final IMarkerFactory markerFactory = new BasicMarkerFactory(); + private static final MDCAdapter contextMapAdapter = new BasicMDCAdapter(); + /** + * Declare the version of the SLF4J API this implementation is compiled against. The value of this + * field is modified with each major release. + */ + // to avoid constant folding by the compiler, this field must *not* be final + public static String REQUESTED_API_VERSION = "2.0.99"; // !final + + @Override + public ILoggerFactory getLoggerFactory() { + return loggerFactory; + } + + @Override + public IMarkerFactory getMarkerFactory() { + return markerFactory; + } + + @Override + public MDCAdapter getMDCAdapter() { + return contextMapAdapter; + } + + @Override + public String getRequestedApiVersion() { + return REQUESTED_API_VERSION; + } + + @Override + public void initialize() { + // initialized by static fields + } + +} diff --git a/core/src/main/java/uk/bot_by/aws_lambda/slf4j/package-info.java b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/package-info.java new file mode 100644 index 0000000..8f959c3 --- /dev/null +++ b/core/src/main/java/uk/bot_by/aws_lambda/slf4j/package-info.java @@ -0,0 +1,8 @@ +/** + * Contains SLF4J implementations AWS Lambda classes to the SLF4J + * framework. + * + * @author Vitalij Berdinskih + * @since 1.0.0 + */ +package uk.bot_by.aws_lambda.slf4j; diff --git a/core/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider b/core/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider new file mode 100644 index 0000000..c8c85b0 --- /dev/null +++ b/core/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider @@ -0,0 +1 @@ +uk.bot_by.aws_lambda.slf4j.AWSLambdaServiceProvider diff --git a/core/src/test/java/org/example/ServiceProvider.java b/core/src/test/java/org/example/ServiceProvider.java new file mode 100644 index 0000000..8ee0fb6 --- /dev/null +++ b/core/src/test/java/org/example/ServiceProvider.java @@ -0,0 +1,9 @@ +package org.example; + +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput; + +public interface ServiceProvider extends AWSLambdaLoggerOutput { + + String hello(); + +} diff --git a/core/src/test/java/org/example/TestServiceProvider.java b/core/src/test/java/org/example/TestServiceProvider.java new file mode 100644 index 0000000..2bd2eff --- /dev/null +++ b/core/src/test/java/org/example/TestServiceProvider.java @@ -0,0 +1,22 @@ +package org.example; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerConfiguration; + +public class TestServiceProvider implements ServiceProvider { + + @Override + public String hello() { + return "hello world"; + } + + @Override + public void log(@NotNull AWSLambdaLoggerConfiguration configuration, @Nullable Marker marker, + @NotNull Level level, @NotNull String message, @Nullable Throwable throwable) { + hello(); + } + +} diff --git a/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfigurationTest.java b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfigurationTest.java new file mode 100644 index 0000000..75a3fb9 --- /dev/null +++ b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerConfigurationTest.java @@ -0,0 +1,291 @@ +package uk.bot_by.aws_lambda.slf4j; + +import static java.util.Objects.nonNull; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + +import java.text.SimpleDateFormat; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.helpers.BasicMarkerFactory; + +@ExtendWith(MockitoExtension.class) +@Tag("fast") +class AWSLambdaLoggerConfigurationTest { + + @Mock + private Marker marker; + + @DisplayName("Logger level is required") + @Test + void loggerLevelIsRequired() { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").requestId("request#"); + + // when + Exception exception = assertThrows(NullPointerException.class, builder::build); + + // then + assertEquals("Logger level is null", exception.getMessage()); + } + + @DisplayName("Logger name is required") + @Test + void nameIsRequired() { + // given + var builder = AWSLambdaLoggerConfiguration.builder().loggerLevel(Level.TRACE) + .requestId("request#"); + + // when + Exception exception = assertThrows(NullPointerException.class, builder::build); + + // then + assertEquals("Logger name is null", exception.getMessage()); + } + + @DisplayName("Request ID is required") + @Test + void requestIdIsRequired() { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(Level.TRACE); + + // when + Exception exception = assertThrows(NullPointerException.class, builder::build); + + // then + assertEquals("AWS request ID is null", exception.getMessage()); + } + + @DisplayName("Date and time format") + @ParameterizedTest(name = "[{index}] Date format: {arguments}") + @CsvSource(value = {"null", "MM/dd/yy HH:mm"}, nullValues = "null") + void dateTimeFormat(String dateTimeFormat) { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(Level.TRACE) + .requestId("request#"); + if (nonNull(dateTimeFormat)) { + builder.dateTimeFormat(new SimpleDateFormat(dateTimeFormat)); + } + + // when + var configuration = builder.build(); + + // then + if (nonNull(dateTimeFormat)) { + assertNotNull(configuration.dateTimeFormat()); + } else { + assertNull(configuration.dateTimeFormat()); + } + } + + @DisplayName("Level in brackets") + @ParameterizedTest(name = "[{index}] Level in brackets: {arguments}") + @ValueSource(booleans = {true, false}) + void levelInBrackets(boolean levelInBrackets) { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(Level.TRACE) + .requestId("request#"); + builder.levelInBrackets(levelInBrackets); + + // when + var configuration = builder.build(); + + // then + assertEquals(levelInBrackets, configuration.levelInBrackets()); + } + + @DisplayName("Logger level") + @ParameterizedTest(name = "[{index}] Logger level: {arguments}") + @CsvSource(value = {"TRACE,N/A", "DEBUG,TRACE", "INFO,DEBUG", "WARN,INFO", + "ERROR,WARN"}, nullValues = "N/A") + void loggerLevel(Level enabledLevel, Level disabledLevel) { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(enabledLevel) + .requestId("request#"); + + // when + var configuration = builder.build(); + + // then + assertTrue(configuration.isLevelEnabled(enabledLevel), "Test log level"); + if (nonNull(disabledLevel)) { + assertFalse(configuration.isLevelEnabled(disabledLevel), "Test log level -1"); + } + } + + @DisplayName("Logger level with marker") + @ParameterizedTest(name = "[{index}] Logger level: {arguments}") + @CsvSource(value = {"TRACE,N/A", "DEBUG,TRACE", "INFO,DEBUG", "WARN,INFO", + "ERROR,WARN"}, nullValues = "N/A") + void loggerLevelWithMarker(Level enabledLevel, Level disabledLevel) { + // given + when(marker.getName()).thenReturn("i-am-a-marker"); + + var builder = AWSLambdaLoggerConfiguration.builder().name("test") + .loggerLevel(enabledLevel, marker) + .requestId("request#"); + var markerFactory = new BasicMarkerFactory(); + var knownMarker = markerFactory.getMarker("i-am-a-marker"); + var unknownMarker = markerFactory.getMarker("i-am-an-unknown-marker"); + + // when + var configuration = builder.build(); + + // then + assertAll("Test log level with marker", + () -> assertTrue(configuration.isLevelEnabled(enabledLevel, knownMarker), "known marker"), + () -> assertFalse(configuration.isLevelEnabled(enabledLevel), "without any markers"), + () -> assertFalse(configuration.isLevelEnabled(enabledLevel, unknownMarker), + "unknown marker")); + if (nonNull(disabledLevel)) { + assertFalse(configuration.isLevelEnabled(disabledLevel, knownMarker), "Test log level -1"); + } + } + + @DisplayName("Name") + @Test + void name() { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(Level.TRACE) + .requestId("request#"); + + // when + var configuration = builder.build(); + + // then + assertEquals("test", configuration.name()); + } + + @DisplayName("AWS request ID") + @Test + void requestId() { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(Level.TRACE); + builder.requestId("request-id"); + + // when + var configuration = builder.build(); + + // then + assertEquals("request-id", configuration.requestId()); + } + + @DisplayName("Show a short log name") + @ParameterizedTest(name = "[{index}] Short log name: {arguments}") + @ValueSource(booleans = {true, false}) + void showShortLogName(boolean showShortLogName) { + // given + var builder = AWSLambdaLoggerConfiguration.builder().loggerLevel(Level.TRACE) + .requestId("request#"); + builder.name("abc.xyz.TestLog").showShortLogName(showShortLogName); + + // when + var configuration = builder.build(); + + // then + if (showShortLogName) { + assertEquals("TestLog", configuration.logName()); + } else { + assertNull(configuration.logName()); + } + } + + @DisplayName("Show a log name") + @ParameterizedTest(name = "[{index}] Log name: {arguments}") + @ValueSource(booleans = {true, false}) + void showLogName(boolean showLogName) { + // given + var builder = AWSLambdaLoggerConfiguration.builder().loggerLevel(Level.TRACE) + .requestId("request#"); + builder.name("abc.xyz.TestLog").showLogName(showLogName); + + // when + var configuration = builder.build(); + + // then + if (showLogName) { + assertEquals("abc.xyz.TestLog", configuration.logName()); + } else { + assertNull(configuration.logName()); + } + } + + @DisplayName("Show a short log name instead of full one") + @Test + void showShortLogNameInsteadOfFullOne() { + // given + var builder = AWSLambdaLoggerConfiguration.builder().loggerLevel(Level.TRACE) + .requestId("request#"); + builder.name("abc.xyz.TestLog").showShortLogName(true).showLogName(true); + + // when + var configuration = builder.build(); + + // then + assertEquals("TestLog", configuration.logName()); + } + + @DisplayName("Show date and time") + @ParameterizedTest(name = "[{index}] Date and time: {arguments}") + @ValueSource(booleans = {true, false}) + void showDateTime(boolean showDateTime) { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(Level.TRACE) + .requestId("request#"); + builder.showDateTime(showDateTime); + + // when + var configuration = builder.build(); + + // then + assertEquals(showDateTime, configuration.showDateTime()); + } + + @DisplayName("Show a thread id") + @ParameterizedTest(name = "[{index}] Thread Id: {arguments}") + @ValueSource(booleans = {true, false}) + void showThreadId(boolean showThreadId) { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(Level.TRACE) + .requestId("request#"); + builder.showThreadId(showThreadId); + + // when + var configuration = builder.build(); + + // then + assertEquals(showThreadId, configuration.showThreadId()); + } + + @DisplayName("Show a thread name") + @ParameterizedTest(name = "[{index}] Thread name: {arguments}") + @ValueSource(booleans = {true, false}) + void showThreadName(boolean showThreadName) { + // given + var builder = AWSLambdaLoggerConfiguration.builder().name("test").loggerLevel(Level.TRACE) + .requestId("request#"); + builder.showThreadName(showThreadName); + + // when + var configuration = builder.build(); + + // then + assertEquals(showThreadName, configuration.showThreadName()); + } + +} diff --git a/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerFactoryTest.java b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerFactoryTest.java new file mode 100644 index 0000000..de09ce5 --- /dev/null +++ b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerFactoryTest.java @@ -0,0 +1,37 @@ +package uk.bot_by.aws_lambda.slf4j; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.example.ServiceProvider; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +@Tag("slow") +class AWSLambdaLoggerFactoryTest { + + @DisplayName("Custom output service provider") + @Test + void customOutputServiceProvider() { + // when + var serviceProvider = (ServiceProvider) assertDoesNotThrow( + () -> AWSLambdaLoggerFactory.getOutputServiceProvider(ServiceProvider.class)); + var message = serviceProvider.hello(); + + // then + assertEquals("hello world", message); + } + + @DisplayName("No output service providers") + @Test + void noOutputServiceProviders() { + // when and then + Exception exception = assertThrows(IllegalStateException.class, + AWSLambdaLoggerFactory::getOutputServiceProvider); + + assertEquals("No AWS Lambda Logger providers were found", exception.getMessage()); + } + +} \ No newline at end of file diff --git a/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerLevelTest.java b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerLevelTest.java new file mode 100644 index 0000000..dbd8dfe --- /dev/null +++ b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerLevelTest.java @@ -0,0 +1,84 @@ +package uk.bot_by.aws_lambda.slf4j; + +import static java.util.Objects.isNull; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.converter.TypedArgumentConverter; +import org.junit.jupiter.params.provider.CsvSource; +import org.slf4j.event.Level; +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerLevel.Builder; + +@Tag("fast") +class AWSLambdaLoggerLevelTest { + + @Test + void builder() { + // when and the + assertNotNull(AWSLambdaLoggerLevel.builder()); + } + + @Test + void level() { + // given + Builder builder = AWSLambdaLoggerLevel.builder(); + + // when + Exception exception = assertThrows(NullPointerException.class, builder::build); + + // then + assertEquals("Logger level is null", exception.getMessage()); + } + + @ParameterizedTest + @CsvSource(value = {"N/A, 0", "first, 1", "first|Second|THIRD, 3"}, nullValues = "N/A") + void getMarkers(@ConvertWith(PipeSeparatedValues.class) String[] markerNames, int count) { + // given + Builder builder = AWSLambdaLoggerLevel.builder().level(Level.DEBUG); + + for (String markerName : markerNames) { + builder.marker(markerName); + } + + // when + AWSLambdaLoggerLevel loggerLevel = assertDoesNotThrow(builder::build); + + // then + assertThat(loggerLevel.getMarkers(), arrayWithSize(count)); + } + + static class PipeSeparatedValues extends TypedArgumentConverter { + + /** + * Create a new {@code PipeSeparatedValues}. + */ + public PipeSeparatedValues() { + super(String.class, String[].class); + } + + /** + * Convert a pipe-separated string to a string array. + * + * @param source the source object to convert; may be {@code null} + * @return string array + */ + @Override + protected String[] convert(String source) { + if (isNull(source)) { + return new String[0]; + } + + return source.split("\\|"); + } + + } + +} diff --git a/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerTest.java b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerTest.java new file mode 100644 index 0000000..8d86709 --- /dev/null +++ b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaLoggerTest.java @@ -0,0 +1,571 @@ +package uk.bot_by.aws_lambda.slf4j; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.MDC; +import org.slf4j.event.Level; + +@ExtendWith(MockitoExtension.class) +@Tag("fast") +class AWSLambdaLoggerTest { + + @Mock + private AWSLambdaLoggerOutput output; + @Mock + private Throwable throwable; + + @AfterEach + void tearDown() { + MDC.clear(); + } + + @DisplayName("Trace is enabled") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, false", "INFO, false", "WARN, false", "ERROR, false"}) + void isTraceEnabled(Level level, boolean enabled) { + // given + var logger = getLogger(level); + + // when and then + assertEquals(enabled, logger.isTraceEnabled()); + } + + @DisplayName("Trace message") + @Test + void trace() { + // given + var logger = getSpiedLogger(Level.TRACE); + + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + + // when + logger.trace("test trace message"); + + // then + verify(logger).log(Level.TRACE, "test trace message", null); + } + + @DisplayName("Trace formatted message with an argument") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, false", "INFO, false", "WARN, false", "ERROR, false"}) + void trace1(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.trace("test trace message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.TRACE, "test trace message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Trace formatted message with two arguments") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, false", "INFO, false", "WARN, false", "ERROR, false"}) + void trace2(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.trace("test trace message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.TRACE, "test trace message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Trace formatted message with varargs") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, false", "INFO, false", "WARN, false", "ERROR, false"}) + void traceVarargs(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.trace("test trace message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.TRACE, "test trace message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Trace message with a throwable") + @Test + void traceThrowable() { + // given + var logger = getSpiedLogger(Level.ERROR); + + doNothing().when(logger).log(isA(Level.class), anyString(), isA(Throwable.class)); + + // when + logger.trace("test trace message", throwable); + + // then + verify(logger).log(Level.TRACE, "test trace message", throwable); + } + + @DisplayName("Debug is enabled") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, false", "WARN, false", "ERROR, false"}) + void isDebugEnabled(Level level, boolean enabled) { + // given + var logger = getLogger(level); + + // when and then + assertEquals(enabled, logger.isDebugEnabled()); + } + + @DisplayName("Debug message") + @Test + void debug() { + // given + var logger = getSpiedLogger(Level.DEBUG); + + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + + // when + logger.debug("test debug message"); + + // then + verify(logger).log(Level.DEBUG, "test debug message", null); + } + + @DisplayName("Debug formatted message with an argument") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, false", "WARN, false", "ERROR, false"}) + void debug1(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.debug("test debug message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.DEBUG, "test debug message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Debug formatted message with two arguments") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, false", "WARN, false", "ERROR, false"}) + void debug2(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.debug("test debug message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.DEBUG, "test debug message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Debug formatted message with varargs") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, false", "WARN, false", "ERROR, false"}) + void debugVarargs(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.debug("test debug message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.DEBUG, "test debug message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Debug message with a throwable") + @Test + void debugThrowable() { + // given + var logger = getSpiedLogger(Level.DEBUG); + + doNothing().when(logger).log(isA(Level.class), anyString(), isA(Throwable.class)); + + // when + logger.debug("test debug message", throwable); + + // then + verify(logger).log(Level.DEBUG, "test debug message", throwable); + } + + @DisplayName("Info is enabled") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, true", "WARN, false", "ERROR, false"}) + void isInfoEnabled(Level level, boolean enabled) { + // given + var logger = getLogger(level); + + // when and then + assertEquals(enabled, logger.isInfoEnabled()); + } + + @DisplayName("Info message") + @Test + void info() { + // given + var logger = getSpiedLogger(Level.INFO); + + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + + // when + logger.info("test info message"); + + // then + verify(logger).log(Level.INFO, "test info message", null); + } + + @DisplayName("Info formatted message with an argument") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, true", "WARN, false", "ERROR, false"}) + void info1(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.info("test info message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.INFO, "test info message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Info formatted message with two arguments") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, true", "WARN, false", "ERROR, false"}) + void info2(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.info("test info message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.INFO, "test info message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Info formatted message with varargs") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, true", "WARN, false", "ERROR, false"}) + void infoVarargs(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.info("test info message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.INFO, "test info message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Info message with a throwable") + @Test + void infoThrowable() { + // given + var logger = getSpiedLogger(Level.ERROR); + + doNothing().when(logger).log(isA(Level.class), anyString(), isA(Throwable.class)); + + // when + logger.info("test info message", throwable); + + // then + verify(logger).log(Level.INFO, "test info message", throwable); + } + + @DisplayName("Warn is enabled") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, true", "WARN, true", "ERROR, false"}) + void isWarnEnabled(Level level, boolean enabled) { + // given + var logger = getLogger(level); + + // when and then + assertEquals(enabled, logger.isWarnEnabled()); + } + + @DisplayName("Warning message") + @Test + void warn() { + // given + var logger = getSpiedLogger(Level.WARN); + + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + + // when + logger.warn("test warning message"); + + // then + verify(logger).log(Level.WARN, "test warning message", null); + } + + @DisplayName("Warning formatted message with an argument") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, true", "WARN, true", "ERROR, false"}) + void warning1(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.warn("test warning message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.WARN, "test warning message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Warning formatted message with two arguments") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, true", "WARN, true", "ERROR, false"}) + void warning2(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.warn("test warning message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.WARN, "test warning message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Warning formatted message with varargs") + @ParameterizedTest + @CsvSource({"TRACE, true", "DEBUG, true", "INFO, true", "WARN, true", "ERROR, false"}) + void warnVarargs(Level level, boolean enabled) { + // given + var logger = getSpiedLogger(level); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + } + + // when + logger.warn("test warning message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.WARN, "test warning message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), anyString(), any()); + } + } + + @DisplayName("Warning message with a throwable") + @Test + void warnThrowable() { + // given + var logger = getSpiedLogger(Level.WARN); + + doNothing().when(logger).log(isA(Level.class), anyString(), isA(Throwable.class)); + + // when + logger.warn("test warning message", throwable); + + // then + verify(logger).log(Level.WARN, "test warning message", throwable); + } + + @DisplayName("Error is enabled") + @ParameterizedTest + @CsvSource({"TRACE", "DEBUG", "INFO", "WARN", "ERROR"}) + void isErrorEnabled(Level level) { + // given + var logger = getLogger(level); + + // when and then + assertTrue(logger.isErrorEnabled()); + } + + @DisplayName("Error message") + @Test + void error() { + // given + var logger = getSpiedLogger(Level.ERROR); + + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + + // when + logger.error("test error message"); + + // then + verify(logger).log(Level.ERROR, "test error message", null); + } + + @DisplayName("Error formatted message with an argument") + @ParameterizedTest + @CsvSource({"TRACE", "DEBUG", "INFO", "WARN", "ERROR"}) + void error1(Level level) { + // given + var logger = getSpiedLogger(level); + + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + + // when + logger.error("test error message {}", "with an argument"); + + // then + verify(logger).log(Level.ERROR, "test error message with an argument", null); + } + + @DisplayName("Error formatted message with two arguments") + @ParameterizedTest + @CsvSource({"TRACE", "DEBUG", "INFO", "WARN", "ERROR"}) + void error2(Level level) { + // given + var logger = getSpiedLogger(level); + + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + + // when + logger.error("test error message {} {}", "with", "arguments"); + + // then + verify(logger).log(Level.ERROR, "test error message with arguments", null); + } + + @DisplayName("Error formatted message with varargs") + @ParameterizedTest + @CsvSource({"TRACE", "DEBUG", "INFO", "WARN", "ERROR"}) + void errorVarargs(Level level) { + // given + var logger = getSpiedLogger(level); + + doNothing().when(logger).log(isA(Level.class), anyString(), isNull()); + + // when + logger.error("test error message {} {} {}", "with", "some", "arguments"); + + // then + verify(logger).log(Level.ERROR, "test error message with some arguments", null); + } + + @DisplayName("Error message with a throwable") + @Test + void errorThrowable() { + // given + var logger = getSpiedLogger(Level.ERROR); + + doNothing().when(logger).log(isA(Level.class), anyString(), isA(Throwable.class)); + + // when + logger.error("test error message", throwable); + + // then + verify(logger).log(Level.ERROR, "test error message", throwable); + } + + @NotNull + private AWSLambdaLogger getLogger(Level level) { + var configuration = AWSLambdaLoggerConfiguration.builder().name("test logger") + .loggerLevel(level).requestId("request#").build(); + + return new AWSLambdaLogger(configuration, output); + } + + @NotNull + private AWSLambdaLogger getSpiedLogger(Level level) { + return spy(getLogger(level)); + } + +} diff --git a/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaServiceProviderTest.java b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaServiceProviderTest.java new file mode 100644 index 0000000..820bf91 --- /dev/null +++ b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/AWSLambdaServiceProviderTest.java @@ -0,0 +1,32 @@ +package uk.bot_by.aws_lambda.slf4j; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +@Tag("fast") +class AWSLambdaServiceProviderTest { + + private AWSLambdaServiceProvider provider; + + @BeforeEach + void setUp() { + provider = new AWSLambdaServiceProvider(); + } + + @Test + void initialize() { + // when + provider.initialize(); + + // then + assertAll("After initialization", + () -> assertNotNull(provider.getLoggerFactory(), "logger factory"), + () -> assertNotNull(provider.getMarkerFactory(), "marker factory"), + () -> assertNotNull(provider.getMDCAdapter(), "context map adapter")); + } + +} diff --git a/core/src/test/java/uk/bot_by/aws_lambda/slf4j/EnvironmentVariablesTest.java b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/EnvironmentVariablesTest.java new file mode 100644 index 0000000..6f8eeb9 --- /dev/null +++ b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/EnvironmentVariablesTest.java @@ -0,0 +1,219 @@ +package uk.bot_by.aws_lambda.slf4j; + +import static java.util.Objects.nonNull; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.helpers.BasicMarkerFactory; +import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; + +@ExtendWith({MockitoExtension.class, SystemStubsExtension.class}) +@Tag("slow") +class EnvironmentVariablesTest { + + @SystemStub + private EnvironmentVariables environment; + @Captor + private ArgumentCaptor configurationCaptor; + @Captor + private ArgumentCaptor levelCaptor; + @Captor + private ArgumentCaptor markerCaptor; + @Mock + private AWSLambdaLoggerOutput output; + @Captor + private ArgumentCaptor stringCaptor; + + @BeforeEach + void setUp() { + // override all properties + environment.set("LOG_AWS_REQUEST_ID", "request-id"); + environment.set("LOG_SHOW_DATE_TIME", "false"); + environment.set("LOG_LEVEL_IN_BRACKETS", "false"); + environment.set("LOG_SHOW_NAME", "false"); + environment.set("LOG_SHOW_SHORT_NAME", "false"); + environment.set("LOG_SHOW_THREAD_ID", "false"); + environment.set("LOG_SHOW_THREAD_NAME", "false"); + MDC.put("request-id", "variables-request-id"); + } + + @AfterEach + void tearDown() { + MDC.clear(); + } + + @DisplayName("Read logger properties from the environment, get logger then print out trace message") + @Test + void useEnvironmentVariables() { + // given + environment.set("LOG_DEFAULT_LEVEL", "Trace"); + + var loggerFactory = spy(AWSLambdaLoggerFactory.class); + + doReturn(output).when(loggerFactory).getOutput(); + + var logger = loggerFactory.getLogger("lambda.logger.test"); + + // when + logger.trace("trace message"); + + // then + verify(output).log(configurationCaptor.capture(), isNull(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Environment variable", + () -> assertTrue(configuration.isLevelEnabled(Level.TRACE), "trace is enabled"), + () -> assertEquals(Level.TRACE, levelCaptor.getValue(), "level"), + () -> assertEquals("trace message", stringCaptor.getValue(), "message")); + } + + @DisplayName("Default log level with a marker") + @Test + void defaultLogLevelWithMarker() { + // given + environment.set("LOG_DEFAULT_LEVEL", "Trace@aMarker"); + + var loggerFactory = spy(AWSLambdaLoggerFactory.class); + var marker = new BasicMarkerFactory().getMarker("aMarker"); + + doReturn(output).when(loggerFactory).getOutput(); + + var logger = loggerFactory.getLogger("lambda.logger.test"); + + // when + logger.trace(marker, "trace message"); + + // then + verify(output).log(configurationCaptor.capture(), markerCaptor.capture(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Default level with a marker", + () -> assertNotNull(markerCaptor.getValue(), "marker not null"), + () -> assertEquals("aMarker", markerCaptor.getValue().getName(), "marker"), + () -> assertFalse(configuration.isLevelEnabled(Level.TRACE), "level without a marker"), + () -> assertTrue(configuration.isLevelEnabled(Level.TRACE, marker), "level with a marker"), + () -> assertEquals(Level.TRACE, levelCaptor.getValue(), "level"), + () -> assertEquals("trace message", stringCaptor.getValue(), "message")); + } + + @DisplayName("Implement NONE/OFF level") + @ParameterizedTest + @NullSource + @ValueSource(strings = "aMarker") + void implementNoneLevel(String markerName) { + // given + environment.set("LOG_DEFAULT_LEVEL", "Trace@none"); + + var loggerFactory = spy(AWSLambdaLoggerFactory.class); + var marker = (Marker) null; + + if (nonNull(markerName)) { + marker = new BasicMarkerFactory().getMarker("aMarker"); + } + + doReturn(output).when(loggerFactory).getOutput(); + + var logger = loggerFactory.getLogger("lambda.logger.test"); + + // when + if (nonNull(marker)) { + logger.trace(marker, "trace message"); + } else { + logger.trace("trace message"); + } + + // then + verify(output, never()).log(any(), any(), any(), anyString(), any()); + } + + @DisplayName("Wrong a date-time format") + @Test + void wrongDateTimeFormat() { + // given + environment.set("LOG_DATE_TIME_FORMAT", "qwerty"); + environment.set("LOG_SHOW_DATE_TIME", "true"); + + var loggerFactory = spy(AWSLambdaLoggerFactory.class); + + doReturn(output).when(loggerFactory).getOutput(); + + var logger = loggerFactory.getLogger("lambda.logger.test"); + + // when + logger.warn("warn message"); + + // then + verify(output).log(configurationCaptor.capture(), isNull(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Timestamp", () -> assertTrue(configuration.showDateTime(), "timestamp"), + () -> assertNull(configuration.dateTimeFormat(), "format"), + () -> assertEquals(Level.WARN, levelCaptor.getValue(), "level"), + () -> assertEquals("warn message", stringCaptor.getValue(), "message")); + } + + @DisplayName("Wrong the default logger level") + @Test + void wrongDefaultLoggerLever() { + // given + environment.set("LOG_DEFAULT_LEVEL", "qwerty"); + + var loggerFactory = spy(AWSLambdaLoggerFactory.class); + + doReturn(output).when(loggerFactory).getOutput(); + + var logger = loggerFactory.getLogger("lambda.logger.test"); + + // when + logger.trace("trace message"); + logger.debug("debug message"); + + // then + verify(output).log(configurationCaptor.capture(), isNull(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Default level", + () -> assertFalse(configuration.isLevelEnabled(Level.TRACE), "trace is disabled"), + () -> assertTrue(configuration.isLevelEnabled(Level.DEBUG), "debug is enabled"), + () -> assertEquals(Level.DEBUG, levelCaptor.getValue(), "level"), + () -> assertEquals("debug message", stringCaptor.getValue(), "message")); + } + +} diff --git a/core/src/test/java/uk/bot_by/aws_lambda/slf4j/MarkedTest.java b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/MarkedTest.java new file mode 100644 index 0000000..c2ebd01 --- /dev/null +++ b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/MarkedTest.java @@ -0,0 +1,686 @@ +package uk.bot_by.aws_lambda.slf4j; + +import static java.util.Objects.nonNull; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.helpers.BasicMarkerFactory; + +@ExtendWith(MockitoExtension.class) +@Tag("fast") +class MarkedTest { + + @Mock + private AWSLambdaLoggerOutput output; + @Mock + private Marker marker; + @Mock + private Throwable throwable; + + private Marker knownMarker; + private Marker markerWithReference; + private Marker unknownMarker; + + @BeforeEach + void setUp() { + var markerFactory = new BasicMarkerFactory(); + + knownMarker = markerFactory.getMarker("i-am-a-marker"); + markerWithReference = markerFactory.getMarker("marker-with-referenct"); + markerWithReference.add(knownMarker); + unknownMarker = markerFactory.getMarker("i-am-an-unknown-marker"); + } + + @AfterEach + void tearDown() { + MDC.clear(); + } + + @DisplayName("Trace is enabled") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "TRACE, i-am-an-another-marker, false", + "DEBUG, N/A, false", "INFO, N/A, false", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void isTraceEnabled(Level level, String markerName, boolean enabled) { + // given + var logger = getLambdaLogger(level, markerName); + + // when and then + assertAll("Trace is enabled", + () -> assertEquals(enabled, logger.isTraceEnabled(knownMarker), "known marker"), + () -> assertEquals(enabled, logger.isTraceEnabled(markerWithReference), + "marker with reference"), + () -> assertFalse(logger.isTraceEnabled(), "without any markers"), + () -> assertFalse(logger.isTraceEnabled(unknownMarker), "unknown marker")); + } + + @DisplayName("Trace message") + @Test + void trace() { + // given + var logger = getSpiedLambdaLogger(Level.TRACE, null); + + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + + // when + logger.trace(knownMarker, "test trace message"); + + // then + verify(logger).log(eq(Level.TRACE), isA(Marker.class), eq("test trace message"), isNull()); + } + + @DisplayName("Trace formatted message with an argument") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "TRACE, i-am-an-another-marker, false", + "DEBUG, N/A, false", "INFO, N/A, false", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void trace1(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.trace(knownMarker, "test trace message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.TRACE, knownMarker, "test trace message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Trace formatted message with two arguments") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "TRACE, i-am-an-another-marker, false", + "DEBUG, N/A, false", "INFO, N/A, false", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void trace2(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.trace(knownMarker, "test trace message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.TRACE, knownMarker, "test trace message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Trace formatted message with varargs") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "TRACE, i-am-an-another-marker, false", + "DEBUG, N/A, false", "INFO, N/A, false", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void traceVarargs(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.trace(knownMarker, "test trace message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.TRACE, knownMarker, "test trace message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Trace message with a throwable") + @Test + void traceThrowable() { + // given + var logger = getSpiedLambdaLogger(Level.TRACE, null); + + doNothing().when(logger) + .log(isA(Level.class), isA(Marker.class), anyString(), isA(Throwable.class)); + + // when + logger.trace(knownMarker, "test trace message", throwable); + + // then + verify(logger).log(eq(Level.TRACE), isA(Marker.class), eq("test trace message"), eq(throwable)); + } + + @DisplayName("Debug is enabled") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-an-another-marker, false", + "DEBUG, i-am-a-marker, true", "INFO, N/A, false", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void isDebugEnabled(Level level, String markerName, boolean enabled) { + // given + var logger = getLambdaLogger(level, markerName); + + // when and then + assertAll("Marked debug is enabled", + () -> assertEquals(enabled, logger.isDebugEnabled(knownMarker), "known marker"), + () -> assertEquals(enabled, logger.isDebugEnabled(markerWithReference), + "marker with reference"), + () -> assertFalse(logger.isDebugEnabled(), "without any markers"), + () -> assertFalse(logger.isDebugEnabled(unknownMarker), "unknown marker")); + } + + @DisplayName("Debug message") + @Test + void debug() { + // given + var logger = getSpiedLambdaLogger(Level.DEBUG, null); + + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + + // when + logger.debug(knownMarker, "test debug message"); + + // then + verify(logger).log(eq(Level.DEBUG), isA(Marker.class), eq("test debug message"), isNull()); + } + + @DisplayName("Debug formatted message with an argument") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-an-another-marker, false", + "DEBUG, i-am-a-marker, true", "INFO, N/A, false", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void debug1(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.debug(knownMarker, "test debug message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.DEBUG, knownMarker, "test debug message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Debug formatted message with two arguments") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-an-another-marker, false", + "DEBUG, i-am-a-marker, true", "INFO, N/A, false", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void debug2(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.debug(knownMarker, "test debug message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.DEBUG, knownMarker, "test debug message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Debug formatted message with varargs") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-an-another-marker, false", + "DEBUG, i-am-a-marker, true", "INFO, N/A, false", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void debugVarargs(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.debug(knownMarker, "test debug message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.DEBUG, knownMarker, "test debug message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Debug message with a throwable") + @Test + void debugThrowable() { + // given + var logger = getSpiedLambdaLogger(Level.DEBUG, null); + + doNothing().when(logger) + .log(isA(Level.class), isA(Marker.class), anyString(), isA(Throwable.class)); + + // when + logger.debug(knownMarker, "test debug message", throwable); + + // then + verify(logger).log(eq(Level.DEBUG), isA(Marker.class), eq("test debug message"), eq(throwable)); + } + + @DisplayName("Info is enabled") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-an-another-marker, false", "INFO, i-am-a-marker, true", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void isInfoEnabled(Level level, String markerName, boolean enabled) { + // given + var logger = getLambdaLogger(level, markerName); + + // when and then + assertAll("Marked info is enabled", + () -> assertEquals(enabled, logger.isInfoEnabled(knownMarker), "known marker"), + () -> assertEquals(enabled, logger.isInfoEnabled(markerWithReference), + "marker with reference"), + () -> assertFalse(logger.isInfoEnabled(), "without any markers"), + () -> assertFalse(logger.isInfoEnabled(unknownMarker), "unknown marker")); + } + + @DisplayName("Info message") + @Test + void info() { + // given + var logger = getSpiedLambdaLogger(Level.INFO, null); + + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + + // when + logger.info(knownMarker, "test info message"); + + // then + verify(logger).log(eq(Level.INFO), isA(Marker.class), eq("test info message"), isNull()); + } + + @DisplayName("Info formatted message with an argument") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-an-another-marker, false", "INFO, i-am-a-marker, true", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void info1(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.info(knownMarker, "test info message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.INFO, knownMarker, "test info message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Info formatted message with two arguments") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-an-another-marker, false", "INFO, i-am-a-marker, true", "WARN, N/A, false", + "ERROR, N/A, false"}, nullValues = "N/A") + void info2(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.info(knownMarker, "test info message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.INFO, knownMarker, "test info message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Info formatted message with varargs") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, N/A, false", "ERROR, N/A, false"}, nullValues = "N/A") + void infoVarargs(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.info(knownMarker, "test info message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.INFO, knownMarker, "test info message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Info message with a throwable") + @Test + void infoThrowable() { + // given + var logger = getSpiedLambdaLogger(Level.INFO, null); + + doNothing().when(logger) + .log(isA(Level.class), isA(Marker.class), anyString(), isA(Throwable.class)); + + // when + logger.info(knownMarker, "test info message", throwable); + + // then + verify(logger).log(eq(Level.INFO), isA(Marker.class), eq("test info message"), eq(throwable)); + } + + @DisplayName("Warning is enabled") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, i-am-an-another-marker, false", + "WARN, i-am-a-marker, true", "ERROR, N/A, false"}, nullValues = "N/A") + void isWarnEnabled(Level level, String markerName, boolean enabled) { + // given + var logger = getLambdaLogger(level, markerName); + + // when and then + assertAll("Marked warning is enabled", + () -> assertEquals(enabled, logger.isWarnEnabled(knownMarker), "known marker"), + () -> assertEquals(enabled, logger.isWarnEnabled(markerWithReference), + "marker with reference"), + () -> assertFalse(logger.isWarnEnabled(), "without any markers"), + () -> assertFalse(logger.isWarnEnabled(unknownMarker), "unknown marker")); + } + + @DisplayName("Warning message") + @Test + void warn() { + // given + var logger = getSpiedLambdaLogger(Level.WARN, null); + + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + + // when + logger.warn(knownMarker, "test warning message"); + + // then + verify(logger).log(eq(Level.WARN), isA(Marker.class), eq("test warning message"), isNull()); + } + + @DisplayName("Warning formatted message with an argument") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, i-am-an-another-marker, false", + "WARN, i-am-a-marker, true", "ERROR, N/A, false"}, nullValues = "N/A") + void warning1(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.warn(knownMarker, "test warning message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.WARN, knownMarker, "test warning message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Warning formatted message with two arguments") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, i-am-an-another-marker, false", + "WARN, i-am-a-marker, true", "ERROR, N/A, false"}, nullValues = "N/A") + void warning2(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.warn(knownMarker, "test warning message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.WARN, knownMarker, "test warning message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Warning formatted message with varargs") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, i-am-an-another-marker, false", + "WARN, i-am-a-marker, true", "ERROR, N/A, false"}, nullValues = "N/A") + void warnVarargs(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.warn(knownMarker, "test warning message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.WARN, knownMarker, "test warning message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Warning message with a throwable") + @Test + void warnThrowable() { + // given + var logger = getSpiedLambdaLogger(Level.WARN, null); + + doNothing().when(logger) + .log(isA(Level.class), isA(Marker.class), anyString(), isA(Throwable.class)); + + // when + logger.warn(knownMarker, "test warning message", throwable); + + // then + verify(logger).log(eq(Level.WARN), isA(Marker.class), eq("test warning message"), + eq(throwable)); + } + + @DisplayName("Error is enabled") + @ParameterizedTest + @CsvSource({"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, i-am-a-marker, true", + "ERROR, i-am-an-another-marker, false", "ERROR, i-am-a-marker, true"}) + void isErrorEnabled(Level level, String markerName, boolean enabled) { + // given + var logger = getLambdaLogger(level, markerName); + + // when and then + assertAll("Marked trace is enabled", + () -> assertEquals(enabled, logger.isErrorEnabled(knownMarker), "known marker"), + () -> assertEquals(enabled, logger.isErrorEnabled(markerWithReference), + "marker with reference"), + () -> assertFalse(logger.isErrorEnabled(), "without any markers"), + () -> assertFalse(logger.isErrorEnabled(unknownMarker), "unknown marker")); + } + + @DisplayName("Error message") + @Test + void error() { + // given + var logger = getSpiedLambdaLogger(Level.ERROR, null); + + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + + // when + logger.error(knownMarker, "test error message"); + + // then + verify(logger).log(eq(Level.ERROR), isA(Marker.class), eq("test error message"), isNull()); + } + + @DisplayName("Error formatted message with an argument") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, i-am-a-marker, true", + "ERROR, i-am-an-another-marker, false", "ERROR, i-am-a-marker, true"}, nullValues = "N/A") + void error1(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.error(knownMarker, "test error message {}", "with an argument"); + + // then + if (enabled) { + verify(logger).log(Level.ERROR, knownMarker, "test error message with an argument", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Error formatted message with two arguments") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, i-am-a-marker, true", + "ERROR, i-am-an-another-marker, false", "ERROR, i-am-a-marker, true"}, nullValues = "N/A") + void error2(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.error(knownMarker, "test error message {} {}", "with", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.ERROR, knownMarker, "test error message with arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Error formatted message with varargs") + @ParameterizedTest + @CsvSource(value = {"TRACE, i-am-a-marker, true", "DEBUG, i-am-a-marker, true", + "INFO, i-am-a-marker, true", "WARN, i-am-a-marker, true", + "ERROR, i-am-an-another-marker, false", "ERROR, i-am-a-marker, true"}, nullValues = "N/A") + void errorVarargs(Level level, String markerName, boolean enabled) { + // given + var logger = getSpiedLambdaLogger(level, markerName); + + if (enabled) { + doNothing().when(logger).log(isA(Level.class), isA(Marker.class), anyString(), isNull()); + } + + // when + logger.error(knownMarker, "test error message {} {} {}", "with", "some", "arguments"); + + // then + if (enabled) { + verify(logger).log(Level.ERROR, knownMarker, "test error message with some arguments", null); + } else { + verify(logger, never()).log(isA(Level.class), isA(Marker.class), anyString(), any()); + } + } + + @DisplayName("Error message with a throwable") + @Test + void errorThrowable() { + // given + var logger = getSpiedLambdaLogger(Level.ERROR, null); + + doNothing().when(logger) + .log(isA(Level.class), isA(Marker.class), anyString(), isA(Throwable.class)); + + // when + logger.error(knownMarker, "test error message", throwable); + + // then + verify(logger).log(eq(Level.ERROR), isA(Marker.class), eq("test error message"), eq(throwable)); + } + + @NotNull + private AWSLambdaLogger getLambdaLogger(Level level, String markerName) { + var configuration = AWSLambdaLoggerConfiguration.builder().name("test logger") + .loggerLevel(level, marker).requestId("request#").build(); + + if (nonNull(markerName)) { + when(marker.getName()).thenReturn(markerName); + } + + return new AWSLambdaLogger(configuration, output); + } + + @NotNull + private AWSLambdaLogger getSpiedLambdaLogger(Level level, String markerName) { + return spy(getLambdaLogger(level, markerName)); + } + +} diff --git a/core/src/test/java/uk/bot_by/aws_lambda/slf4j/PropertiesTest.java b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/PropertiesTest.java new file mode 100644 index 0000000..83ce0a8 --- /dev/null +++ b/core/src/test/java/uk/bot_by/aws_lambda/slf4j/PropertiesTest.java @@ -0,0 +1,447 @@ +package uk.bot_by.aws_lambda.slf4j; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.helpers.BasicMarkerFactory; + +@ExtendWith(MockitoExtension.class) +@Tag("slow") +class PropertiesTest { + + @Captor + private ArgumentCaptor configurationCaptor; + @Captor + private ArgumentCaptor levelCaptor; + @Mock + private AWSLambdaLoggerOutput output; + @Captor + private ArgumentCaptor stringCaptor; + + private Marker markerA; + private Marker markerB; + private Marker markerC; + + @BeforeEach + void setUp() { + markerA = new BasicMarkerFactory().getMarker("iAmMarker"); + markerB = new BasicMarkerFactory().getMarker("important"); + markerC = new BasicMarkerFactory().getMarker("important"); + } + + @AfterEach + void tearDown() { + MDC.clear(); + } + + @DisplayName("Parent log level") + @ParameterizedTest(name = "[{index}] {0}") + @CsvSource({"trace,true,true,true,true,true", "debug,false,true,true,true,true", + "info,false,false,true,true,true", "warn,false,false,false,true,true", + "error,false,false,false,false,true", "none,false,false,false,false,false"}) + void parentLogLevel(String levelName, boolean traceEnabled, boolean debugEnabled, + boolean infoEnabled, boolean warnEnabled, boolean errorEnabled) { + // given + var loggerFactory = spy( + new AWSLambdaLoggerFactory("parent-log-level-" + levelName + ".properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("org.test.Class"); + + // then + assertAll("Check parent log level", + () -> assertThat("trace", logger.isTraceEnabled(), is(traceEnabled)), + () -> assertThat("debug", logger.isDebugEnabled(), is(debugEnabled)), + () -> assertThat("info", logger.isInfoEnabled(), is(infoEnabled)), + () -> assertThat("warn", logger.isWarnEnabled(), is(warnEnabled)), + () -> assertThat("error", logger.isErrorEnabled(), is(errorEnabled))); + } + + @DisplayName("Parent log level with a marker") + @Test + void parentLogLevelWithMarker() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("parent-log-level-marker.properties")); + var marker = new BasicMarkerFactory().getMarker("iAmMarker"); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("org.test.Class"); + + // then + assertAll("Check parent log level", () -> assertFalse(logger.isTraceEnabled(), "trace"), + () -> assertFalse(logger.isDebugEnabled(), "debug"), + () -> assertFalse(logger.isInfoEnabled(), "info"), + () -> assertFalse(logger.isWarnEnabled(), "warn"), + () -> assertFalse(logger.isErrorEnabled(), "error"), + () -> assertTrue(logger.isWarnEnabled(marker), "debug with a marker")); + } + + @DisplayName("Parent log multi-levels with multi-markers") + @Test + void parentLogLevelMulti() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("parent-log-level-multi.properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("org.test.Class"); + + // then + assertAll("Check parent log level", () -> assertFalse(logger.isTraceEnabled(), "trace"), + () -> assertFalse(logger.isDebugEnabled(), "debug"), + () -> assertFalse(logger.isInfoEnabled(), "info"), + () -> assertTrue(logger.isWarnEnabled(), "warn"), + () -> assertTrue(logger.isErrorEnabled(), "error"), + () -> assertTrue(logger.isInfoEnabled(markerA), "info with a marker"), + () -> assertTrue(logger.isTraceEnabled(markerB), "trace with the marker B"), + () -> assertTrue(logger.isTraceEnabled(markerC), "trace with the marker C")); + } + + @DisplayName("Class log level") + @ParameterizedTest(name = "[{index}] {0}") + @CsvSource({"trace,true,true,true,true,true", "debug,false,true,true,true,true", + "info,false,false,true,true,true", "warn,false,false,false,true,true", + "error,false,false,false,false,true", "none,false,false,false,false,false"}) + void classLogLevel(String levelName, boolean traceEnabled, boolean debugEnabled, + boolean infoEnabled, boolean warnEnabled, boolean errorEnabled) { + // given + var loggerFactory = spy( + new AWSLambdaLoggerFactory("class-log-level-" + levelName + ".properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("org.test.Class"); + + // then + assertAll("Check class log level", + () -> assertThat("trace", logger.isTraceEnabled(), is(traceEnabled)), + () -> assertThat("debug", logger.isDebugEnabled(), is(debugEnabled)), + () -> assertThat("info", logger.isInfoEnabled(), is(infoEnabled)), + () -> assertThat("warn", logger.isWarnEnabled(), is(warnEnabled)), + () -> assertThat("error", logger.isErrorEnabled(), is(errorEnabled))); + } + + @DisplayName("Class log level with a marker") + @Test + void classLogLevelWithMarker() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("class-log-level-marker.properties")); + var marker = new BasicMarkerFactory().getMarker("iAmMarker"); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("org.test.Class"); + + // then + assertAll("Check class log level", () -> assertFalse(logger.isTraceEnabled(), "trace"), + () -> assertFalse(logger.isDebugEnabled(), "debug"), + () -> assertFalse(logger.isInfoEnabled(), "info"), + () -> assertFalse(logger.isWarnEnabled(), "warn"), + () -> assertFalse(logger.isErrorEnabled(), "error"), + () -> assertTrue(logger.isInfoEnabled(marker), "debug with a marker")); + } + + @DisplayName("Class log multi-levels with multi-markers") + @Test + void classLogLevelMulti() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("class-log-level-multi.properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("org.test.Class"); + + // then + assertAll("Check class log level", () -> assertFalse(logger.isTraceEnabled(), "trace"), + () -> assertFalse(logger.isDebugEnabled(), "debug"), + () -> assertFalse(logger.isInfoEnabled(), "info"), + () -> assertTrue(logger.isWarnEnabled(), "warn"), + () -> assertTrue(logger.isErrorEnabled(), "error"), + () -> assertTrue(logger.isInfoEnabled(markerA), "info with a marker"), + () -> assertTrue(logger.isTraceEnabled(markerB), "trace with the marker B"), + () -> assertTrue(logger.isTraceEnabled(markerC), "trace with the marker C")); + } + + @DisplayName("Default log level") + @ParameterizedTest(name = "[{index}] {0}") + @CsvSource({"trace,true,true,true,true,true", "debug,false,true,true,true,true", + "info,false,false,true,true,true", "warn,false,false,false,true,true", + "error,false,false,false,false,true", "none,false,false,false,false,false"}) + void defaultLogLevel(String levelName, boolean traceEnabled, boolean debugEnabled, + boolean infoEnabled, boolean warnEnabled, boolean errorEnabled) { + // given + var loggerFactory = spy( + new AWSLambdaLoggerFactory("default-log-level-" + levelName + ".properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger(levelName + " test"); + + // then + assertAll("Check default log level", + () -> assertThat("trace", logger.isTraceEnabled(), is(traceEnabled)), + () -> assertThat("debug", logger.isDebugEnabled(), is(debugEnabled)), + () -> assertThat("info", logger.isInfoEnabled(), is(infoEnabled)), + () -> assertThat("warn", logger.isWarnEnabled(), is(warnEnabled)), + () -> assertThat("error", logger.isErrorEnabled(), is(errorEnabled))); + } + + @DisplayName("Default log level with a marker") + @Test + void defaultLogLevelWithMarker() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("default-log-level-marker.properties")); + var marker = new BasicMarkerFactory().getMarker("iAmMarker"); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("marker test"); + + // then + assertAll("Check default log level", () -> assertFalse(logger.isTraceEnabled(), "trace"), + () -> assertFalse(logger.isDebugEnabled(), "debug"), + () -> assertFalse(logger.isInfoEnabled(), "info"), + () -> assertFalse(logger.isWarnEnabled(), "warn"), + () -> assertFalse(logger.isErrorEnabled(), "error"), + () -> assertTrue(logger.isDebugEnabled(marker), "debug with a marker")); + } + + @DisplayName("Default log multi-levels with multi-markers") + @Test + void defaultLogLevelMulti() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("default-log-level-multi.properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("org.test.Class"); + + // then + assertAll("Check default log level", () -> assertFalse(logger.isTraceEnabled(), "trace"), + () -> assertFalse(logger.isDebugEnabled(), "debug"), + () -> assertFalse(logger.isInfoEnabled(), "info"), + () -> assertTrue(logger.isWarnEnabled(), "warn"), + () -> assertTrue(logger.isErrorEnabled(), "error"), + () -> assertTrue(logger.isInfoEnabled(markerA), "info with a marker"), + () -> assertTrue(logger.isTraceEnabled(markerB), "trace with the marker B"), + () -> assertTrue(logger.isTraceEnabled(markerC), "trace with the marker C")); + } + + @DisplayName("Custom level and marker separators") + @Test + void customLevelAndMarkerSeparators() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("custom-separators.properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + // when + var logger = loggerFactory.getLogger("org.test.Class"); + + // then + assertAll("Check custom level and marker separators", + () -> assertFalse(logger.isTraceEnabled(), "trace"), + () -> assertFalse(logger.isDebugEnabled(), "debug"), + () -> assertFalse(logger.isInfoEnabled(), "info"), + () -> assertTrue(logger.isWarnEnabled(), "warn"), + () -> assertTrue(logger.isErrorEnabled(), "error"), + () -> assertTrue(logger.isInfoEnabled(markerA), "info with a marker"), + () -> assertTrue(logger.isTraceEnabled(markerB), "trace with the marker B"), + () -> assertTrue(logger.isTraceEnabled(markerC), "trace with the marker C")); + } + + @DisplayName("Read logger properties from the file, get logger then print out debug message") + @Test + void useLoggerProperties() { + // given + var loggerFactory = spy(AWSLambdaLoggerFactory.class); + + doReturn(output).when(loggerFactory).getOutput(); + + MDC.put("request#", "properties-request-id"); + + // when + loggerFactory.getLogger("lambda.logger.test").debug("debug message"); + + // then + verify(output).log(configurationCaptor.capture(), isNull(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Missed properties", () -> assertTrue(configuration.showDateTime(), "timestamp"), + () -> assertNotEquals(configuration.dateTimeFormat(), "format"), + () -> assertTrue(configuration.levelInBrackets(), "brackets"), + () -> assertEquals("test", configuration.logName(), "short name"), + () -> assertTrue(configuration.showThreadId(), "thread id"), + () -> assertTrue(configuration.showThreadName(), "thread name"), + () -> assertEquals(Level.DEBUG, levelCaptor.getValue(), "level"), + () -> assertEquals("debug message", stringCaptor.getValue(), "message")); + } + + @DisplayName("Try to read missed logger properties file, use default values") + @Test + void missedProperties() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("missed.properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + MDC.put("request#", "properties-request-id"); + + var logger = loggerFactory.getLogger("lambda.logger.test"); + + // when + logger.debug("debug message"); + logger.info("info message"); + + // then + verify(output).log(configurationCaptor.capture(), isNull(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Missed properties", () -> assertFalse(configuration.showDateTime(), "timestamp"), + () -> assertNull(configuration.dateTimeFormat(), "format"), + () -> assertFalse(configuration.isLevelEnabled(Level.DEBUG), "debug is disabled"), + () -> assertTrue(configuration.isLevelEnabled(Level.INFO), "info is enabled"), + () -> assertFalse(configuration.levelInBrackets(), "brackets"), + () -> assertEquals("lambda.logger.test", configuration.logName(), "long name"), + () -> assertFalse(configuration.showThreadId(), "thread id"), + () -> assertFalse(configuration.showThreadName(), "thread name"), + () -> assertEquals(Level.INFO, levelCaptor.getValue(), "level"), + () -> assertEquals("info message", stringCaptor.getValue(), "message")); + } + + @DisplayName("Wrong a date-time format") + @Test + void wrongDateTimeFormat() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("wrong-date-time-format.properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + MDC.put("request#", "properties-request-id"); + + // when + loggerFactory.getLogger("lambda.logger.test").info("info message"); + + // then + verify(output).log(configurationCaptor.capture(), isNull(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Timestamp", () -> assertTrue(configuration.showDateTime(), "timestamp"), + () -> assertNull(configuration.dateTimeFormat(), "format"), + () -> assertTrue(configuration.levelInBrackets(), "brackets"), + () -> assertEquals("test", configuration.logName(), "short name"), + () -> assertTrue(configuration.showThreadId(), "thread id"), + () -> assertTrue(configuration.showThreadName(), "thread name"), + () -> assertEquals(Level.INFO, levelCaptor.getValue(), "level"), + () -> assertEquals("info message", stringCaptor.getValue(), "message")); + } + + @DisplayName("Wrong the default logger level") + @Test + void wrongDefaultLoggerLevel() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("wrong-default-logger-level.properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + MDC.put("request#", "properties-request-id"); + + var logger = loggerFactory.getLogger("lambda.logger.test"); + + // when + logger.debug("debug message"); + logger.info("info message"); + + // then + verify(output).log(configurationCaptor.capture(), isNull(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Default level", + () -> assertFalse(configuration.isLevelEnabled(Level.DEBUG), "debug is disabled"), + () -> assertTrue(configuration.isLevelEnabled(Level.INFO), "info is enabled"), + () -> assertTrue(configuration.levelInBrackets(), "brackets"), + () -> assertEquals("test", configuration.logName(), "short name"), + () -> assertTrue(configuration.showThreadId(), "thread id"), + () -> assertTrue(configuration.showThreadName(), "thread name"), + () -> assertEquals(Level.INFO, levelCaptor.getValue(), "level"), + () -> assertEquals("info message", stringCaptor.getValue(), "message")); + } + + @DisplayName("Wrong a logger level") + @Test + void wrongLoggerLevel() { + // given + var loggerFactory = spy(new AWSLambdaLoggerFactory("wrong-logger-level.properties")); + + doReturn(output).when(loggerFactory).getOutput(); + + MDC.put("request#", "properties-request-id"); + + var logger = loggerFactory.getLogger("org.test.Class"); + + // when + logger.trace("trace message"); + logger.debug("debug message"); + + // then + verify(output).log(configurationCaptor.capture(), isNull(), levelCaptor.capture(), + stringCaptor.capture(), isNull()); + + var configuration = configurationCaptor.getValue(); + + assertAll("Logger level", + () -> assertFalse(configuration.isLevelEnabled(Level.TRACE), "trace is disabled"), + () -> assertTrue(configuration.isLevelEnabled(Level.DEBUG), "debug is enabled"), + () -> assertTrue(configuration.levelInBrackets(), "brackets"), + () -> assertEquals("Class", configuration.logName(), "short name"), + () -> assertTrue(configuration.showThreadId(), "thread id"), + () -> assertTrue(configuration.showThreadName(), "thread name"), + () -> assertEquals(Level.DEBUG, levelCaptor.getValue(), "level"), + () -> assertEquals("debug message", stringCaptor.getValue(), "message")); + } + +} diff --git a/core/src/test/resources/META-INF/services/org.example.ServiceProvider b/core/src/test/resources/META-INF/services/org.example.ServiceProvider new file mode 100644 index 0000000..40a6436 --- /dev/null +++ b/core/src/test/resources/META-INF/services/org.example.ServiceProvider @@ -0,0 +1 @@ +org.example.TestServiceProvider diff --git a/core/src/test/resources/class-log-level-debug.properties b/core/src/test/resources/class-log-level-debug.properties new file mode 100644 index 0000000..017bc15 --- /dev/null +++ b/core/src/test/resources/class-log-level-debug.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org.test.Class=DeBuG diff --git a/core/src/test/resources/class-log-level-error.properties b/core/src/test/resources/class-log-level-error.properties new file mode 100644 index 0000000..9705dbc --- /dev/null +++ b/core/src/test/resources/class-log-level-error.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org.test.Class=eRroR diff --git a/core/src/test/resources/class-log-level-info.properties b/core/src/test/resources/class-log-level-info.properties new file mode 100644 index 0000000..033c020 --- /dev/null +++ b/core/src/test/resources/class-log-level-info.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org.test.Class=Info diff --git a/core/src/test/resources/class-log-level-marker.properties b/core/src/test/resources/class-log-level-marker.properties new file mode 100644 index 0000000..a7b1be2 --- /dev/null +++ b/core/src/test/resources/class-log-level-marker.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org.test.Class=info@iAmMarker diff --git a/core/src/test/resources/class-log-level-multi.properties b/core/src/test/resources/class-log-level-multi.properties new file mode 100644 index 0000000..00d6f47 --- /dev/null +++ b/core/src/test/resources/class-log-level-multi.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org.test.Class=warn,info@iAmMarker,trace@important:notify-admin diff --git a/core/src/test/resources/class-log-level-none.properties b/core/src/test/resources/class-log-level-none.properties new file mode 100644 index 0000000..7145b97 --- /dev/null +++ b/core/src/test/resources/class-log-level-none.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org.test.Class=trace@abc diff --git a/core/src/test/resources/class-log-level-trace.properties b/core/src/test/resources/class-log-level-trace.properties new file mode 100644 index 0000000..2fcc1de --- /dev/null +++ b/core/src/test/resources/class-log-level-trace.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org.test.Class=trace diff --git a/core/src/test/resources/class-log-level-warn.properties b/core/src/test/resources/class-log-level-warn.properties new file mode 100644 index 0000000..f00769b --- /dev/null +++ b/core/src/test/resources/class-log-level-warn.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org.test.Class=warn diff --git a/core/src/test/resources/custom-separators.properties b/core/src/test/resources/custom-separators.properties new file mode 100644 index 0000000..310bace --- /dev/null +++ b/core/src/test/resources/custom-separators.properties @@ -0,0 +1,5 @@ +defaultLogLevel=warn info@iAmMarker trace@important|notify-admin +# multi-space +logLevelSeparator=\\s+ +# single pipe symbol +markerSeparator=\\| diff --git a/core/src/test/resources/default-log-level-debug.properties b/core/src/test/resources/default-log-level-debug.properties new file mode 100644 index 0000000..828873e --- /dev/null +++ b/core/src/test/resources/default-log-level-debug.properties @@ -0,0 +1 @@ +defaultLogLevel=DeBuG diff --git a/core/src/test/resources/default-log-level-error.properties b/core/src/test/resources/default-log-level-error.properties new file mode 100644 index 0000000..3fac6c0 --- /dev/null +++ b/core/src/test/resources/default-log-level-error.properties @@ -0,0 +1 @@ +defaultLogLevel=eRroR diff --git a/core/src/test/resources/default-log-level-info.properties b/core/src/test/resources/default-log-level-info.properties new file mode 100644 index 0000000..1b64aef --- /dev/null +++ b/core/src/test/resources/default-log-level-info.properties @@ -0,0 +1 @@ +defaultLogLevel=Info diff --git a/core/src/test/resources/default-log-level-marker.properties b/core/src/test/resources/default-log-level-marker.properties new file mode 100644 index 0000000..bd682f9 --- /dev/null +++ b/core/src/test/resources/default-log-level-marker.properties @@ -0,0 +1 @@ +defaultLogLevel=DeBuG@iAmMarker diff --git a/core/src/test/resources/default-log-level-multi.properties b/core/src/test/resources/default-log-level-multi.properties new file mode 100644 index 0000000..b407513 --- /dev/null +++ b/core/src/test/resources/default-log-level-multi.properties @@ -0,0 +1 @@ +defaultLogLevel=warn,info@iAmMarker,trace@important:notify-admin diff --git a/core/src/test/resources/default-log-level-none.properties b/core/src/test/resources/default-log-level-none.properties new file mode 100644 index 0000000..9dc422b --- /dev/null +++ b/core/src/test/resources/default-log-level-none.properties @@ -0,0 +1 @@ +defaultLogLevel=trace@ignore diff --git a/core/src/test/resources/default-log-level-trace.properties b/core/src/test/resources/default-log-level-trace.properties new file mode 100644 index 0000000..899f845 --- /dev/null +++ b/core/src/test/resources/default-log-level-trace.properties @@ -0,0 +1 @@ +defaultLogLevel=trace diff --git a/core/src/test/resources/default-log-level-warn.properties b/core/src/test/resources/default-log-level-warn.properties new file mode 100644 index 0000000..2eed7f4 --- /dev/null +++ b/core/src/test/resources/default-log-level-warn.properties @@ -0,0 +1 @@ +defaultLogLevel=WARN diff --git a/core/src/test/resources/lambda-logger.properties b/core/src/test/resources/lambda-logger.properties new file mode 100644 index 0000000..0e4f078 --- /dev/null +++ b/core/src/test/resources/lambda-logger.properties @@ -0,0 +1,9 @@ +dateTimeFormat=HH:mm:ss.sss +defaultLogLevel=DeBuG +levelInBrackets=true +requestId=request# +showDateTime=true +showLogName=true +showShortLogName=true +showThreadId=true +showThreadName=true diff --git a/core/src/test/resources/parent-log-level-debug.properties b/core/src/test/resources/parent-log-level-debug.properties new file mode 100644 index 0000000..3ecfac5 --- /dev/null +++ b/core/src/test/resources/parent-log-level-debug.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org=DeBuG diff --git a/core/src/test/resources/parent-log-level-error.properties b/core/src/test/resources/parent-log-level-error.properties new file mode 100644 index 0000000..655a1f8 --- /dev/null +++ b/core/src/test/resources/parent-log-level-error.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org=eRroR diff --git a/core/src/test/resources/parent-log-level-info.properties b/core/src/test/resources/parent-log-level-info.properties new file mode 100644 index 0000000..52715d8 --- /dev/null +++ b/core/src/test/resources/parent-log-level-info.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org=Info diff --git a/core/src/test/resources/parent-log-level-marker.properties b/core/src/test/resources/parent-log-level-marker.properties new file mode 100644 index 0000000..f2e3cf8 --- /dev/null +++ b/core/src/test/resources/parent-log-level-marker.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org=Warn@iAmMarker diff --git a/core/src/test/resources/parent-log-level-multi.properties b/core/src/test/resources/parent-log-level-multi.properties new file mode 100644 index 0000000..40f7099 --- /dev/null +++ b/core/src/test/resources/parent-log-level-multi.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org=warn,info@iAmMarker,trace@important:notify-admin diff --git a/core/src/test/resources/parent-log-level-none.properties b/core/src/test/resources/parent-log-level-none.properties new file mode 100644 index 0000000..6f0eb45 --- /dev/null +++ b/core/src/test/resources/parent-log-level-none.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org=trace@abc diff --git a/core/src/test/resources/parent-log-level-trace.properties b/core/src/test/resources/parent-log-level-trace.properties new file mode 100644 index 0000000..a22a60b --- /dev/null +++ b/core/src/test/resources/parent-log-level-trace.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org=trace diff --git a/core/src/test/resources/parent-log-level-warn.properties b/core/src/test/resources/parent-log-level-warn.properties new file mode 100644 index 0000000..5351dc8 --- /dev/null +++ b/core/src/test/resources/parent-log-level-warn.properties @@ -0,0 +1,2 @@ +defaultLogLevel=trace +log.org=warn diff --git a/core/src/test/resources/wrong-date-time-format.properties b/core/src/test/resources/wrong-date-time-format.properties new file mode 100644 index 0000000..5e042cf --- /dev/null +++ b/core/src/test/resources/wrong-date-time-format.properties @@ -0,0 +1,9 @@ +dateTimeFormat=qwerty +defaultLogLevel=DeBuG +levelInBrackets=true +requestId=request# +showDateTime=true +showLogName=true +showShortLogName=true +showThreadId=true +showThreadName=true diff --git a/core/src/test/resources/wrong-default-logger-level.properties b/core/src/test/resources/wrong-default-logger-level.properties new file mode 100644 index 0000000..0ccacd4 --- /dev/null +++ b/core/src/test/resources/wrong-default-logger-level.properties @@ -0,0 +1,8 @@ +defaultLogLevel=qwerty +levelInBrackets=true +requestId=request# +showDateTime=false +showLogName=true +showShortLogName=true +showThreadId=true +showThreadName=true diff --git a/core/src/test/resources/wrong-logger-level.properties b/core/src/test/resources/wrong-logger-level.properties new file mode 100644 index 0000000..3dcf2b3 --- /dev/null +++ b/core/src/test/resources/wrong-logger-level.properties @@ -0,0 +1,9 @@ +defaultLogLevel=debug +log.org.test.Class=qwerty +levelInBrackets=true +requestId=request# +showDateTime=false +showLogName=true +showShortLogName=true +showThreadId=true +showThreadName=true diff --git a/json-logger/pom.xml b/json-logger/pom.xml new file mode 100644 index 0000000..13d1b85 --- /dev/null +++ b/json-logger/pom.xml @@ -0,0 +1,82 @@ + + aws-lambda-slf4j-json-logger + + + + maven-surefire-plugin + org.apache.maven.plugins + + + jacoco-maven-plugin + org.jacoco + + + + + + annotations + org.jetbrains + provided + + + aws-lambda-java-core + com.amazonaws + + + slf4j-api + org.slf4j + + + aws-lambda-slf4j-core + io.github.vitalijr2.aws-lambda + 1.1.1 + + + json + org.json + 20240205 + + + + junit-jupiter-api + org.junit.jupiter + test + + + junit-jupiter-engine + org.junit.jupiter + test + + + mockito-core + org.mockito + test + + + mockito-junit-jupiter + org.mockito + test + + + hamcrest + org.hamcrest + test + + + jsonassert + org.skyscreamer + test + 1.5.1 + + + An SLF4J Logger implementation for AWS Lambda, JSON Output + 4.0.0 + SLF4J for AWS Lambda : JSON Logger + + aws-lambda-slf4j + io.github.vitalijr2.aws-lambda + 1.1.1 + + diff --git a/json-logger/src/main/java/uk/bot_by/aws_lambda/slf4j/json_output/JSONLoggerOutput.java b/json-logger/src/main/java/uk/bot_by/aws_lambda/slf4j/json_output/JSONLoggerOutput.java new file mode 100644 index 0000000..e02d4e6 --- /dev/null +++ b/json-logger/src/main/java/uk/bot_by/aws_lambda/slf4j/json_output/JSONLoggerOutput.java @@ -0,0 +1,169 @@ +/* + * Copyright 2022-2024 Vitalij Berdinskih + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.bot_by.aws_lambda.slf4j.json_output; + +import static java.util.Objects.nonNull; + +import com.amazonaws.services.lambda.runtime.LambdaLogger; +import com.amazonaws.services.lambda.runtime.LambdaRuntime; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; +import org.json.JSONObject; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerConfiguration; +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput; + +/** + * An SLF4J Logger implementation for AWS Lambda with JSON output. + */ +public class JSONLoggerOutput implements AWSLambdaLoggerOutput { + + private static final String AWS_REQUEST_ID = "aws-request-id"; + private static final String RELATIVE_TIMESTAMP = "relative-timestamp"; + private static final String LEVEL = "level"; + private static final String LOGNAME = "logname"; + private static final String MARKERS = "markers"; + private static final String MESSAGE = "message"; + private static final String STACK_TRACE = "stack-trace"; + private static final Long START_TIME = System.currentTimeMillis(); + private static final String THREAD_ID = "thread-id"; + private static final String THREAD_NAME = "thread-name"; + private static final String THROWABLE_CLASS = "throwable-class"; + private static final String THROWABLE_MESSAGE = "throwable-message"; + private static final String TIMESTAMP = "timestamp"; + + private static void addLevel(Level level, JSONObject jsonObject) { + jsonObject.put(LEVEL, level); + } + + private static void addLogName(AWSLambdaLoggerConfiguration configuration, + JSONObject jsonObject) { + if (nonNull(configuration.logName())) { + jsonObject.put(LOGNAME, configuration.logName()); + } + } + + private static void addMarkerAndReferences(Marker marker, JSONObject jsonObject) { + if (nonNull(marker)) { + var markers = new ArrayList(); + + marker.iterator().forEachRemaining(referenceMarker -> markers.add(referenceMarker.getName())); + markers.add(0, marker.getName()); + jsonObject.put(MARKERS, markers); + } + } + + private static void addRequestId(AWSLambdaLoggerConfiguration configuration, + JSONObject jsonObject) { + if (nonNull(MDC.get(configuration.requestId()))) { + jsonObject.put(AWS_REQUEST_ID, MDC.get(configuration.requestId())); + } + } + + private static void addThread(AWSLambdaLoggerConfiguration configuration, JSONObject jsonObject) { + if (configuration.showThreadName()) { + jsonObject.put(THREAD_NAME, Thread.currentThread().getName()); + } + if (configuration.showThreadId()) { + jsonObject.put(THREAD_ID, Thread.currentThread().getId()); + } + } + + private static void addThrowable(Throwable throwable, JSONObject jsonObject) { + if (nonNull(throwable)) { + jsonObject.put(THROWABLE_CLASS, throwable.getClass().getName()); + if (nonNull(throwable.getMessage())) { + jsonObject.put(THROWABLE_MESSAGE, throwable.getMessage()); + } + + var stackTraceOutputStream = new ByteArrayOutputStream(); + + throwable.printStackTrace(new PrintStream(stackTraceOutputStream)); + jsonObject.put(STACK_TRACE, stackTraceOutputStream); + } + } + + @SuppressWarnings("ConstantConditions") + private static void addTimestamp(AWSLambdaLoggerConfiguration configuration, + JSONObject jsonObject) { + if (configuration.showDateTime()) { + if (nonNull(configuration.dateTimeFormat())) { + jsonObject.put(TIMESTAMP, getFormattedDate(configuration.dateTimeFormat())); + } else { + jsonObject.put(RELATIVE_TIMESTAMP, System.currentTimeMillis() - START_TIME); + } + } + } + + private static String getFormattedDate(DateFormat dateFormat) { + String dateText; + + synchronized (START_TIME) { + dateText = dateFormat.format(new Date()); + } + + return dateText; + } + + /** + * Write a message to the AWS lambda log in JSON. + * + * @param configuration logging configuration + * @param marker logging marker + * @param level logging level + * @param message logging message + * @param throwable exception + */ + @Override + public void log(@NotNull AWSLambdaLoggerConfiguration configuration, @Nullable Marker marker, + @NotNull Level level, @NotNull String message, @Nullable Throwable throwable) { + log(configuration, getLambdaLogger(), marker, level, message, throwable); + } + + @VisibleForTesting + LambdaLogger getLambdaLogger() { + return LambdaRuntime.getLogger(); + } + + @VisibleForTesting + void log(@NotNull AWSLambdaLoggerConfiguration configuration, @NotNull LambdaLogger lambdaLogger, + @Nullable Marker marker, @NotNull Level level, @NotNull String message, + @Nullable Throwable throwable) { + JSONObject jsonObject = new JSONObject(); + + addRequestId(configuration, jsonObject); + addTimestamp(configuration, jsonObject); + addThread(configuration, jsonObject); + addMarkerAndReferences(marker, jsonObject); + addLevel(level, jsonObject); + addLogName(configuration, jsonObject); + jsonObject.put(MESSAGE, message); + addThrowable(throwable, jsonObject); + + synchronized (START_TIME) { + lambdaLogger.log(jsonObject.toString()); + } + } + +} diff --git a/json-logger/src/main/java/uk/bot_by/aws_lambda/slf4j/json_output/package-info.java b/json-logger/src/main/java/uk/bot_by/aws_lambda/slf4j/json_output/package-info.java new file mode 100644 index 0000000..c6a55c4 --- /dev/null +++ b/json-logger/src/main/java/uk/bot_by/aws_lambda/slf4j/json_output/package-info.java @@ -0,0 +1,7 @@ +/** + * An SLF4J Logger implementation for AWS Lambda with JSON output. + * + * @author Vitalij Berdinskih + * @since 1.0.0 + */ +package uk.bot_by.aws_lambda.slf4j.json_output; diff --git a/json-logger/src/main/resources/META-INF/services/uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput b/json-logger/src/main/resources/META-INF/services/uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput new file mode 100644 index 0000000..e4a1293 --- /dev/null +++ b/json-logger/src/main/resources/META-INF/services/uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput @@ -0,0 +1 @@ +uk.bot_by.aws_lambda.slf4j.json_output.JSONLoggerOutput \ No newline at end of file diff --git a/json-logger/src/test/java/uk/bot_by/aws_lambda/slf4j/json_output/JSONLoggerOutputTest.java b/json-logger/src/test/java/uk/bot_by/aws_lambda/slf4j/json_output/JSONLoggerOutputTest.java new file mode 100644 index 0000000..f43f371 --- /dev/null +++ b/json-logger/src/test/java/uk/bot_by/aws_lambda/slf4j/json_output/JSONLoggerOutputTest.java @@ -0,0 +1,354 @@ +package uk.bot_by.aws_lambda.slf4j.json_output; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.StringStartsWith.startsWith; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; + +import com.amazonaws.services.lambda.runtime.LambdaLogger; +import java.io.PrintStream; +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import org.json.JSONObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.helpers.BasicMarkerFactory; +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerConfiguration; + +@ExtendWith(MockitoExtension.class) +@Tag("fast") +class JSONLoggerOutputTest { + + @Mock + private AWSLambdaLoggerConfiguration configuration; + @Mock + private LambdaLogger lambdaLogger; + @Spy + private JSONLoggerOutput loggerOutput; + @Captor + private ArgumentCaptor stringCaptor; + + @AfterEach + void tearDown() { + MDC.clear(); + } + + @DisplayName("Happy path") + @Test + void happyPath() { + // given + doNothing().when(loggerOutput).log(any(), any(), any(), any(), anyString(), any()); + + // when and then + assertDoesNotThrow( + () -> loggerOutput.log(configuration, null, Level.ERROR, "test error message", null)); + + verify(loggerOutput).log(isA(AWSLambdaLoggerConfiguration.class), isA(LambdaLogger.class), + isNull(), isA(Level.class), anyString(), isNull()); + } + + @DisplayName("Happy path with a marker") + @Test + void happyPathWithMarker() { + // given + var marker = new BasicMarkerFactory().getMarker("aMarker"); + + doNothing().when(loggerOutput).log(any(), any(), any(), any(), anyString(), any()); + + // when and then + assertDoesNotThrow( + () -> loggerOutput.log(configuration, marker, Level.ERROR, "test error message", null)); + + verify(loggerOutput).log(isA(AWSLambdaLoggerConfiguration.class), isA(LambdaLogger.class), + isA(Marker.class), isA(Level.class), anyString(), isNull()); + } + + @DisplayName("Happy path with a throwable") + @Test + void happyPathWithThrowable() { + // given + var throwable = new Throwable("test throwable"); + + doNothing().when(loggerOutput).log(any(), any(), any(), any(), anyString(), any()); + + // when and then + assertDoesNotThrow( + () -> loggerOutput.log(configuration, null, Level.ERROR, "test error message", throwable)); + + verify(loggerOutput).log(isA(AWSLambdaLoggerConfiguration.class), isA(LambdaLogger.class), + isNull(), isA(Level.class), anyString(), isA(Throwable.class)); + } + + @DisplayName("Default log message") + @Test + void logMessage() { + // given + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals("{\"level\":\"ERROR\",\"message\":\"test error message\"}", + stringCaptor.getValue(), true); + } + + @DisplayName("Marker") + @Test + void marker() { + // given + var marker = new BasicMarkerFactory().getMarker("aMarker"); + + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, marker, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals( + "{\"level\":\"ERROR\",\"markers\":[\"aMarker\"],\"message\":\"test error message\"}", + stringCaptor.getValue(), true); + } + + @DisplayName("Markers") + @Test + void markers() { + // given + var markerFactory = new BasicMarkerFactory(); + var marker = markerFactory.getMarker("aMarker"); + marker.add(markerFactory.getMarker("marker a")); + marker.add(markerFactory.getMarker("marker 1")); + marker.add(markerFactory.getMarker("marker *")); + + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, marker, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals( + "{\"level\":\"ERROR\",\"markers\":[\"aMarker\",\"marker a\",\"marker 1\",\"marker *\"],\"message\":\"test error message\"}", + stringCaptor.getValue(), true); + } + + @DisplayName("Show relative time") + @Test + void relativeTime() { + // given + when(configuration.requestId()).thenReturn("request#"); + when(configuration.showDateTime()).thenReturn(true); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + var jsonObject = new JSONObject(stringCaptor.getValue()); + + assertAll("relative time", + () -> assertTrue(jsonObject.has("relative-timestamp"), "field exists"), + () -> assertDoesNotThrow(() -> jsonObject.getLong("relative-timestamp"), "field value")); + } + + @DisplayName("Show timestamp") + @Test + void timestamp() { + // given + var dateTimeFormat = new DateFormat() { + + @Override + public StringBuffer format(java.util.Date date, StringBuffer toAppendTo, + FieldPosition fieldPosition) { + return toAppendTo.append("1/1/1970 0:00"); + } + + @Override + public java.util.Date parse(String source, ParsePosition pos) { + return null; + } + + }; + + when(configuration.dateTimeFormat()).thenReturn(dateTimeFormat); + when(configuration.requestId()).thenReturn("request#"); + when(configuration.showDateTime()).thenReturn(true); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals( + "{\"level\":\"ERROR\",\"message\":\"test error message\",\"timestamp\":\"1/1/1970 0:00\"}", + stringCaptor.getValue(), true); + } + + @DisplayName("Show AWS request ID") + @Test + void requestId() { + // given + MDC.put("request#", "123-456-789-abc-0"); + + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals( + "{\"level\":\"ERROR\",\"message\":\"test error message\",\"aws-request-id\":\"123-456-789-abc-0\"}", + stringCaptor.getValue(), true); + } + + @DisplayName("Show a thread name") + @Test + void showThreadName() { + // given + Thread.currentThread().setName("test thread"); + + when(configuration.requestId()).thenReturn("request#"); + when(configuration.showThreadName()).thenReturn(true); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals( + "{\"level\":\"ERROR\",\"message\":\"test error message\",\"thread-name\":\"test thread\"}", + stringCaptor.getValue(), true); + } + + @DisplayName("Show a thread id") + @Test + void showThreadId() { + // given + when(configuration.requestId()).thenReturn("request#"); + when(configuration.showThreadId()).thenReturn(true); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + var jsonObject = new JSONObject(stringCaptor.getValue()); + + assertAll("thread ID", () -> assertTrue(jsonObject.has("thread-id"), "field exists"), + () -> assertDoesNotThrow(() -> jsonObject.getLong("thread-id"), "field value")); + } + + @DisplayName("Show a log name") + @Test + void showLogName() { + // given + when(configuration.logName()).thenReturn("com.example.TestLogger"); + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals( + "{\"level\":\"ERROR\",\"message\":\"test error message\",\"logname\":\"com.example.TestLogger\"}", + stringCaptor.getValue(), true); + } + + @DisplayName("Print a throwable") + @Test + void throwableWithMessage() { + // given + var throwable = mock(Throwable.class); + + doAnswer(invocationOnMock -> { + invocationOnMock.getArgument(0, PrintStream.class).println("*"); + return null; + }).when(throwable).printStackTrace(isA(PrintStream.class)); + when(throwable.getMessage()).thenReturn("test message"); + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", + throwable); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + var jsonObject = new JSONObject(stringCaptor.getValue()); + + assertAll("throwable", () -> assertTrue(jsonObject.has("throwable-class")), + () -> assertThat("class", jsonObject.getString("throwable-class"), + equalTo("java.lang.Throwable")), () -> assertTrue(jsonObject.has("throwable-message")), + () -> assertThat("message", jsonObject.getString("throwable-message"), + equalTo("test message")), + () -> assertTrue(jsonObject.has("stack-trace"), "field exists"), + () -> assertThat("field value", jsonObject.getString("stack-trace"), startsWith("*"))); + } + + @DisplayName("Print a throwable without message") + @Test + void throwableWithoutMessage() { + // given + var throwable = mock(Throwable.class); + + doAnswer(invocationOnMock -> { + invocationOnMock.getArgument(0, PrintStream.class).println("*"); + return null; + }).when(throwable).printStackTrace(isA(PrintStream.class)); + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", + throwable); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + var jsonObject = new JSONObject(stringCaptor.getValue()); + + assertAll("throwable", () -> assertTrue(jsonObject.has("throwable-class")), + () -> assertThat("class", jsonObject.getString("throwable-class"), + equalTo("java.lang.Throwable")), () -> assertFalse(jsonObject.has("throwable-message")), + () -> assertTrue(jsonObject.has("stack-trace"), "field exists"), + () -> assertThat("field value", jsonObject.getString("stack-trace"), startsWith("*"))); + } + +} \ No newline at end of file diff --git a/logger/pom.xml b/logger/pom.xml new file mode 100644 index 0000000..58b835c --- /dev/null +++ b/logger/pom.xml @@ -0,0 +1,87 @@ + + + + aws-lambda-slf4j-logger + + + + maven-surefire-plugin + org.apache.maven.plugins + + + jacoco-maven-plugin + org.jacoco + + + + + + annotations + org.jetbrains + provided + + + aws-lambda-java-core + com.amazonaws + + + slf4j-api + org.slf4j + + + aws-lambda-slf4j-core + io.github.vitalijr2.aws-lambda + 1.1.1 + + + + junit-jupiter-api + org.junit.jupiter + test + + + junit-jupiter-engine + org.junit.jupiter + test + + + mockito-core + org.mockito + test + + + mockito-junit-jupiter + org.mockito + test + + + hamcrest + org.hamcrest + test + + + An SLF4J Logger implementation for AWS Lambda + 4.0.0 + SLF4J for AWS Lambda : Logger + + aws-lambda-slf4j + io.github.vitalijr2.aws-lambda + 1.1.1 + + diff --git a/logger/src/main/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/LambdaLoggerOutput.java b/logger/src/main/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/LambdaLoggerOutput.java new file mode 100644 index 0000000..9a0bff4 --- /dev/null +++ b/logger/src/main/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/LambdaLoggerOutput.java @@ -0,0 +1,149 @@ +/* + * Copyright 2022-2024 Vitalij Berdinskih + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package uk.bot_by.aws_lambda.slf4j.lambda_logger; + +import static java.util.Objects.nonNull; + +import com.amazonaws.services.lambda.runtime.LambdaLogger; +import com.amazonaws.services.lambda.runtime.LambdaRuntime; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.text.DateFormat; +import java.util.Date; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.VisibleForTesting; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerConfiguration; +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput; + +/** + * An SLF4J Logger implementation for AWS Lambda. + */ +public class LambdaLoggerOutput implements AWSLambdaLoggerOutput { + + private static final char LEFT_BRACKET = '['; + private static final String LOG_NAME_SEPARATOR = " - "; + private static final char RIGHT_BRACKET = ']'; + private static final char SPACE = ' '; + private static final Long START_TIME = System.currentTimeMillis(); + private static final String THREAD = "thread="; + + private static void addLevel(AWSLambdaLoggerConfiguration configuration, Level level, + StringBuilder builder) { + if (configuration.levelInBrackets()) { + builder.append(LEFT_BRACKET).append(level).append(RIGHT_BRACKET); + } else { + builder.append(level); + } + builder.append(SPACE); + } + + private static void addLogName(AWSLambdaLoggerConfiguration configuration, + StringBuilder builder) { + if (nonNull(configuration.logName())) { + builder.append(configuration.logName()); + builder.append(LOG_NAME_SEPARATOR); + } + } + + private static void addRequestId(AWSLambdaLoggerConfiguration configuration, + StringBuilder builder) { + if (nonNull(MDC.get(configuration.requestId()))) { + builder.append(MDC.get(configuration.requestId())).append(SPACE); + } + } + + private static void addThread(AWSLambdaLoggerConfiguration configuration, StringBuilder builder) { + if (configuration.showThreadName()) { + builder.append(LEFT_BRACKET).append(Thread.currentThread().getName()).append(RIGHT_BRACKET) + .append(SPACE); + } + if (configuration.showThreadId()) { + builder.append(THREAD).append(Thread.currentThread().getId()).append(SPACE); + } + } + + @SuppressWarnings("ConstantConditions") + private static void addTimestamp(AWSLambdaLoggerConfiguration configuration, + StringBuilder builder) { + if (configuration.showDateTime()) { + if (nonNull(configuration.dateTimeFormat())) { + builder.append(getFormattedDate(configuration.dateTimeFormat())); + } else { + builder.append(System.currentTimeMillis() - START_TIME); + } + builder.append(SPACE); + } + } + + private static String getFormattedDate(DateFormat dateFormat) { + String dateText; + + synchronized (START_TIME) { + dateText = dateFormat.format(new Date()); + } + + return dateText; + } + + /** + * Write a message to the AWS lambda log. + * + * @param configuration logging configuration + * @param marker logging marker + * @param level logging level + * @param message logging message + * @param throwable exception + */ + @Override + public void log(@NotNull AWSLambdaLoggerConfiguration configuration, @Nullable Marker marker, + @NotNull Level level, @NotNull String message, @Nullable Throwable throwable) { + log(configuration, getLambdaLogger(), marker, level, message, throwable); + } + + @VisibleForTesting + LambdaLogger getLambdaLogger() { + return LambdaRuntime.getLogger(); + } + + @VisibleForTesting + void log(@NotNull AWSLambdaLoggerConfiguration configuration, @NotNull LambdaLogger lambdaLogger, + @Nullable Marker marker, @NotNull Level level, @NotNull String message, + @Nullable Throwable throwable) { + StringBuilder builder = new StringBuilder(); + + addRequestId(configuration, builder); + addTimestamp(configuration, builder); + addThread(configuration, builder); + addLevel(configuration, level, builder); + addLogName(configuration, builder); + builder.append(message); + if (nonNull(throwable)) { + var stackTraceOutputStream = new ByteArrayOutputStream(); + + throwable.printStackTrace(new PrintStream(stackTraceOutputStream)); + builder.append(System.lineSeparator()).append(stackTraceOutputStream); + } + + synchronized (START_TIME) { + lambdaLogger.log(builder.toString()); + } + } + +} diff --git a/logger/src/main/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/package-info.java b/logger/src/main/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/package-info.java new file mode 100644 index 0000000..46551c7 --- /dev/null +++ b/logger/src/main/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/package-info.java @@ -0,0 +1,7 @@ +/** + * An SLF4J Logger implementation for AWS Lambda. + * + * @author Vitalij Berdinskih + * @since 1.0.0 + */ +package uk.bot_by.aws_lambda.slf4j.lambda_logger; diff --git a/logger/src/main/resources/META-INF/services/uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput b/logger/src/main/resources/META-INF/services/uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput new file mode 100644 index 0000000..3ecb1df --- /dev/null +++ b/logger/src/main/resources/META-INF/services/uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerOutput @@ -0,0 +1 @@ +uk.bot_by.aws_lambda.slf4j.lambda_logger.LambdaLoggerOutput \ No newline at end of file diff --git a/logger/src/test/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/LambdaLoggerOutputTest.java b/logger/src/test/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/LambdaLoggerOutputTest.java new file mode 100644 index 0000000..49571d5 --- /dev/null +++ b/logger/src/test/java/uk/bot_by/aws_lambda/slf4j/lambda_logger/LambdaLoggerOutputTest.java @@ -0,0 +1,271 @@ +package uk.bot_by.aws_lambda.slf4j.lambda_logger; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.StringStartsWith.startsWith; +import static org.hamcrest.text.MatchesPattern.matchesPattern; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.amazonaws.services.lambda.runtime.LambdaLogger; +import java.io.PrintStream; +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.helpers.BasicMarkerFactory; +import uk.bot_by.aws_lambda.slf4j.AWSLambdaLoggerConfiguration; + +@ExtendWith(MockitoExtension.class) +@Tag("fast") +class LambdaLoggerOutputTest { + + @Mock + private AWSLambdaLoggerConfiguration configuration; + @Mock + private LambdaLogger lambdaLogger; + @Spy + private LambdaLoggerOutput loggerOutput; + @Captor + private ArgumentCaptor stringCaptor; + + @AfterEach + void tearDown() { + MDC.clear(); + } + + @DisplayName("Happy path") + @Test + void happyPath() { + // given + doNothing().when(loggerOutput).log(any(), any(), any(), any(), anyString(), any()); + + // when and then + assertDoesNotThrow( + () -> loggerOutput.log(configuration, null, Level.ERROR, "test error message", null)); + + verify(loggerOutput).log(isA(AWSLambdaLoggerConfiguration.class), isA(LambdaLogger.class), + isNull(), isA(Level.class), anyString(), isNull()); + } + + @DisplayName("Happy path with a marker") + @Test + void happyPathWithMarker() { + // given + var marker = new BasicMarkerFactory().getMarker("aMarker"); + + doNothing().when(loggerOutput).log(any(), any(), any(), any(), anyString(), any()); + + // when and then + assertDoesNotThrow( + () -> loggerOutput.log(configuration, marker, Level.ERROR, "test error message", null)); + + verify(loggerOutput).log(isA(AWSLambdaLoggerConfiguration.class), isA(LambdaLogger.class), + isA(Marker.class), isA(Level.class), anyString(), isNull()); + } + + @DisplayName("Happy path with a throwable") + @Test + void happyPathWithThrowable() { + // given + var throwable = new Throwable("test throwable"); + + doNothing().when(loggerOutput).log(any(), any(), any(), any(), anyString(), any()); + + // when and then + assertDoesNotThrow( + () -> loggerOutput.log(configuration, null, Level.ERROR, "test error message", throwable)); + + verify(loggerOutput).log(isA(AWSLambdaLoggerConfiguration.class), isA(LambdaLogger.class), + isNull(), isA(Level.class), anyString(), isA(Throwable.class)); + } + + @DisplayName("Default log message") + @Test + void logMessage() { + // given + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals("ERROR test error message", stringCaptor.getValue()); + } + + @DisplayName("Show relative time") + @Test + void relativeTime() { + // given + when(configuration.requestId()).thenReturn("request#"); + when(configuration.showDateTime()).thenReturn(true); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertThat(stringCaptor.getValue(), matchesPattern("\\d+ ERROR test error message")); + } + + @DisplayName("Show timestamp") + @Test + void timestamp() { + // given + var dateTimeFormat = new DateFormat() { + + @Override + public StringBuffer format(java.util.Date date, StringBuffer toAppendTo, + FieldPosition fieldPosition) { + return toAppendTo.append("1/1/1970 0:00"); + } + + @Override + public java.util.Date parse(String source, ParsePosition pos) { + return null; + } + + }; + + when(configuration.dateTimeFormat()).thenReturn(dateTimeFormat); + when(configuration.requestId()).thenReturn("request#"); + when(configuration.showDateTime()).thenReturn(true); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals("1/1/1970 0:00 ERROR test error message", stringCaptor.getValue()); + } + + @DisplayName("Show AWS request ID") + @Test + void requestId() { + // given + MDC.put("request#", "123-456-789-abc-0"); + + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals("123-456-789-abc-0 ERROR test error message", stringCaptor.getValue()); + } + + @DisplayName("Show a thread name") + @Test + void showThreadName() { + // given + Thread.currentThread().setName("test thread"); + + when(configuration.requestId()).thenReturn("request#"); + when(configuration.showThreadName()).thenReturn(true); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals("[test thread] ERROR test error message", stringCaptor.getValue()); + } + + @DisplayName("Show a thread id") + @Test + void showThreadId() { + // given + when(configuration.requestId()).thenReturn("request#"); + when(configuration.showThreadId()).thenReturn(true); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertThat(stringCaptor.getValue(), matchesPattern("thread=\\d+ ERROR test error message")); + } + + @DisplayName("Show a level in brackets") + @Test + void showLevelInBrackets() { + // given + when(configuration.levelInBrackets()).thenReturn(true); + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals("[ERROR] test error message", stringCaptor.getValue()); + } + + @DisplayName("Show a log name") + @Test + void showLogName() { + // given + when(configuration.logName()).thenReturn("com.example.TestLogger"); + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", null); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertEquals("ERROR com.example.TestLogger - test error message", stringCaptor.getValue()); + } + + @DisplayName("Print a stack trace") + @Test + void stackTrace() { + // given + var throwable = mock(Throwable.class); + + doAnswer(invocationOnMock -> { + invocationOnMock.getArgument(0, PrintStream.class).println("*"); + return null; + }).when(throwable).printStackTrace(isA(PrintStream.class)); + when(configuration.requestId()).thenReturn("request#"); + + // when + loggerOutput.log(configuration, lambdaLogger, null, Level.ERROR, "test error message", + throwable); + + // then + verify(lambdaLogger).log(stringCaptor.capture()); + + assertThat(stringCaptor.getValue(), startsWith("ERROR test error message\n*")); + } + +} \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..8d937f4 --- /dev/null +++ b/mvnw @@ -0,0 +1,308 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.2.0 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "$(uname)" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin ; then + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "\"$javaExecutable\"")" + fi + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$(cd "$wdir/.." || exit 1; pwd) + fi + # end of workaround + done + printf '%s' "$(cd "$basedir" || exit 1; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; + esac + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget > /dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..f80fbad --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,205 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d00a88b --- /dev/null +++ b/pom.xml @@ -0,0 +1,456 @@ + + + + aws-lambda-slf4j + + clean verify + + + + maven-clean-plugin + org.apache.maven.plugins + 3.3.2 + + + flatten-maven-plugin + + ossrh + + + + + flatten + + flatten + process-resources + + + + clean + + clean + clean + + + org.codehaus.mojo + 1.6.0 + + + templating-maven-plugin + + + + filter-sources + + filter-sources + + + org.codehaus.mojo + 3.0.0 + + + maven-resources-plugin + + ISO-8859-1 + + org.apache.maven.plugins + 3.3.1 + + + maven-compiler-plugin + + 11 + + org.apache.maven.plugins + 3.12.1 + + + maven-surefire-plugin + + + fast + + + org.apache.maven.plugins + 3.2.5 + + + maven-jar-plugin + + + + ${java.vm.version} (${java.vm.vendor}) + ${project.name} + + + + org.apache.maven.plugins + 3.3.0 + + + maven-failsafe-plugin + + 1 + + **/*Test.java + + + slow + + false + + + + + integration-test + verify + + + + org.apache.maven.plugins + 3.2.5 + + + jacoco-maven-plugin + + + + ${project.build.directory}/jacoco-ut.exec + + + prepare-agent + + prepare-agent + + + + prepare-agent-integration + + prepare-agent-integration + + + + ${project.build.directory}/jacoco.exec + + + ${project.build.directory} + + *.exec + + + + + + merge + + merge-results + verify + + + + ${project.build.directory}/jacoco.exec + ${project.reporting.outputDirectory}/jacoco + + + report + + report + verify + + + + ${project.build.directory}/jacoco.exec + + + BUNDLE + + + COMPLEXITY + 0.72 + COVEREDRATIO + + + + + + + check + + check-coverage + verify + + + org.jacoco + 0.8.11 + + + maven-source-plugin + org.apache.maven.plugins + 3.3.0 + + + maven-javadoc-plugin + org.apache.maven.plugins + ${javadoc-plugin.version} + + + sign-maven-plugin + org.simplify4u.plugins + 1.0.1 + + + central-publishing-maven-plugin + org.sonatype.central + 0.3.0 + + + + + + maven-enforcer-plugin + + + + [11,) + + + [3.9.0,) + + + + + + + enforce + + enforce-maven + + + + enforce + + enforce-clean + pre-clean + + + org.apache.maven.plugins + 3.4.1 + + + flatten-maven-plugin + org.codehaus.mojo + + + + + + + annotations + org.jetbrains + provided + 24.1.0 + + + aws-lambda-java-core + com.amazonaws + 1.2.3 + + + aws-lambda-java-events + com.amazonaws + 3.11.4 + + + slf4j-api + org.slf4j + ${slf4j.version} + + + + junit-jupiter-api + org.junit.jupiter + test + ${junit-jupiter.version} + + + junit-jupiter-engine + org.junit.jupiter + test + ${junit-jupiter.version} + + + junit-jupiter-params + org.junit.jupiter + test + ${junit-jupiter.version} + + + mockito-core + org.mockito + test + ${mockito.version} + + + mockito-junit-jupiter + org.mockito + test + ${mockito.version} + + + hamcrest + org.hamcrest + test + 2.2 + + + system-stubs-core + uk.org.webcompere + test + ${system-stubs.version} + + + system-stubs-jupiter + uk.org.webcompere + test + ${system-stubs.version} + + + + An SLF4J Logger implementation for AWS Lambda and CloudWatch. + + + vitalij_r2@outlook.com + vitalijr2 + Vitalij Berdinskih + Europe/Kyiv + https://github.com/vitalijr2 + + + io.github.vitalijr2.aws-lambda + 2022 + + + See NOTICE for third-party licenses. + repo + Apache 2 + https://www.apache.org/licenses/LICENSE-2.0.txt + + + 4.0.0 + + core + logger + json-logger + + SLF4J for AWS Lambda + pom + + + + clean deploy + + + maven-javadoc-plugin + + + + -J-Dhttp.agent=maven-javadoc-plugin_${project.groupId}:${project.artifactId} + + + + --allow-script-in-comments + + + ]]> + true + ${java.home}/bin/javadoc + + https://javadoc.io/doc/org.slf4j/slf4j-api/${slf4j.version}/ + + false + public + + + ]]> + + + + + jar + + attach-javadocs + + + org.apache.maven.plugins + + + maven-source-plugin + + + + jar + + attach-sources + + + org.apache.maven.plugins + + + central-publishing-maven-plugin + + central + true + + true + org.sonatype.central + + + sign-maven-plugin + + + + sign + + + + org.simplify4u.plugins + + + + release + + + + 3.6.3 + 5.10.2 + 5.10.0 + UTF-8 + 2.0.12 + 2.1.6 + + + scm:git:https://github.com/vitalijr2/aws-lambda-slf4j.git + scm:git:git@github.com:vitalijr2/aws-lambda-slf4j.git + https://github.com/vitalijr2/aws-lambda-slf4j + + https://github.com/vitalijr2/aws-lambda-slf4j + 1.1.1 + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..81f53bd --- /dev/null +++ b/readme.md @@ -0,0 +1,259 @@ +# SLF4J for AWS Lambda + +An [SLF4J][] Logger implementation for [AWS Lambda][lambda] +and [CloudWatch][cloudwatch]. + +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/ce44f4e6dfca46a893d1986b4747feca)](https://app.codacy.com/gh/vitalijr2/aws-lambda-slf4j/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) +[![Codacy Coverage](https://app.codacy.com/project/badge/Coverage/ce44f4e6dfca46a893d1986b4747feca)](https://app.codacy.com/gh/vitalijr2/aws-lambda-slf4j/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage) +[![Java Version](https://img.shields.io/static/v1?label=java&message=11&color=blue&logo=java&logoColor=E23D28)](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html) + +| Logger | Release | Javadoc | +|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------| +| **slf4j-aws-lambda-logger** | [![Maven Central](https://img.shields.io/maven-central/v/uk.bot-by/slf4j-aws-lambda-logger)](https://search.maven.org/artifact/uk.bot-by/slf4j-aws-lambda-logger) | [![Javadoc](https://javadoc.io/badge2/uk.bot-by/slf4j-aws-lambda-logger/javadoc.svg)](https://javadoc.io/doc/uk.bot-by/slf4j-aws-lambda-logger) | +| **slf4j-aws-lambda-json-logger** | [![Maven Central](https://img.shields.io/maven-central/v/uk.bot-by/slf4j-aws-lambda-json-logger)](https://search.maven.org/artifact/uk.bot-by/slf4j-aws-lambda-json-logger) | [![Javadoc](https://javadoc.io/badge2/uk.bot-by/slf4j-aws-lambda-json-logger/javadoc.svg)](https://javadoc.io/doc/uk.bot-by/slf4j-aws-lambda-json-logger) | + +## Table of Contents + +* [Getting started](#getting-started) + * [Usage](#usage) + * [Configuration](#configuration) + * [Setup a provider by a system property](#setup-a-provider-by-a-system-property) +* [Other solutions](#other-solutions) +* [Contributing](#contributing) +* [History](#history) +* [Authors and acknowledgment](#authors-and-acknowledgment) +* [License](#license) + +Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) + +## Getting started + +Yet another SLF4J Simple, isn't it? + +No, it isn't. + +This implementation supports [MDC][mdc] to print out **AWS request ID** +in start of every logging record and supports [Markers][marker] too. +And the killer feature: it solves +the [CRLF issue](https://twitter.com/ben11kehoe/status/1264597451010433025) +described by Frank Afriat in +[Solving the Java Aws Lambda logging problem][aws-lambda-logging-problem] - +you don't have to prepare logging messages +and stacktraces to log them on CloudWatch Logs. + +The footprint of **slf4j-aws-lambda** (88K) is same size +as **slf4j-simple** (79K) and much smaller than **logback** (888K). + +### Usage + +There is a great original [manual][manual]. + +The sample code: + +```java + +@Override +public String handleRequest(Map input, Context context) { + MDC.put("@aws-request-id@", context.getAwsRequestId()); + + logger.trace("trace message"); + logger.debug("debug message"); + logger.info("info message"); + logger.warn("warning message"); + logger.error("error message"); + + var marker = new BasicMarkerFactory().getMarker("important"); + + Stream.of("\n", "\r\n", "\r").forEach(injection -> { + logger.trace(marker, "CRLF{}injection", injection); + }); + + logger.warn("printable stacktrace", new Throwable("Printable Stacktrace Demo")); + return "done"; +} +``` + +The log with **slf4j-aws-lambda-logger**: + +```log +983f71e5-9091-443b-8c01-6668120c0e5d INFO uk.bot_by.slf4j_demo.BotHandler - info message +983f71e5-9091-443b-8c01-6668120c0e5d WARN uk.bot_by.slf4j_demo.BotHandler - warning message +983f71e5-9091-443b-8c01-6668120c0e5d ERROR uk.bot_by.slf4j_demo.BotHandler - error message +983f71e5-9091-443b-8c01-6668120c0e5d TRACE uk.bot_by.slf4j_demo.BotHandler - CRLF +injection +983f71e5-9091-443b-8c01-6668120c0e5d TRACE uk.bot_by.slf4j_demo.BotHandler - CRLF +injection +983f71e5-9091-443b-8c01-6668120c0e5d TRACE uk.bot_by.slf4j_demo.BotHandler - CRLF +injection +983f71e5-9091-443b-8c01-6668120c0e5d WARN uk.bot_by.slf4j_demo.BotHandler - printable stacktrace +``` + +There is a JSON option with **slf4j-aws-lambda-json-logger**: + +```json +{ + "level": "INFO", + "logname": "uk.bot_by.slf4j_demo.BotHandler", + "message": "info message", + "aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf" +} +{ + "level": "WARN", + "logname": "uk.bot_by.slf4j_demo.BotHandler", + "message": "warning message", + "aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf" +} +{ + "level": "ERROR", + "logname": "uk.bot_by.slf4j_demo.BotHandler", + "message": "error message", + "aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf" +} +{ + "level": "TRACE", + "logname": "uk.bot_by.slf4j_demo.BotHandler", + "message": "CRLF\ninjection", + "aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf" +} +{ + "level": "TRACE", + "logname": "uk.bot_by.slf4j_demo.BotHandler", + "message": "CRLF\r\ninjection", + "aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf" +} +{ + "level": "TRACE", + "logname": "uk.bot_by.slf4j_demo.BotHandler", + "message": "CRLF\rinjection", + "aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf" +} +{ + "stack-trace": "java.lang.Throwable: Printable Stacktrace Demo\n\tat uk.bot_by.slf4j_demo.BotHandler.handleRequest(BotHandler.java:36)\n\tat uk.bot_by.slf4j_demo.BotHandler.handleRequest(BotHandler.java:12)\n\tat lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:205)\n\tat lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:905)\n\tat lambdainternal.AWSLambda.startRuntime(AWSLambda.java:261)\n\tat lambdainternal.AWSLambda.startRuntime(AWSLambda.java:200)\n\tat lambdainternal.AWSLambda.main(AWSLambda.java:194)\n", + "level": "WARN", + "logname": "uk.bot_by.slf4j_demo.BotHandler", + "message": "printable stacktrace", + "aws-request-id": "7b9af47e-d861-44b4-bde7-fa2e84ffb7cf" +} +``` + +![CloudWatch logs](src/site/resources/cloudwatch-screenshot.png) + +### Configuration + +The configuration is similar to [SLF4J Simple][slf4j-simple]. + +It looks for the `lambda-logger.properties` resource and read properties: + +* **dateTimeFormat** - The date and time format to be used + in the output messages. The pattern describing the date + and time format is defined by [SimpleDateFormat][]. If the format is not + specified or is invalid, the number of milliseconds since start up + will be output. +* **defaultLogLevel** - Default log level for all instances of LambdaLogger. + Must be one of (_trace_, _debug_, _info_, _warn_, _error_), + a value is case-insensitive. If not specified, defaults to _info_. +* **levelInBrackets** - Should the level string be output in brackets? + Defaults to `false`. +* **log.a.b.c** - Logging detail level for a LambdaLogger instance + named _a.b.c_. +* **requestId** - Set the context name of AWS request ID. + Defaults to `AWS_REQUEST_ID`. +* **showDateTime** - Set to `true` if you want the current date + and time to be included in output messages. Defaults to `false`. +* **showLogName** - Set to `true` if you want the Logger instance name + to be included in output messages. Defaults to `true`. +* **showShortLogName** - Set to `true` if you want the last component + of the name to be included in output messages. Defaults to `false`. +* **showThreadId** - If you would like to output the current thread id, + then set to `true`. Defaults to `false`. +* **showThreadName** - Set to `true` if you want to output + the current thread name. Defaults to `false`. + +The environment variables overrides the properties: **LOG_AWS_REQUEST_ID**, +**LOG_DATE_TIME_FORMAT**, **LOG_DEFAULT_LEVEL**, **LOG_LEVEL_IN_BRACKETS**, +**LOG_SHOW_DATE_TIME**, **LOG_SHOW_NAME**, **LOG_SHOW_SHORT_NAME**, +**LOG_SHOW_THREAD_ID**, **LOG_SHOW_THREAD_NAME**. + +### Setup a provider by a system property + +[SLF4J 2.0.9][slf4j.provider] allows a provider to be explicitly specified. +Since AWS Lambda Environment does not provide any configuration options +to set what options should be used on startup, +the [trick is to use the JAVA_TOOL_OPTIONS][java-tool-options-trick] +environment variable. + +If your AWS Java Lambda has some SLF4J providers and you want +to point one of them, that needs to setup a System property +named `slf4j.provider`, as in the following: + +![Using JAVA_TOOL_OPTIONS to setup a provider](src/site/resources/environment-variable-screenshot.png) + +## Other solutions + +Other AWS centric loggers are [SLF4J/Logback Appender][awslambda-logback], +[slf4j-simple-lambda][], Logback's [CloudWatch appender][cloudwatch-appender] +and [CloudWatchLogs Java appender][cloudwatchlogs-java-appender]. + +## Contributing + +Please read [Contributing](contributing.md). + +## History + +See [Changelog](changelog.md) + +## Authors and acknowledgment + +* Replace the custom output to stdout with AWS LambdaLogger, the main idea from + @igorakkerman [SLF4J/Logback Appender][awslambda-logback]. + +## License + +Copyright 2022-2024 Vitalij Berdinskih + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +[http://www.apache.org/licenses/LICENSE-2.0][license] + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +[Apache License v2.0](LICENSE) +[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0.html) + +[SLF4J]: https://www.slf4j.org/ + +[lambda]: https://aws.amazon.com/lambda/ + +[cloudwatch]: https://aws.amazon.com/cloudwatch/ + +[mdc]: https://www.slf4j.org/manual.html#mdc "Mapped Diagnostic Context (MDC)" + +[marker]: https://www.slf4j.org/apidocs/org/slf4j/Marker.html + +[aws-lambda-logging-problem]: https://frank-afriat.medium.com/solving-the-java-aws-lambda-logging-problem-305b06df457f "Solving the Java Aws Lambda logging problem" + +[manual]: https://www.slf4j.org/manual.html "SLF4J user manual" + +[slf4j-simple]: https://www.slf4j.org/api/org/slf4j/simple/SimpleLogger.html + +[SimpleDateFormat]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/SimpleDateFormat.html + +[slf4j.provider]: https://jira.qos.ch/browse/SLF4J-450 "[SLF4J-450]: Allow binding to be explicitly specified" + +[java-tool-options-trick]: https://zenidas.wordpress.com/recipes/system-properties-for-a-java-lambda-function/ "System properties for a Java Lambda function" + +[awslambda-logback]: https://github.com/jlib-framework/jlib-awslambda-logback "jlib AWS Lambda SLF4J/Logback Appender" + +[slf4j-simple-lambda]: https://github.com/microlam-io/slf4j-simple-lambda + +[cloudwatch-appender]: https://github.com/sndyuk/logback-more-appenders "Logback more appenders" + +[cloudwatchlogs-java-appender]: https://github.com/boxfuse/cloudwatchlogs-java-appender + +[license]: http://www.apache.org/licenses/LICENSE-2.0 "Apache License, Version 2.0" diff --git a/src/site/resources/cloudwatch-screenshot.png b/src/site/resources/cloudwatch-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..460fc12e54d61be47fc87fcd897f8ed9ccec2654 GIT binary patch literal 208866 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

  • c9{_cji-c>m%@pn)5qygl{1IE>AZMn|Xk#6| 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 literal 0 HcmV?d00001 diff --git a/src/site/resources/environment-variable-screenshot.png b/src/site/resources/environment-variable-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..9634ac88cb3a06f2844d6f47a013319e981b2354 GIT binary patch literal 23979 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 LRcTQAXXJkYTSAji literal 0 HcmV?d00001