config = ProcessedTemplate.asMap(resource.getValue());
+
+ if (config.containsKey(ProcessedTemplate.CLAUSE_DEPENDS_ON)) {
+ Object dependsOn = config.get(ProcessedTemplate.CLAUSE_DEPENDS_ON);
+ config.put(ProcessedTemplate.CLAUSE_DEPENDS_ON, this.replaceDependenciesIn(dependsOn));
+ }
+
+ output.put(logicalId, config);
+ }
+
+ return output;
+ }
+
+ /**
+ * Handles DependsOn clause of single resource.
+ *
+ * @param dependsOn Depends on clause.
+ * @return Computed new DependsOn clause.
+ */
+ private Object replaceDependenciesIn(Object dependsOn) {
+ if (dependsOn instanceof List) {
+ return ((List>) dependsOn).stream()
+ .map(Object::toString)
+ .map(this::resolveDependency)
+ .collect(Collectors.toList());
+ } else {
+ return this.resolveDependency(dependsOn.toString());
+ }
+ }
+
+ /**
+ * Tries to resolve dependencies against lambda functions.
+ *
+ *
+ * Effective dependency will be LogGroup, to ensure no Lambda execution happens before log group creation.
+ *
+ *
+ * @param dependency Source dependency ID.
+ * @return Resolved dependency ID.
+ */
+ private String resolveDependency(String dependency) {
+ return this.resources.containsKey(dependency)
+ ? this.resources.get(dependency).getLogGroupLogicalId()
+ : dependency;
+ }
+
+ /**
+ * Safely converts value to a typed map.
+ *
+ * @param value Input object.
+ * @return Typed map.
+ */
+ private static Map asMap(Object value) {
+ Map output = new HashMap<>();
+
+ if (value instanceof Map) {
+ for (Map.Entry, ?> entry : ((Map, ?>) value).entrySet()) {
+ output.put(entry.getKey().toString(), entry.getValue());
+ }
+ }
+
+ return output;
+ }
+}
diff --git a/lambda-macro/lambda-macro-lambda-function/src/main/java/pl/wrzasq/lambda/macro/lambda/function/template/ResourcesDefinition.java b/lambda-macro/lambda-macro-lambda-function/src/main/java/pl/wrzasq/lambda/macro/lambda/function/template/ResourcesDefinition.java
new file mode 100644
index 000000000..ab0e59af2
--- /dev/null
+++ b/lambda-macro/lambda-macro-lambda-function/src/main/java/pl/wrzasq/lambda/macro/lambda/function/template/ResourcesDefinition.java
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the pl.wrzasq.lambda.
+ *
+ * @license http://mit-license.org/ The MIT license
+ * @copyright 2019 © by Rafał Wrzeszcz - Wrzasq.pl.
+ */
+
+package pl.wrzasq.lambda.macro.lambda.function.template;
+
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * Generic structure of resources section.
+ */
+@Data
+public class ResourcesDefinition {
+ /**
+ * Resource type.
+ */
+ @JsonProperty("Type")
+ private String type;
+
+ /**
+ * Resource properties.
+ */
+ @JsonProperty("Properties")
+ private Map properties;
+}
diff --git a/lambda-macro/lambda-macro-lambda-function/src/main/resources/logback.xml b/lambda-macro/lambda-macro-lambda-function/src/main/resources/logback.xml
new file mode 100644
index 000000000..27f1ea8bc
--- /dev/null
+++ b/lambda-macro/lambda-macro-lambda-function/src/main/resources/logback.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n%ex{full}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-macro/lambda-macro-lambda-function/src/site/markdown/guide/usage.md b/lambda-macro/lambda-macro-lambda-function/src/site/markdown/guide/usage.md
new file mode 100644
index 000000000..0123e81bc
--- /dev/null
+++ b/lambda-macro/lambda-macro-lambda-function/src/site/markdown/guide/usage.md
@@ -0,0 +1,128 @@
+
+
+# Using in CloudFormation
+
+This macro handler automates setup of additional Lambda function resources:
+
+- managed log group with customizable retention period;
+- memory consumption metric;
+- warnings logs filter metric;
+- errors logs filter metric;
+- errors metric alert.
+
+# Required permissions
+
+`lambda-macro-lambda-function` Needs no specific permissions, you may want to add following policies to it's role:
+
+- `arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole` (if you want to see **CloudWatch** logs of
+resource handler execution);
+- `arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess` (if you want more detailed tracing, package is built with
+**X-Ray** instrumentor).
+
+# Definition
+
+Type: `WrzasqPl::Lambda::Function`.
+
+## Properties
+
+All of the properties are transparently forwarder to
+[AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
+resource. Additionally following properties are available to customize extra resources:
+
+## `LogsRetentionInDays` - number
+
+Number of days for log retention (by default `7`).
+
+## `ErrorsFilterPattern` - string
+
+Log filter to detect error events (by default `ERROR -LOG_ERROR`).
+
+## `WarningsFilterPattern` - string
+
+Log filter to detect warning events (by default `WARN`).
+
+## `ErrorsAlarmActions` - string[]
+
+List of target ARNs that will receive notification when errors alarm is turned on.
+
+## Output values
+
+Any reference to `Ref` or `GetAtt` on this virtual resource will be replace by analogical call to physical
+`AWS::Lambda::Function` creation in place of it.
+
+**Note:** When you add this virtual resource to any `DependsOn` claus it will be replaced by log group dependency, to
+ensure any execution of created Lambda function will occur after creation of it's managed log group.
+
+# Example
+
+```yaml
+Transform:
+ - "WrzasqPlLambdaFunction"
+
+Resources:
+ EnhancedLambda:
+ Type: "WrzasqPl::Lambda::Function"
+ Properties:
+ Runtime: "java8"
+ Code:
+ # put your source bucket
+ S3Bucket: "your-bucket"
+ S3Key: "lambda-cform-account-1.0.4-standalone.jar"
+ Handler: "pl.wrzasq.lambda.cform.account.Handler::handle"
+ MemorySize: 256
+ Description: "AWS Account manager deployment."
+ Timeout: 300
+ TracingConfig:
+ Mode: "Active"
+ Role: !GetAtt "AccountManagerRole.Arn"
+ LogsRetentionInDays: 10
+ ErrorsFilterPattern: "error"
+ WarningsFilterPattern: "warning"
+ ErrorsAlarmActions:
+ - !Ref AlarmsQueue
+```
+
+# Installation
+
+```yaml
+ MacroFunctionRole:
+ Type: "AWS::IAM::Role"
+ Properties:
+ AssumeRolePolicyDocument:
+ Statement:
+ -
+ Action: "sts:AssumeRole"
+ Effect: "Allow"
+ Principal:
+ Service:
+ - "lambda.amazonaws.com"
+ ManagedPolicyArns:
+ - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
+
+ MacroFunction:
+ Type: "AWS::Serverless::Function"
+ Properties:
+ Runtime: "java8"
+ Code:
+ # put your source bucket
+ S3Bucket: "your-bucket"
+ S3Key: "lambda-macro-lambda-function-1.0.36-standalone.jar"
+ Handler: "pl.wrzasq.lambda.macro.lambda.function.Handler::handle"
+ MemorySize: 256
+ Description: "Custom CloudFormation macro handler."
+ Timeout: 300
+ TracingConfig:
+ Mode: "Active"
+ Role: !GetAtt "MacroFunctionRole.Arn"
+
+ Macro:
+ Type: "AWS::CloudFormation::Macro"
+ Properties:
+ Name: "WrzasqPlLambdaFunction"
+ FunctionName: !GetAtt "MacroFunction.Arn"
+```
diff --git a/lambda-macro/lambda-macro-lambda-function/src/site/site.xml b/lambda-macro/lambda-macro-lambda-function/src/site/site.xml
new file mode 100644
index 000000000..6d5cf9464
--- /dev/null
+++ b/lambda-macro/lambda-macro-lambda-function/src/site/site.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-macro/lambda-macro-lambda-function/src/test/java/test/pl/wrzasq/lambda/macro/lambda/function/HandlerTest.java b/lambda-macro/lambda-macro-lambda-function/src/test/java/test/pl/wrzasq/lambda/macro/lambda/function/HandlerTest.java
new file mode 100644
index 000000000..5c6426cc5
--- /dev/null
+++ b/lambda-macro/lambda-macro-lambda-function/src/test/java/test/pl/wrzasq/lambda/macro/lambda/function/HandlerTest.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the pl.wrzasq.lambda.
+ *
+ * @license http://mit-license.org/ The MIT license
+ * @copyright 2019 © by Rafał Wrzeszcz - Wrzasq.pl.
+ */
+
+package test.pl.wrzasq.lambda.macro.lambda.function;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import pl.wrzasq.lambda.macro.lambda.function.Handler;
+import pl.wrzasq.lambda.macro.lambda.function.model.CloudFormationMacroRequest;
+import pl.wrzasq.lambda.macro.lambda.function.model.CloudFormationMacroResponse;
+import pl.wrzasq.lambda.macro.lambda.function.template.ProcessedTemplate;
+
+@ExtendWith(MockitoExtension.class)
+public class HandlerTest {
+ @Mock
+ private ProcessedTemplate template;
+
+ @Mock
+ private Function