This is an automated email from the ASF dual-hosted git repository.

sgoeschl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/freemarker-generator.git


The following commit(s) were added to refs/heads/master by this push:
     new dba2617  FREEMARKER-181 Support custom pattern definitions for Grok 
tool (#33)
dba2617 is described below

commit dba26177c05142e80301d979eb0edb00fc04a8a3
Author: Siegfried Goeschl <[email protected]>
AuthorDate: Mon May 24 17:47:11 2021 +0200

    FREEMARKER-181 Support custom pattern definitions for Grok tool (#33)
---
 .../generator/datasource/DataSourceLoaderTest.java |   1 +
 freemarker-generator-cli/CHANGELOG.md              |   3 +
 freemarker-generator-cli/pom.xml                   |   2 +
 .../src/app/examples/data/logs/server.01.log       |  14 +++
 .../src/app/examples/data/logs/server.02.log       |  13 +++
 .../templates/accesslog/combined-access.ftl        |   4 +-
 .../templates/logs/csv/serverlog-to-csv.ftl        |  50 +++++++++
 .../src/app/scripts/examples-win.args              | 109 +++++++++++++++++++
 .../src/app/scripts/examples.args                  | 109 +++++++++++++++++++
 .../src/app/scripts/run-examples.bat               |   3 +
 .../src/app/scripts/run-examples.sh                |   3 +
 .../site/markdown/cli/concepts/transformation.md   |  23 ++--
 .../site/markdown/cli/usage/parsing-with-grok.md   | 121 +++++++++++++++++++++
 .../site/markdown/cli/usage/running-examples.md    |  65 +----------
 .../src/site/markdown/index.md                     |   1 +
 .../freemarker/generator/cli/ExamplesTest.java     |   1 +
 freemarker-generator-tools/pom.xml                 |   2 +-
 .../freemarker/generator/tools/grok/GrokTool.java  |  49 +++++++--
 .../generator/tools/grok/impl/GrokWrapper.java     |  42 -------
 .../generator/tools/grok/GrokToolTest.java         |  35 +++++-
 pom.xml                                            |  11 +-
 travis.sh                                          |   1 +
 22 files changed, 529 insertions(+), 133 deletions(-)

diff --git 
a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceLoaderTest.java
 
b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceLoaderTest.java
index c1e8f36..dfd24ec 100644
--- 
a/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceLoaderTest.java
+++ 
b/freemarker-generator-base/src/test/java/org/apache/freemarker/generator/datasource/DataSourceLoaderTest.java
@@ -162,6 +162,7 @@ public class DataSourceLoaderTest {
     }
 
     @Test
+    @Ignore("TODO Travis build failed with: 'Environment variable not found: 
TRAVIS_TAG'")
     public void shouldCreateDataSourceFromEnvironmentVariable() {
         if (!hasEnvironmentVariables()) {
             return;
diff --git a/freemarker-generator-cli/CHANGELOG.md 
b/freemarker-generator-cli/CHANGELOG.md
index 3cbf959..13055af 100644
--- a/freemarker-generator-cli/CHANGELOG.md
+++ b/freemarker-generator-cli/CHANGELOG.md
@@ -5,6 +5,7 @@ All notable changes to this project will be documented in this 
file. We try to a
 ## 0.1.0-SNAPSHOT
 
 ### Added
+* [FREEMARKER-181] Support custom pattern definitions for Grok tool
 * Parse a list of `DataSources` for the various tools
 * [FREEMARKER-161] Allow multiple transformations on the CLI
 * [FREEMARKER-163] Integrate Java Faker library for test data generation
@@ -78,3 +79,5 @@ All notable changes to this project will be documented in 
this file. We try to a
 [FREEMARKER-174]: https://issues.apache.org/jira/browse/FREEMARKER-174
 [FREEMARKER-175]: https://issues.apache.org/jira/browse/FREEMARKER-175
 [FREEMARKER-176]: https://issues.apache.org/jira/browse/FREEMARKER-176
+[FREEMARKER-181]: https://issues.apache.org/jira/browse/FREEMARKER-181
+
diff --git a/freemarker-generator-cli/pom.xml b/freemarker-generator-cli/pom.xml
index c21d5d9..4984b36 100644
--- a/freemarker-generator-cli/pom.xml
+++ b/freemarker-generator-cli/pom.xml
@@ -76,6 +76,8 @@
                                 <copy file="NOTICE" 
todir="./target/appassembler" />
                                 <copy 
file="./src/app/scripts/run-examples.bat" todir="./target/appassembler" />
                                 <copy file="./src/app/scripts/run-examples.sh" 
todir="./target/appassembler" />
+                                <copy file="./src/app/scripts/examples.args" 
todir="./target/appassembler" />
+                                <copy 
file="./src/app/scripts/examples-win.args" todir="./target/appassembler" />
                                 <copy todir="./target/appassembler/config">
                                     <fileset dir="src/app/config" />
                                 </copy>
diff --git a/freemarker-generator-cli/src/app/examples/data/logs/server.01.log 
b/freemarker-generator-cli/src/app/examples/data/logs/server.01.log
new file mode 100644
index 0000000..c1edb4b
--- /dev/null
+++ b/freemarker-generator-cli/src/app/examples/data/logs/server.01.log
@@ -0,0 +1,14 @@
+2021-05-18 20:00:32,120 INFO  [aa.bb.ccc] (Thread-98) message response handled 
in: 1 ms; message counter: 2047; total message counter: 7093
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) 
FinancialAdviceServiceImpl.createPostingLines() : 123456789012345678
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) 
FinancialAdviceDAO.getCountryCode() countryCode : 40
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) 
FinancialAdviceServiceImpl.createPostingLines() : 123456789012345678
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) 
AuthorizationDAO.insertAuthorization() Start ...
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) 
FinancialAdviceServiceImpl.processFinancialAdvice() successfully insert before 
AUTHORIZATIONS: true
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) 
AuthorizationDAO.insertInterface() Start ...
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) 
FinancialAdviceServiceImpl.processFinancialAdvice() successfully inserted into 
DB: true
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) responding message 1230 
data
+2021-05-18 20:00:32,124 INFO  [aa.bb.ccc] (Thread-99) no remote configuration 
available, will create local context
+2021-05-18 20:00:32,140 INFO  [aa.bb.ccc] (Thread-99) writing bytes of message 
1230
+2021-05-18 20:00:32,140 INFO  [aa.bb.ccc] (Thread-99) message response handled 
in: 62 ms; message counter: 2048; total message counter: 7094
+2021-05-18 20:00:32,187 INFO  [aa.bb.ccc] (Thread-99) no remote configuration 
available, will create local context
+2021-05-18 20:00:32,187 INFO  [aa.bb.ccc] (Thread-99) no remote configuration 
available, will create local context
\ No newline at end of file
diff --git a/freemarker-generator-cli/src/app/examples/data/logs/server.02.log 
b/freemarker-generator-cli/src/app/examples/data/logs/server.02.log
new file mode 100644
index 0000000..e603015
--- /dev/null
+++ b/freemarker-generator-cli/src/app/examples/data/logs/server.02.log
@@ -0,0 +1,13 @@
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) 
FinancialAdviceServiceImpl.createPostingLines() : 123456789012345678
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) 
FinancialAdviceDAO.getCountryCode() countryCode : 40
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) 
FinancialAdviceServiceImpl.createPostingLines() :  123456789012345678
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) 
AuthorizationDAO.insertAuthorization() Start ...
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) 
FinancialAdviceServiceImpl.processFinancialAdvice() successfully insert before 
AUTHORIZATIONS: true
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) 
AuthorizationDAO.insertInterface() Start ...
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) 
FinancialAdviceServiceImpl.processFinancialAdvice() successfully inserted into 
DB: true
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) responding message 1230 
data
+2021-05-18 21:00:32,124 INFO  [aa.bb.ccc] (Thread-97) no remote configuration 
available, will create local context
+2021-05-18 21:00:32,140 INFO  [aa.bb.ccc] (Thread-97) writing bytes of message 
1230
+2021-05-18 21:00:32,140 INFO  [aa.bb.ccc] (Thread-97) message response handled 
in: 162 ms; message counter: 2049; total message counter: 7095
+2021-05-18 21:00:32,187 INFO  [aa.bb.ccc] (Thread-97) no remote configuration 
available, will create local context
+2021-05-18 21:00:32,187 INFO  [aa.bb.ccc] (Thread-97) no remote configuration 
available, will create local context
\ No newline at end of file
diff --git 
a/freemarker-generator-cli/src/app/examples/templates/accesslog/combined-access.ftl
 
b/freemarker-generator-cli/src/app/examples/templates/accesslog/combined-access.ftl
index af78768..944a826 100644
--- 
a/freemarker-generator-cli/src/app/examples/templates/accesslog/combined-access.ftl
+++ 
b/freemarker-generator-cli/src/app/examples/templates/accesslog/combined-access.ftl
@@ -15,14 +15,14 @@
   specific language governing permissions and limitations
   under the License.
 -->
-<#assign grok = tools.grok.compile("%{COMBINEDAPACHELOG}")>
+<#assign grok = tools.grok.create("%{COMBINEDAPACHELOG}")>
 <#assign dataSource = dataSources?values[0]>
 <#assign lines = dataSource.getLineIterator()>
 
 <#compress>
     TIMESTAMP;VERB;REQUEST;HTTPVERSION
     <#list lines as line>
-        <#assign parts = grok.match(line)>
+        <#assign parts = grok.match(line).capture()>
         <#assign timestamp = parts.timestamp>
         <#assign verb = parts.verb>
         <#assign request = parts.request>
diff --git 
a/freemarker-generator-cli/src/app/examples/templates/logs/csv/serverlog-to-csv.ftl
 
b/freemarker-generator-cli/src/app/examples/templates/logs/csv/serverlog-to-csv.ftl
new file mode 100644
index 0000000..544975f
--- /dev/null
+++ 
b/freemarker-generator-cli/src/app/examples/templates/logs/csv/serverlog-to-csv.ftl
@@ -0,0 +1,50 @@
+<#ftl output_format="plainText" strip_whitespace=true>
+<#--
+  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.
+-->
+
+<#--
+    Define custom grok pattern as map to match something like using 
"MY_SERVERLOG"
+    2019-05-17 20:00:32,140 INFO  [xx.yyy.zzzz] (Thread-99) message response 
handled in: 62 ms; message counter: 2048; total message counter: 7094
+-->
+<#assign patternDefinitions = {
+"MY_DATE": "%{YEAR}-%{MONTHNUM}-%{MONTHDAY}",
+"MY_TIMESTAMP": "%{MY_DATE:date} %{TIME:time},%{INT:millis}",
+"MY_MODULE": "\\[%{NOTSPACE}\\]",
+"MY_THREAD": "\\(%{NOTSPACE}\\)",
+"MY_SERVERLOG": "^%{MY_TIMESTAMP} %{LOGLEVEL}%{SPACE:UNWANTED}%{MY_MODULE} 
%{MY_THREAD} message response handled in: %{INT:response_time} ms; 
%{GREEDYDATA:UNWANTED}$"
+}>
+
+<#-- Instantiante the grok tool -->
+<#assign grok = tools.grok.create("%{MY_SERVERLOG}", patternDefinitions)>
+
+<#-- Iterate over all data sources and convert matching lines to CSV output -->
+<#compress>
+    TIMESTAMP;MILLIS
+    <#if dataSources?has_content>
+        <#list dataSources?values as dataSource>
+            <#list dataSource.getLineIterator() as line>
+                <#assign parts = grok.match(line).capture()>
+                <#if parts?has_content>
+                    <#-- Skip all response times less than 5 ms because these 
are boring pings -->
+                    <#if parts.response_time?number gt 5>
+                        
${parts.date}T${parts.time}.${parts.millis}+02:00;${parts.response_time}
+                    </#if>
+                </#if>
+            </#list>
+        </#list>
+    </#if>
+</#compress>
\ No newline at end of file
diff --git a/freemarker-generator-cli/src/app/scripts/examples-win.args 
b/freemarker-generator-cli/src/app/scripts/examples-win.args
new file mode 100644
index 0000000..4219adf
--- /dev/null
+++ b/freemarker-generator-cli/src/app/scripts/examples-win.args
@@ -0,0 +1,109 @@
+#
+# 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.
+#
+
+# Proof of concept for pioclo's @-files support for Windows
+
+#############################################################################
+# Info
+#############################################################################
+
+-t freemarker-generator\info.ftl -s README.md -o target\out\info.txt
+
+#############################################################################
+# Demo
+#############################################################################
+
+-t examples\templates\demo.ftl -s README.md -o target\out\demo.txt
+
+#############################################################################
+# DataSources
+#############################################################################
+
+-t examples\templates\datasources.ftl -s :data=examples\data -o 
target\out\datasources-01.txt
+-t examples\templates\datasources.ftl -s https://xkcd.com\info.0.json -s 
https://www.google.com -o target\out\datasources-02.txt
+
+#############################################################################
+# CSV
+#############################################################################
+
+-t freemarker-generator\csv\html\transform.ftl -s 
examples\data\csv\contract.csv -o target\out\contract.html
+-t freemarker-generator\csv\md\transform.ftl -s examples\data\csv\contract.csv 
-o target\out\contract.md
+-t examples\templates\csv\shell\curl.ftl -s examples\data\csv\user.csv -o 
target\out\curl.sh
+
+#############################################################################
+# Grok
+#############################################################################
+
+-t examples\templates\accesslog\combined-access.ftl -s 
examples\data\accesslog\combined-access.log -o 
target\out\combined-access.log.txt
+-t examples\templates\logs\csv\serverlog-to-csv.ftl -s examples\data\logs -o 
target\out\server.log.csv
+
+#############################################################################
+# Excel
+#############################################################################
+
+-t examples\templates\excel\dataframe\transform.ftl -s 
examples\data\excel\test.xls -o target\out\test.xls.dataframe.txt
+-t freemarker-generator\excel\html\transform.ftl -s 
examples\data\excel\test.xls -o target\out\test.xls.html
+-t freemarker-generator\excel\html\transform.ftl -s 
examples\data\excel\test.xlsx -o target\out\test.xslx.html
+-t freemarker-generator\excel\html\transform.ftl -s 
examples\data\excel\test-multiple-sheets.xlsx -o 
target\out\test-multiple-sheets.xlsx.html
+-t freemarker-generator\excel\md\transform.ftl -s 
examples\data\excel\test-multiple-sheets.xlsx -o 
target\out\test-multiple-sheets.xlsx.md
+-t freemarker-generator\excel\csv\transform.ftl -s 
examples\data\excel\test-multiple-sheets.xlsx -o 
target\out\test-multiple-sheets.xlsx.csv
+
+#############################################################################
+# HTML
+#############################################################################
+
+-t examples\templates\html\csv\dependencies.ftl -s 
examples\data\html\dependencies.html -o target\out\dependencies.csv
+-t examples\templates\html\txt\licence.ftl -s 
examples\data\html\dependencies.html -o target\out\licence.txt
+
+#############################################################################
+# Java Faker
+#############################################################################
+
+-t examples\templates\javafaker\csv\testdata.ftl -o target\out\testdata.csv
+
+#############################################################################
+# JSON
+#############################################################################
+
+-t examples\templates\json\csv\swagger-endpoints.ftl -s 
examples\data\json\swagger-spec.json -o target\out\swagger-spec.csv
+-t freemarker-generator\json\yaml\transform.ftl -s 
examples\data\json\swagger-spec.json -o target\out\swagger-spec.yaml
+-t examples\templates\json\md\github-users.ftl -s 
examples\data\json\github-users.json -o target\out\github-users.md
+
+#############################################################################
+# Properties
+#############################################################################
+
+-t examples\templates\properties\csv\locker-test-users.ftl -s 
examples\data\properties -o target\out\locker-test-users.csv
+
+#############################################################################
+# Template Directory
+#############################################################################
+
+-t examples\data\template -PNGINX_HOSTNAME=localhost -o target\out\template
+
+#############################################################################
+# XML
+#############################################################################
+
+-t examples\templates\xml\txt\recipients.ftl -s 
examples\data\xml\recipients.xml -o target\out\recipients.txt
+
+#############################################################################
+# YAML
+#############################################################################
+
+-t examples\templates\yaml\txt\transform.ftl -s 
examples\data\yaml\customer.yaml -o target\out\customer.txt
+-t freemarker-generator\yaml\json\transform.ftl -s 
examples\data\yaml\swagger-spec.yaml -o target\out\swagger-spec.json
\ No newline at end of file
diff --git a/freemarker-generator-cli/src/app/scripts/examples.args 
b/freemarker-generator-cli/src/app/scripts/examples.args
new file mode 100644
index 0000000..c867988
--- /dev/null
+++ b/freemarker-generator-cli/src/app/scripts/examples.args
@@ -0,0 +1,109 @@
+#
+# 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.
+#
+
+# Proof of concept for pioclo's @-files support for Linux/MacOS
+
+#############################################################################
+# Info
+#############################################################################
+
+-t freemarker-generator/info.ftl -s README.md -o target/out/info.txt
+
+#############################################################################
+# Demo
+#############################################################################
+
+-t examples/templates/demo.ftl -s README.md -o target/out/demo.txt
+
+#############################################################################
+# DataSources
+#############################################################################
+
+-t examples/templates/datasources.ftl -s :data=examples/data -o 
target/out/datasources-01.txt
+-t examples/templates/datasources.ftl -s https://xkcd.com/info.0.json -s 
https://www.google.com -o target/out/datasources-02.txt
+
+#############################################################################
+# CSV
+#############################################################################
+
+-t freemarker-generator/csv/html/transform.ftl -s 
examples/data/csv/contract.csv -o target/out/contract.html
+-t freemarker-generator/csv/md/transform.ftl -s examples/data/csv/contract.csv 
-o target/out/contract.md
+-t examples/templates/csv/shell/curl.ftl -s examples/data/csv/user.csv -o 
target/out/curl.sh
+
+#############################################################################
+# Grok
+#############################################################################
+
+-t examples/templates/accesslog/combined-access.ftl -s 
examples/data/accesslog/combined-access.log -o 
target/out/combined-access.log.txt
+-t examples/templates/logs/csv/serverlog-to-csv.ftl -s examples/data/logs -o 
target/out/server.log.csv
+
+#############################################################################
+# Excel
+#############################################################################
+
+-t examples/templates/excel/dataframe/transform.ftl -s 
examples/data/excel/test.xls -o target/out/test.xls.dataframe.txt
+-t freemarker-generator/excel/html/transform.ftl -s 
examples/data/excel/test.xls -o target/out/test.xls.html
+-t freemarker-generator/excel/html/transform.ftl -s 
examples/data/excel/test.xlsx -o target/out/test.xslx.html
+-t freemarker-generator/excel/html/transform.ftl -s 
examples/data/excel/test-multiple-sheets.xlsx -o 
target/out/test-multiple-sheets.xlsx.html
+-t freemarker-generator/excel/md/transform.ftl -s 
examples/data/excel/test-multiple-sheets.xlsx -o 
target/out/test-multiple-sheets.xlsx.md
+-t freemarker-generator/excel/csv/transform.ftl -s 
examples/data/excel/test-multiple-sheets.xlsx -o 
target/out/test-multiple-sheets.xlsx.csv
+
+#############################################################################
+# HTML
+#############################################################################
+
+-t examples/templates/html/csv/dependencies.ftl -s 
examples/data/html/dependencies.html -o target/out/dependencies.csv
+-t examples/templates/html/txt/licence.ftl -s 
examples/data/html/dependencies.html -o target/out/licence.txt
+
+#############################################################################
+# Java Faker
+#############################################################################
+
+-t examples/templates/javafaker/csv/testdata.ftl -o target/out/testdata.csv
+
+#############################################################################
+# JSON
+#############################################################################
+
+-t examples/templates/json/csv/swagger-endpoints.ftl -s 
examples/data/json/swagger-spec.json -o target/out/swagger-spec.csv
+-t freemarker-generator/json/yaml/transform.ftl -s 
examples/data/json/swagger-spec.json -o target/out/swagger-spec.yaml
+-t examples/templates/json/md/github-users.ftl -s 
examples/data/json/github-users.json -o target/out/github-users.md
+
+#############################################################################
+# Properties
+#############################################################################
+
+-t examples/templates/properties/csv/locker-test-users.ftl -s 
examples/data/properties -o target/out/locker-test-users.csv
+
+#############################################################################
+# Template Directory
+#############################################################################
+
+-t examples/data/template -PNGINX_HOSTNAME=localhost -o target/out/template
+
+#############################################################################
+# XML
+#############################################################################
+
+-t examples/templates/xml/txt/recipients.ftl -s 
examples/data/xml/recipients.xml -o target/out/recipients.txt
+
+#############################################################################
+# YAML
+#############################################################################
+
+-t examples/templates/yaml/txt/transform.ftl -s 
examples/data/yaml/customer.yaml -o target/out/customer.txt
+-t freemarker-generator/yaml/json/transform.ftl -s 
examples/data/yaml/swagger-spec.yaml -o target/out/swagger-spec.json
\ No newline at end of file
diff --git a/freemarker-generator-cli/src/app/scripts/run-examples.bat 
b/freemarker-generator-cli/src/app/scripts/run-examples.bat
index 7ca035e..6512dca 100644
--- a/freemarker-generator-cli/src/app/scripts/run-examples.bat
+++ b/freemarker-generator-cli/src/app/scripts/run-examples.bat
@@ -105,6 +105,9 @@ REM 
=========================================================================
 echo "examples\templates\accesslog\combined-access.ftl"
 %FREEMARKER_CMD% -t examples\templates\accesslog\combined-access.ftl 
examples\data\accesslog\combined-access.log > target\out\combined-access.log.txt
 
+echo "examples\templates\logs\csv\serverlog-to-csv.ftl"
+%FREEMARKER_CMD% -t examples\templates\logs\csv\serverlog-to-csv.ftl 
examples\data\logs > target\out\server.log.csv 
+
 REM =========================================================================
 REM Excel
 REM =========================================================================
diff --git a/freemarker-generator-cli/src/app/scripts/run-examples.sh 
b/freemarker-generator-cli/src/app/scripts/run-examples.sh
index a0d316c..09d09af 100755
--- a/freemarker-generator-cli/src/app/scripts/run-examples.sh
+++ b/freemarker-generator-cli/src/app/scripts/run-examples.sh
@@ -125,6 +125,9 @@ $FREEMARKER_CMD -PCSV_SOURCE_DELIMITER=SEMICOLON 
-PCSV_SOURCE_WITH_HEADER=true -
 echo "examples/templates/accesslog/combined-access.ftl"
 $FREEMARKER_CMD -t examples/templates/accesslog/combined-access.ftl 
examples/data/accesslog/combined-access.log > 
target/out/combined-access.log.txt || { echo >&2 "Test failed.  Aborting."; 
exit 1; }
 
+echo "examples/templates/logs/csv/serverlog-to-csv.ftl"
+$FREEMARKER_CMD -t examples/templates/logs/csv/serverlog-to-csv.ftl 
examples/data/logs > target/out/server.log.csv || { echo >&2 "Test failed.  
Aborting."; exit 1; }
+
 #############################################################################
 # Excel
 #############################################################################
diff --git 
a/freemarker-generator-cli/src/site/markdown/cli/concepts/transformation.md 
b/freemarker-generator-cli/src/site/markdown/cli/concepts/transformation.md
index 11b1323..9b20e10 100644
--- a/freemarker-generator-cli/src/site/markdown/cli/concepts/transformation.md
+++ b/freemarker-generator-cli/src/site/markdown/cli/concepts/transformation.md
@@ -12,7 +12,7 @@ The `freemarker-generator` generates text output based on 
processing FreeMarker
 * When the output is written to a directory
     * the structure of the input directory is preserved
     * any `ftl` file extension is removed
-* Positional command line arguments are interpreted as `data sources` (or 
directories) and accessible by a `output generators`   
+* Positional command line arguments are interpreted as `data sources` (or 
directories) and accessible by a all `output generators`   
 
 ### Examples
 
@@ -69,14 +69,19 @@ target
         `-- nginx.conf
 ```
 
-Transforming multiple templates and data sources to multiple output files
+Defining multiple transformation on the command line can be clumsy but 
[Picolic's @-Files](https://picocli.info/#AtFiles) can help - the following 
`@-File` defined, e.g. `@examples.args`
 
 ```
-freemarker-generator \
--t freemarker-generator/yaml/json/transform.ftl -s 
examples/data/yaml/customer.yaml -o customer.json \
--t freemarker-generator/yaml/json/transform.ftl -s 
examples/data/yaml/swagger-spec.yaml -o swagger-spec.json
+#############################################################################
+# CSV
+#############################################################################
+
+-t freemarker-generator/csv/html/transform.ftl -s 
examples/data/csv/contract.csv -o target/out/contract.html
+-t freemarker-generator/csv/md/transform.ftl -s examples/data/csv/contract.csv 
-o target/out/contract.md
+```
 
-> ls -l *.json
--rw-r--r--  1 sgoeschl  staff   332B Jan  5 21:30 customer.json
--rw-r--r--  1 sgoeschl  staff    25K Jan  5 21:30 swagger-spec.json
-```  
+than multiple transformation can be invoked using the following command line
+
+```
+bin/freemarker-generator @examples.args 
+```
diff --git 
a/freemarker-generator-cli/src/site/markdown/cli/usage/parsing-with-grok.md 
b/freemarker-generator-cli/src/site/markdown/cli/usage/parsing-with-grok.md
new file mode 100644
index 0000000..5cbadda
--- /dev/null
+++ b/freemarker-generator-cli/src/site/markdown/cli/usage/parsing-with-grok.md
@@ -0,0 +1,121 @@
+## Parsing With Grok
+
+### Unleashing The Power Of Grok
+
+Think of `Grok` as modular regular expressions with a pre-defined 
functionality to parse access logs or any other data where you can't comprehend 
the regular expression any longer, one very simple example is `QUOTEDSTRING`
+
+```
+QUOTEDSTRING 
(?>(?<!\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``))
+```
+
+And with `Grok` the `QUOTEDSTRING` is just a building block for an even more 
complex regular expression such as `COMBINEDAPACHELOG`
+
+> bin/freemarker-generator -t examples/templates/accesslog/combined-access.ftl 
examples/data/accesslog/combined-access.log
+
+which gives you the following output
+
+```
+TIMESTAMP;VERB;REQUEST;HTTPVERSION
+19/Jun/2005:06:44:17 +0200;GET;/wximages/wxwidgets02-small.png;1.1
+19/Jun/2005:06:46:05 +0200;GET;/wximages/wxwidgets02-small.png;1.1
+19/Jun/2005:06:47:37 +0200;GET;/wximages/wxwidgets02-small.png;1.1
+19/Jun/2005:06:48:40 +0200;GET;/wiki.pl?WxWidgets_Bounties;1.1
+19/Jun/2005:06:50:49 
+0200;GET;/wiki.pl?WxWidgets_Compared_To_Other_Toolkits;1.1
+19/Jun/2005:06:50:49 +0200;GET;/wxwiki.css;1.1
+19/Jun/2005:06:50:49 +0200;GET;/wximages/wxwidgets02-small.png;1.1
+19/Jun/2005:06:50:50 +0200;GET;/favicon.ico;1.1
+19/Jun/2005:06:52:36 +0200;GET;/wximages/wxwidgets02-small.png;1.1
+19/Jun/2005:06:53:14 +0200;GET;/;1.0
+```
+
+using the following FreeMarker template
+
+```text
+<#ftl output_format="plainText" strip_whitespace=true>
+<#assign grok = tools.grok.create("%{COMBINEDAPACHELOG}")>
+<#assign dataSource = dataSources?values[0]>
+<#assign lines = dataSource.getLineIterator()>
+
+<#compress>
+    TIMESTAMP;VERB;REQUEST;HTTPVERSION
+    <#list lines as line>
+        <#assign parts = grok.match(line).capture()>
+        <#assign timestamp = parts["timestamp"]>
+        <#assign verb = parts["verb"]>
+        <#assign request = parts["request"]>
+        <#assign httpversion = parts["httpversion"]>
+        ${timestamp};${verb};${request};${httpversion}
+    </#list>
+</#compress>
+```
+
+While this looks small and tidy there are some nifty features
+
+* `tools.grok.compile("%{COMBINEDAPACHELOG}")` builds the `Grok` instance to 
parse access logs in `Combined Format`
+* The data source is streamed line by line and not loaded into memory in one 
piece
+* This also works for using `stdin` so are able to parse GB of access log or 
other files
+
+### Parse Server Log File And Generate CSV
+
+A more practical example consists of parsing dozens of server logs files to 
determine response time of message processing, e.g.
+
+```
+2021-05-18 20:00:32,140 INFO  [aa.bb.ccc] (Thread-99) message response handled 
in: 62 ms; message counter: 2048; total message counter: 7094
+```
+
+In technical terms the FTL 
+
+* Defines custom Grok pattern definitions
+* Compiles the Grok expression `MY_SERVERLOG`   
+* Reads through all data sources passed on the command line
+* Use Grok to match lines and extract the timestamp and response times
+* Skip all execution times less than 5 ms because these are `pings` we are not 
interested in  
+* Creates a simple CSV file
+
+```
+<#ftl output_format="plainText" strip_whitespace=true>
+<#--
+    Define custom grok pattern as map to match something like using 
"MY_SERVERLOG"
+    2019-05-17 20:00:32,140 INFO  [xx.yyy.zzzz] (Thread-99) message response 
handled in: 62 ms; message counter: 2048; total message counter: 7094
+-->
+<#assign patternDefinitions = {
+"MY_DATE": "%{YEAR}-%{MONTHNUM}-%{MONTHDAY}",
+"MY_TIMESTAMP": "%{MY_DATE:date} %{TIME:time},%{INT:millis}",
+"MY_MODULE": "\\[%{NOTSPACE}\\]",
+"MY_THREAD": "\\(%{NOTSPACE}\\)",
+"MY_SERVERLOG": "^%{MY_TIMESTAMP} %{LOGLEVEL}%{SPACE:UNWANTED}%{MY_MODULE} 
%{MY_THREAD} message response handled in: %{INT:response_time} ms; 
%{GREEDYDATA:UNWANTED}$"
+}>
+
+<#-- Instantiante the grok tool -->
+<#assign grok = tools.grok.create("%{MY_SERVERLOG}", patternDefinitions)>
+
+<#-- Iterate over all data sources and convert matching lines to CSV output -->
+<#compress>
+    TIMESTAMP;MILLIS
+    <#if dataSources?has_content>
+        <#list dataSources?values as dataSource>
+            <#list dataSource.getLineIterator() as line>
+                <#assign parts = grok.match(line).capture()>
+                <#if parts?has_content>
+                    <#-- Skip all response times less than 5 ms because these 
are boring pings -->
+                    <#if parts.response_time?number gt 5>
+                        
${parts.date}T${parts.time}.${parts.millis}+02:00;${parts.response_time}
+                    </#if>
+                </#if>
+            </#list>
+        </#list>
+    </#if>
+</#compress>
+```
+Executing the FTL yields the following output
+
+```
+> bin/freemarker-generator -t examples/templates/logs/csv/serverlog-to-csv.ftl 
examples/data/logs; echo
+TIMESTAMP;MILLIS
+2021-05-18T20:00:32.140;62
+2021-05-18T21:00:32.140;162
+```
+
+### Performance Considerations
+
+When processing large logfiles you may experience performance issues - using 
regexp anchors as decribed in [Killing your Logstash performance with 
Grok](https://medium.com/@momchil.dev/killing-your-logstash-performance-with-grok-f5f23ae47956)
 might help. Using regexp anchors reduced the execution time by 50% when 
parsing through 3 GB of logs with only small percentage of matching lines.
diff --git 
a/freemarker-generator-cli/src/site/markdown/cli/usage/running-examples.md 
b/freemarker-generator-cli/src/site/markdown/cli/usage/running-examples.md
index d13b2f2..e4cc875 100644
--- a/freemarker-generator-cli/src/site/markdown/cli/usage/running-examples.md
+++ b/freemarker-generator-cli/src/site/markdown/cli/usage/running-examples.md
@@ -649,62 +649,7 @@ time,user,status,duration,size
 2019-09-27T21:02:54,DDDDDDD,200,0.528268,206
 ```
 
-### 10. Unleashing The Power Of Grok
-
-Think of `Grok` as modular regular expressions with a pre-defined 
functionality to parse access logs or any other data where you can't comprehend 
the regular expression any longer, one very simple example is `QUOTEDSTRING`
-
-```
-QUOTEDSTRING 
(?>(?<!\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``))
-```
-
-And with `Grok` the `QUOTEDSTRING` is just a building block for an even more 
complex regular expression such as `COMBINEDAPACHELOG`
-
-> bin/freemarker-generator -t examples/templates/accesslog/combined-access.ftl 
examples/data/accesslog/combined-access.log 
-
-which gives you the following output
-
-```
-TIMESTAMP;VERB;REQUEST;HTTPVERSION
-19/Jun/2005:06:44:17 +0200;GET;/wximages/wxwidgets02-small.png;1.1
-19/Jun/2005:06:46:05 +0200;GET;/wximages/wxwidgets02-small.png;1.1
-19/Jun/2005:06:47:37 +0200;GET;/wximages/wxwidgets02-small.png;1.1
-19/Jun/2005:06:48:40 +0200;GET;/wiki.pl?WxWidgets_Bounties;1.1
-19/Jun/2005:06:50:49 
+0200;GET;/wiki.pl?WxWidgets_Compared_To_Other_Toolkits;1.1
-19/Jun/2005:06:50:49 +0200;GET;/wxwiki.css;1.1
-19/Jun/2005:06:50:49 +0200;GET;/wximages/wxwidgets02-small.png;1.1
-19/Jun/2005:06:50:50 +0200;GET;/favicon.ico;1.1
-19/Jun/2005:06:52:36 +0200;GET;/wximages/wxwidgets02-small.png;1.1
-19/Jun/2005:06:53:14 +0200;GET;/;1.0
-```
-
-using the following FreeMarker template
-
-```text
-<#ftl output_format="plainText" strip_whitespace=true>
-<#assign grok = tools.grok.compile("%{COMBINEDAPACHELOG}")>
-<#assign dataSource = dataSources?values[0]>
-<#assign lines = dataSource.getLineIterator()>
-
-<#compress>
-    TIMESTAMP;VERB;REQUEST;HTTPVERSION
-    <#list lines as line>
-        <#assign parts = grok.match(line)>
-        <#assign timestamp = parts["timestamp"]>
-        <#assign verb = parts["verb"]>
-        <#assign request = parts["request"]>
-        <#assign httpversion = parts["httpversion"]>
-        ${timestamp};${verb};${request};${httpversion}
-    </#list>
-</#compress>
-```
-
-While this looks small and tidy there are some nifty features
-
-* `tools.grok.compile("%{COMBINEDAPACHELOG}")` builds the `Grok` instance to 
parse access logs in `Combined Format`
-* The data source is streamed line by line and not loaded into memory in one 
piece
-* This also works for using `stdin` so are able to parse GB of access log or 
other files
-
-### 11. Executing Arbitrary Commands
+### 10. Executing Arbitrary Commands
 
 Using Apache Commons Exec allows to execute arbitrary commands - nice but 
dangerous. It was recently quite useful to to invoke AWS CLI to generate a 
Confluence page about the overall setup of our AWS accounts. 
 
@@ -760,7 +705,7 @@ h3. AWS EC2 Instance
 </#macro>
 ```
 
-## 12. Interactive Templates
+## 11. Interactive Templates
 
 Sometime you need to apply a CSS, JSON or XPath query in ad ad-hoc way without 
installing `xmllint`, `jq` or `pup` - in this case you can pass a FreeMarker 
template in an interactive fashion
 
@@ -788,7 +733,7 @@ SHELL ==> /bin/bash
 EDITOR ==> vi
 ```
 
-## 13. Filtering & Transforming CSV
+## 12. Filtering & Transforming CSV
 
 During an integration project we imported large transactions CSV files 
(500.000+ records) and in case of import failures the developers would be happy 
to get a nice outline of the transactions causing the problem (the CSV records 
have 60+ columns) - in essence it is filtering (based on some primary key) and 
and transforming into a human-readable output format (Markdown).
 
@@ -884,7 +829,7 @@ yields
 | Total Profit | 498855.44 |
 ```
 
-### 14. Converting Between JSON And YAML
+### 13. Converting Between JSON And YAML
 
 Sometimes we simply need to transform a JSON into an equivalent YAML or the 
other way around
 
@@ -898,7 +843,7 @@ Sometimes we simply need to transform a JSON into an 
equivalent YAML or the othe
 > freemarker-generator -i '${tools.yaml.toYaml(json)}' -m 
 > json=examples/data/json/swagger-spec.json
 ```
 
-### 15. Using Advanced FreeMarker Features
+### 14. Using Advanced FreeMarker Features
 
 There is a `demo.ftl` which shows some advanced FreeMarker functionality
 
diff --git a/freemarker-generator-cli/src/site/markdown/index.md 
b/freemarker-generator-cli/src/site/markdown/index.md
index e6cde71..9370911 100644
--- a/freemarker-generator-cli/src/site/markdown/index.md
+++ b/freemarker-generator-cli/src/site/markdown/index.md
@@ -31,6 +31,7 @@
 * [Using DataFrames](cli/usage/using-dataframes.html)
 * [Transforming CSV](cli/usage/transforming-csv.html)
 * [Generating Test Data](cli/usage/generating-testdata.html)
+* [Parsing with Grok](cli/usage/parsing-with-grok.html)
 
 ### Advanced Topics
 
diff --git 
a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ExamplesTest.java
 
b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ExamplesTest.java
index 88067b2..49e536f 100644
--- 
a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ExamplesTest.java
+++ 
b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ExamplesTest.java
@@ -105,6 +105,7 @@ public class ExamplesTest extends AbstractMainTest {
     @Test
     public void shouldRunGrokExamples() throws IOException {
         assertValid(execute("-t 
src/app/examples/templates/accesslog/combined-access.ftl 
src/app/examples/data/accesslog/combined-access.log"));
+        assertValid(execute("-t 
src/app/examples/templates/logs/csv/serverlog-to-csv.ftl 
src/app/examples/data/logs/server.01.log"));
     }
 
     @Test
diff --git a/freemarker-generator-tools/pom.xml 
b/freemarker-generator-tools/pom.xml
index 5d1bcba..374092f 100644
--- a/freemarker-generator-tools/pom.xml
+++ b/freemarker-generator-tools/pom.xml
@@ -127,7 +127,7 @@
         <dependency>
             <groupId>org.yaml</groupId>
             <artifactId>snakeyaml</artifactId>
-            <version>1.27</version>
+            <version>1.28</version>
         </dependency>
         <!-- Testing -->
         <dependency>
diff --git 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/grok/GrokTool.java
 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/grok/GrokTool.java
index 0beab72..5f3a485 100644
--- 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/grok/GrokTool.java
+++ 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/grok/GrokTool.java
@@ -18,21 +18,52 @@ package org.apache.freemarker.generator.tools.grok;
 
 import io.krakens.grok.api.Grok;
 import io.krakens.grok.api.GrokCompiler;
-import org.apache.freemarker.generator.tools.grok.impl.GrokWrapper;
+import org.apache.freemarker.generator.base.util.Validate;
+
+import java.util.HashMap;
+import java.util.Map;
 
 public class GrokTool {
 
-    private static final String DEFAULT_PATTERN = "/patterns/patterns";
+    private static final String DEFAULT_PATTERN_FILE = "/patterns/patterns";
+
+    /**
+     * Create a default Grok instance using the the default pattern files 
loaded
+     * from the classpath.
+     *
+     * @param pattern Grok pattern to compile
+     * @return Grok object
+     */
+    public Grok create(String pattern) {
+        return create(pattern, new HashMap<>());
+    }
 
-    public GrokWrapper compile(String pattern) {
-        return compile(DEFAULT_PATTERN, pattern);
+    /**
+     * Get a default Grok instance using the the default pattern files loaded
+     * from the classpath.
+     *
+     * @param pattern            Grok pattern to compile
+     * @param patternDefinitions custom patterns to be registered
+     * @return Grok object
+     */
+    public Grok create(String pattern, Map<String, String> patternDefinitions) 
{
+        Validate.notEmpty(pattern, "Grok pattern to compile is empty");
+        final GrokCompiler grokCompiler = grokCompiler();
+        grokCompiler.registerPatternFromClasspath(DEFAULT_PATTERN_FILE);
+        if (patternDefinitions != null) {
+            grokCompiler.register(patternDefinitions);
+        }
+        return grokCompiler.compile(pattern);
     }
 
-    public GrokWrapper compile(String path, String pattern) {
-        final GrokCompiler grokCompiler = GrokCompiler.newInstance();
-        grokCompiler.registerPatternFromClasspath(path);
-        final Grok grok = grokCompiler.compile(pattern);
-        return new GrokWrapper(grok);
+    /**
+     * Create a new Grok compiler instance. This is just
+     * a convinience method if the caller requires full control.
+     *
+     * @return Grok compiler
+     */
+    public GrokCompiler grokCompiler() {
+        return GrokCompiler.newInstance();
     }
 
     @Override
diff --git 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/grok/impl/GrokWrapper.java
 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/grok/impl/GrokWrapper.java
deleted file mode 100644
index 626a94f..0000000
--- 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/grok/impl/GrokWrapper.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-package org.apache.freemarker.generator.tools.grok.impl;
-
-import io.krakens.grok.api.Grok;
-import org.apache.freemarker.generator.base.util.StringUtils;
-
-import java.util.Collections;
-import java.util.Map;
-
-import static java.util.Objects.requireNonNull;
-
-public class GrokWrapper {
-
-    private final Grok grok;
-
-    public GrokWrapper(Grok grok) {
-        this.grok = requireNonNull(grok);
-    }
-
-    public Map<String, Object> match(String line) {
-        if (StringUtils.isEmpty(line)) {
-            return Collections.emptyMap();
-        }
-
-        return grok.match(line).capture();
-    }
-}
diff --git 
a/freemarker-generator-tools/src/test/java/org/apache/freemarker/generator/tools/grok/GrokToolTest.java
 
b/freemarker-generator-tools/src/test/java/org/apache/freemarker/generator/tools/grok/GrokToolTest.java
index 30c0ed7..ef24bf7 100644
--- 
a/freemarker-generator-tools/src/test/java/org/apache/freemarker/generator/tools/grok/GrokToolTest.java
+++ 
b/freemarker-generator-tools/src/test/java/org/apache/freemarker/generator/tools/grok/GrokToolTest.java
@@ -16,22 +16,25 @@
  */
 package org.apache.freemarker.generator.tools.grok;
 
-import org.apache.freemarker.generator.tools.grok.impl.GrokWrapper;
+import io.krakens.grok.api.Grok;
+import io.krakens.grok.api.Match;
 import org.junit.Test;
 
 import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static org.junit.Assert.assertEquals;
 
 public class GrokToolTest {
 
-    private static final String LOG = "112.169.19.192 - - 
[06/Mar/2013:01:36:30 +0900] \"GET / HTTP/1.1\" 200 44346 \"-\" \"Mozilla/5.0 
(Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.22 (KHTML, like Gecko) 
Chrome/25.0.1364.152 Safari/537.22\"";
-
     @Test
     public void shallParseCombinedAccessLog() {
-        final GrokWrapper grok = grokTool().compile("%{COMBINEDAPACHELOG}");
+        final String line = "112.169.19.192 - - [06/Mar/2013:01:36:30 +0900] 
\"GET / HTTP/1.1\" 200 44346 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 
10_8_2) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 
Safari/537.22\"";
+        final Grok grok = grokTool().create("%{COMBINEDAPACHELOG}");
 
-        final Map<String, Object> map = grok.match(LOG);
+        final Match match = grok.match(line);
+        final Map<String, Object> map = match.capture();
 
         assertEquals("GET", map.get("verb"));
         assertEquals("06/Mar/2013:01:36:30 +0900", map.get("timestamp"));
@@ -40,6 +43,28 @@ public class GrokToolTest {
         assertEquals("1.1", map.get("httpversion"));
     }
 
+    @Test
+    public void shallParseServerLogWithCustomPatternDefinitions() {
+        final String line = "2019-05-17 20:00:32,140 INFO  [xx.yyy.zzzz] 
(Thread-99) message response handled in: 62 ms; message counter: 2048; total 
message counter: 7094";
+        Map<String, String> patternDefinitions = Stream.of(new String[][] {
+                { "MY_DATE", "%{YEAR}-%{MONTHNUM}-%{MONTHDAY}" },
+                { "MY_TIMESTAMP", "%{MY_DATE:date} %{TIME:time},%{INT:millis}" 
},
+                { "MY_MODULE", "\\[%{NOTSPACE}\\]" },
+                { "MY_THREAD", "\\(%{NOTSPACE}\\)" },
+                { "MY_SERVERLOG", "%{MY_TIMESTAMP} 
%{LOGLEVEL}%{SPACE:UNWANTED}%{MY_MODULE} %{MY_THREAD} message response handled 
in: %{INT:response_time} ms; %{GREEDYDATA:UNWANTED}" },
+        }).collect(Collectors.toMap(data -> data[0], data -> data[1]));
+
+        final Grok grok = grokTool().create("%{MY_SERVERLOG}", 
patternDefinitions);
+
+        final Map<String, Object> map = grok.match(line).capture();
+
+        assertEquals(16, map.size());
+        assertEquals("2019-05-17", map.get("date"));
+        assertEquals("20:00:32", map.get("time"));
+        assertEquals("140", map.get("millis"));
+        assertEquals("62", map.get("response_time"));
+    }
+
     private GrokTool grokTool() {
         return new GrokTool();
     }
diff --git a/pom.xml b/pom.xml
index 7c44d98..8a38d18 100644
--- a/pom.xml
+++ b/pom.xml
@@ -113,12 +113,12 @@
             <dependency>
                 <groupId>org.apache.commons</groupId>
                 <artifactId>commons-lang3</artifactId>
-                <version>3.7</version>
+                <version>3.12.0</version>
             </dependency>
             <dependency>
                 <groupId>commons-io</groupId>
                 <artifactId>commons-io</artifactId>
-                <version>2.7</version>
+                <version>2.8.0</version>
             </dependency>
             <dependency>
                 <groupId>javax.activation</groupId>
@@ -128,17 +128,17 @@
             <dependency>
                 <groupId>org.slf4j</groupId>
                 <artifactId>slf4j-api</artifactId>
-                <version>1.7.28</version>
+                <version>1.7.30</version>
             </dependency>
             <dependency>
                 <groupId>org.slf4j</groupId>
                 <artifactId>slf4j-simple</artifactId>
-                <version>1.7.28</version>
+                <version>1.7.30</version>
             </dependency>
             <dependency>
                 <groupId>org.slf4j</groupId>
                 <artifactId>slf4j-nop</artifactId>
-                <version>1.7.28</version>
+                <version>1.7.30</version>
             </dependency>
             <dependency>
                 <groupId>junit</groupId>
@@ -149,6 +149,7 @@
         </dependencies>
     </dependencyManagement>
     <build>
+        <defaultGoal>clean install</defaultGoal>
         <pluginManagement>
             <plugins>
                 <plugin>
diff --git a/travis.sh b/travis.sh
index 61d2161..a962f8e 100755
--- a/travis.sh
+++ b/travis.sh
@@ -19,6 +19,7 @@
 # Simulate the Travis build locally
 mvn clean install site site:stage
 cd ./freemarker-generator-cli/target/appassembler/
+sh ./bin/freemarker-generator @examples.args
 sh ./run-examples.sh
 cd ../../../freemarker-generator-maven-plugin-sample
 mvn clean package

Reply via email to