Add azure Monitor API ingestion module

add initial tests

omazuredce: add Azure Monitor output module

This adds a documented Azure Monitor output path so rsyslog can
ship events to Azure-hosted observability workflows. It also makes
the module easier to review and iterate on as a project feature.

Impact: adds a new output module, config parameters, docs, and tests.

Before: rsyslog had no native Azure Monitor DCE output module.
After: rsyslog can batch and send records to Azure Monitor via
omazuredce.

The change adds a new omazuredce plugin and wires it into the
build system and module map. The module obtains Azure tokens,
renders payloads from templates, batches records by size, and
flushes them through the existing action queue model.

The patch also documents the module and its parameters so the
feature is usable without external notes. Supporting config and
build integration are included so the module can be compiled and
packaged consistently with the rest of the tree.

AI-Agent: Codex 2025-06
With the help of AI-Agents: Codex

add tests and address issues

address issues

more issues

more issues

more issues

issues

issues

fix issues

fixfix

fixy

fix

fix fixy fix pants

fix fixy fix pants2

redo the doc
This commit is contained in:
Jan Kängsepp 2026-03-10 20:30:04 +02:00
parent 0bbf1ab111
commit 0006fffe0d
29 changed files with 2509 additions and 1 deletions

View File

@ -231,6 +231,10 @@ if ENABLE_OMAZUREEVENTHUBS
SUBDIRS += plugins/omazureeventhubs
endif
if ENABLE_OMAZUREDCE
SUBDIRS += plugins/omazuredce
endif
if ENABLE_IMDTLS
SUBDIRS += plugins/imdtls
endif
@ -581,6 +585,10 @@ if ENABLE_OMAZUREEVENTHUBS
DISTCHECK_CONFIGURE_FLAGS+= --enable-omazureeventhubs
endif
if ENABLE_OMAZUREDCE
DISTCHECK_CONFIGURE_FLAGS+= --enable-omazuredce
endif
if ENABLE_IMDTLS
DISTCHECK_CONFIGURE_FLAGS+= --enable-imdtls
endif

View File

@ -2768,6 +2768,17 @@ AC_ARG_ENABLE(omazureeventhubs_tests,
)
AM_CONDITIONAL(ENABLE_OMAZUREEVENTHUBS_TESTS, test x$enable_omazureeventhubs_tests = xyes)
AC_ARG_ENABLE(omazuredce_tests,
[AS_HELP_STRING([--enable-omazuredce-tests],[Enable Omazuredce tests @<:@default=no@:>@])],
[case "${enableval}" in
yes) enable_omazuredce_tests="yes" ;;
no) enable_omazuredce_tests="no" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-omazuredce-tests) ;;
esac],
[enable_omazuredce_tests=no]
)
AM_CONDITIONAL(ENABLE_OMAZUREDCE_TESTS, test x$enable_omazuredce_tests = xyes)
AC_ARG_ENABLE(kafka_tests,
[AS_HELP_STRING([--enable-kafka-tests],[Enable Kafka tests, needs Java @<:@default=no@:>@])],
[case "${enableval}" in
@ -2882,6 +2893,26 @@ fi
AM_CONDITIONAL(ENABLE_OMKAFKA, test x$enable_omkafka = xyes -o x$enable_omkafka = xoptional)
AM_CONDITIONAL(ENABLE_IMKAFKA, test x$enable_imkafka = xyes -o x$enable_imkafka = xoptional)
# omazuredce support for output module
AC_ARG_ENABLE(omazuredce,
[AS_HELP_STRING([--enable-omazuredce],[Compiles omazuredce output module @<:@default=no@:>@])],
[case "${enableval}" in
yes) enable_omazuredce="yes" ;;
no) enable_omazuredce="no" ;;
optional) enable_omazuredce="optional" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-omazuredce) ;;
esac],
[enable_omazuredce=no]
)
if test "x$enable_omazuredce" = "xyes" -o "x$enable_omazuredce" = "xoptional"; then
PKG_CHECK_MODULES([CURL], [libcurl], , [
AS_IF([test x$enable_omazuredce = xyes],
AC_MSG_FAILURE([omazuredce requires libcurl])
)
enable_omazuredce="no"
])
fi
AM_CONDITIONAL(ENABLE_OMAZUREDCE, test x$enable_omazuredce = xyes -o x$enable_omazuredce = xoptional)
# omazureeventhubs support for output module
AC_ARG_ENABLE(omazureeventhubs,
@ -3467,6 +3498,7 @@ AC_CONFIG_FILES([Makefile \
plugins/pmlastmsg/Makefile \
plugins/mmdblookup/Makefile \
plugins/omazureeventhubs/Makefile \
plugins/omazuredce/Makefile \
plugins/imdtls/Makefile \
plugins/omdtls/Makefile \
contrib/mmdarwin/Makefile \
@ -3584,6 +3616,7 @@ echo " omtcl module will be compiled: $enable_omtcl"
echo " omkafka module will be compiled: $enable_omkafka"
echo " omhiredis module will be compiled: $enable_omhiredis"
echo " omazureeventhubs module will be compiled: $enable_omazureeventhubs"
echo " omazuredce module will be compiled: $enable_omazuredce"
echo " omdtls module will be compiled: $enable_omdtls"
echo
echo "---{ parser modules }---"
@ -3661,6 +3694,7 @@ echo " PostgreSQL Tests enabled: $enable_pgsql_tests"
echo " Kafka Tests enabled: $enable_kafka_tests"
echo " Redis Tests enabled: $enable_redis_tests"
echo " Omazureeventhubs Tests enabled: $enable_omazureeventhubs_tests"
echo " Omazuredce Tests enabled: $enable_omazuredce_tests"
echo " Imdocker Tests enabled: $enable_imdocker_tests"
echo " imtcp tests enabled: $enable_imtcp_tests"
echo " gnutls tests enabled: $enable_gnutls_tests"

View File

@ -228,6 +228,7 @@ EXTRA_DIST = \
source/configuration/modules/mmutf8fix.rst \
source/configuration/modules/module_workflow.png \
source/configuration/modules/omamqp1.rst \
source/configuration/modules/omazuredce.rst \
source/configuration/modules/omazureeventhubs.rst \
source/configuration/modules/omclickhouse.rst \
source/configuration/modules/omczmq.rst \
@ -839,6 +840,15 @@ EXTRA_DIST = \
source/reference/parameters/omazureeventhubs-eventproperties.rst \
source/reference/parameters/omazureeventhubs-statsname.rst \
source/reference/parameters/omazureeventhubs-template.rst \
source/reference/parameters/omazuredce-client_id.rst \
source/reference/parameters/omazuredce-client_secret.rst \
source/reference/parameters/omazuredce-dce_url.rst \
source/reference/parameters/omazuredce-dcr_id.rst \
source/reference/parameters/omazuredce-flush_timeout_ms.rst \
source/reference/parameters/omazuredce-max_batch_bytes.rst \
source/reference/parameters/omazuredce-table_name.rst \
source/reference/parameters/omazuredce-template.rst \
source/reference/parameters/omazuredce-tenant_id.rst \
source/reference/parameters/omclickhouse-allowunsignedcerts.rst \
source/reference/parameters/omclickhouse-bulkmode.rst \
source/reference/parameters/omclickhouse-errorfile.rst \

View File

@ -26,6 +26,15 @@ omazureeventhubs:
writer: rsyslog_worker
reader: proton_thread
omazuredce:
paths: ["plugins/omazuredce/"]
requires_serialization: true
locks:
- type: mutex
field: pWrkrData.batchLock
notes:
- Each worker owns its batch buffer and timer thread; access is serialized by batchLock.
contrib_omhttp:
paths: ["contrib/omhttp/"]
requires_serialization: false
@ -65,4 +74,3 @@ omotel:
requires_serialization: false
notes:
- Transport resources are not yet active; introduce pData locking once they appear.

View File

@ -0,0 +1,195 @@
.. _module-omazuredce:
.. meta::
:description: Configuration reference for the omazuredce Azure Monitor Logs Ingestion output module.
:keywords: rsyslog, omazuredce, azure, dce, dcr, monitor, logs ingestion
.. summary-start
``omazuredce`` batches JSON records and sends them to the Azure Monitor Logs
Ingestion API by using a Data Collection Endpoint (DCE), Data Collection Rule
(DCR), and Microsoft Entra client-credentials authentication.
.. summary-end
******************************************************
omazuredce: Azure Monitor Logs Ingestion Output Module
******************************************************
=========================== ===========================================================================
**Module Name:** **omazuredce**
**Author:** Jan Kängsepp
**Available since:** v8.2604
=========================== ===========================================================================
Purpose
=======
This module provides native support for forwarding log data to the Azure
Monitor Logs Ingestion API.
Each message rendered by the configured template must be a single JSON object.
``omazuredce`` collects those objects into a JSON array, requests an OAuth
access token from Microsoft Entra ID, and posts the resulting batch to the
configured Azure Data Collection Endpoint.
Notable Features
================
- Size-aware batching with a configurable ``max_batch_bytes`` limit
- Timed flushing for partially filled batches via ``flush_timeout_ms``
- Automatic OAuth token acquisition for the
``https://monitor.azure.com/.default`` scope
- Retry-friendly error handling that cooperates with rsyslog action suspension
Requirements
============
To use ``omazuredce``, you need the following:
- ``libcurl`` support at build time
- A valid Azure Data Collection Endpoint URL
- A Data Collection Rule ID
- A target stream or table name accepted by the DCR
- A Microsoft Entra application with ``client_id``, ``client_secret``, and
``tenant_id`` values that can request tokens for
``https://monitor.azure.com/.default``
- A template that renders one valid JSON object per message, or the built-in
``StdJSONFmt`` default
The module is built only when ``./configure`` is invoked with
``--enable-omazuredce=yes``.
Configuration Parameters
========================
.. note::
Parameter names are case-insensitive; snake_case is used in the examples
because the module's parameter names contain underscores.
.. note::
This module supports action parameters only.
Action Parameters
-----------------
.. list-table::
:widths: 30 70
:header-rows: 1
* - Parameter
- Summary
* - :ref:`param-omazuredce-template`
- .. include:: ../../reference/parameters/omazuredce-template.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-omazuredce-client_id`
- .. include:: ../../reference/parameters/omazuredce-client_id.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-omazuredce-client_secret`
- .. include:: ../../reference/parameters/omazuredce-client_secret.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-omazuredce-tenant_id`
- .. include:: ../../reference/parameters/omazuredce-tenant_id.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-omazuredce-dce_url`
- .. include:: ../../reference/parameters/omazuredce-dce_url.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-omazuredce-dcr_id`
- .. include:: ../../reference/parameters/omazuredce-dcr_id.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-omazuredce-table_name`
- .. include:: ../../reference/parameters/omazuredce-table_name.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-omazuredce-max_batch_bytes`
- .. include:: ../../reference/parameters/omazuredce-max_batch_bytes.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-omazuredce-flush_timeout_ms`
- .. include:: ../../reference/parameters/omazuredce-flush_timeout_ms.rst
:start-after: .. summary-start
:end-before: .. summary-end
.. toctree::
:hidden:
../../reference/parameters/omazuredce-template
../../reference/parameters/omazuredce-client_id
../../reference/parameters/omazuredce-client_secret
../../reference/parameters/omazuredce-tenant_id
../../reference/parameters/omazuredce-dce_url
../../reference/parameters/omazuredce-dcr_id
../../reference/parameters/omazuredce-table_name
../../reference/parameters/omazuredce-max_batch_bytes
../../reference/parameters/omazuredce-flush_timeout_ms
Batching Behavior
=================
``omazuredce`` builds one JSON array per worker and flushes it when one of the
following happens:
- Adding the next record would exceed ``max_batch_bytes``
- The action queue transaction ends and ``flush_timeout_ms`` is set to ``0``
- The batch has been idle for at least ``flush_timeout_ms`` milliseconds
The internal size check is conservative. It includes both the JSON payload size
and an estimate for HTTP headers before sending the request.
Error Handling
==============
The module obtains an OAuth access token before sending data. If Azure returns
``401 Unauthorized`` for a batch request, the module refreshes the token and
returns ``RS_RET_SUSPENDED``. The failed batch is then retried by rsyslog's
central action engine according to the configured action backoff and retry
settings. Other retryable HTTP failures follow the same ``RS_RET_SUSPENDED``
path.
If a rendered message is too large to fit into an empty batch under the current
``max_batch_bytes`` setting, the module logs an error and drops that record.
Example
=======
The following example renders each event as one JSON object and forwards it to
Azure Monitor Logs Ingestion:
.. code-block:: rsyslog
module(load="omazuredce")
template(name="tplAzureDce" type="list" option.jsonf="on") {
property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="Host" name="hostname" format="jsonf")
property(outname="AppName" name="app-name" format="jsonf")
property(outname="Message" name="msg" format="jsonf")
}
action(
type="omazuredce"
template="tplAzureDce"
client_id="<application-id>"
client_secret="<client-secret>"
tenant_id="<tenant-id>"
dce_url="https://<dce-name>.<region>.ingest.monitor.azure.com"
dcr_id="<dcr-id>"
table_name="Custom-MyTable_CL"
max_batch_bytes="1048576"
flush_timeout_ms="2000"
)

View File

@ -0,0 +1,47 @@
.. _param-omazuredce-client_id:
.. _omazuredce.parameter.action.client_id:
.. meta::
:description: Reference for the omazuredce client_id parameter.
:keywords: rsyslog, omazuredce, client_id, azure, entra
client_id
=========
.. index::
single: omazuredce; client_id
single: client_id
.. summary-start
Specifies the Microsoft Entra application client ID used for OAuth token
requests.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: client_id
:Scope: action
:Type: string
:Default: none
:Required?: yes
:Introduced: Not specified
Description
-----------
``client_id`` identifies the Azure application that requests access tokens for
the Logs Ingestion API. It is used together with ``client_secret`` and
``tenant_id``.
Action usage
------------
.. _omazuredce.parameter.action.client_id-usage:
.. code-block:: rsyslog
action(type="omazuredce" client_id="<application-id>" ...)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,46 @@
.. _param-omazuredce-client_secret:
.. _omazuredce.parameter.action.client_secret:
.. meta::
:description: Reference for the omazuredce client_secret parameter.
:keywords: rsyslog, omazuredce, client_secret, azure, entra
client_secret
=============
.. index::
single: omazuredce; client_secret
single: client_secret
.. summary-start
Supplies the client secret paired with ``client_id`` for OAuth token requests.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: client_secret
:Scope: action
:Type: string
:Default: none
:Required?: yes
:Introduced: Not specified
Description
-----------
``client_secret`` provides the shared secret used by Microsoft Entra client
credentials authentication. Treat this value as sensitive and avoid storing
real production secrets in example configurations or version control.
Action usage
------------
.. _omazuredce.parameter.action.client_secret-usage:
.. code-block:: rsyslog
action(type="omazuredce" client_secret="<client-secret>" ...)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,52 @@
.. _param-omazuredce-dce_url:
.. _omazuredce.parameter.action.dce_url:
.. meta::
:description: Reference for the omazuredce dce_url parameter.
:keywords: rsyslog, omazuredce, dce_url, azure, logs ingestion
dce_url
=======
.. index::
single: omazuredce; dce_url
single: dce_url
.. summary-start
Defines the Azure Data Collection Endpoint base URL used for batch submission.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: dce_url
:Scope: action
:Type: string
:Default: none
:Required?: yes
:Introduced: Not specified
Description
-----------
``dce_url`` is the base HTTPS endpoint for the Azure Logs Ingestion API. The
module appends the DCR and stream path segments to this URL when constructing
requests.
Both forms with and without a trailing slash are accepted.
Action usage
------------
.. _omazuredce.parameter.action.dce_url-usage:
.. code-block:: rsyslog
action(
type="omazuredce"
dce_url="https://<dce-name>.<region>.ingest.monitor.azure.com"
...
)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,46 @@
.. _param-omazuredce-dcr_id:
.. _omazuredce.parameter.action.dcr_id:
.. meta::
:description: Reference for the omazuredce dcr_id parameter.
:keywords: rsyslog, omazuredce, dcr_id, azure, logs ingestion
dcr_id
======
.. index::
single: omazuredce; dcr_id
single: dcr_id
.. summary-start
Specifies the Azure Data Collection Rule immutable ID used in the ingestion URL.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: dcr_id
:Scope: action
:Type: string
:Default: none
:Required?: yes
:Introduced: Not specified
Description
-----------
``dcr_id`` identifies the Data Collection Rule that receives the uploaded log
records. The value is inserted into the request path under
``dataCollectionRules/<dcr_id>``.
Action usage
------------
.. _omazuredce.parameter.action.dcr_id-usage:
.. code-block:: rsyslog
action(type="omazuredce" dcr_id="<dcr-id>" ...)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,48 @@
.. _param-omazuredce-flush_timeout_ms:
.. _omazuredce.parameter.action.flush_timeout_ms:
.. meta::
:description: Reference for the omazuredce flush_timeout_ms parameter.
:keywords: rsyslog, omazuredce, flush_timeout_ms, azure, batching
flush_timeout_ms
================
.. index::
single: omazuredce; flush_timeout_ms
single: flush_timeout_ms
.. summary-start
Controls how long a partially filled batch may stay idle before it is flushed.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: flush_timeout_ms
:Scope: action
:Type: non-negative integer
:Default: 1000
:Required?: no
:Introduced: Not specified
Description
-----------
When ``flush_timeout_ms`` is greater than ``0``, a worker thread checks for
idle batches and flushes them after the configured number of milliseconds.
When it is set to ``0``, the timer-based flush is disabled and batches are sent
only when they fill up or when the current action queue transaction ends.
Action usage
------------
.. _omazuredce.parameter.action.flush_timeout_ms-usage:
.. code-block:: rsyslog
action(type="omazuredce" flush_timeout_ms="2000" ...)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,50 @@
.. _param-omazuredce-max_batch_bytes:
.. _omazuredce.parameter.action.max_batch_bytes:
.. meta::
:description: Reference for the omazuredce max_batch_bytes parameter.
:keywords: rsyslog, omazuredce, max_batch_bytes, azure, batching
max_batch_bytes
===============
.. index::
single: omazuredce; max_batch_bytes
single: max_batch_bytes
.. summary-start
Limits the estimated total size of one Azure ingestion request, including the
payload and HTTP overhead.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: max_batch_bytes
:Scope: action
:Type: integer
:Default: 1048576
:Required?: no
:Introduced: Not specified
Description
-----------
``max_batch_bytes`` defines the upper bound for a batch. Before appending a new
record, the module estimates the final HTTP request size and flushes the
current batch if needed.
Valid values are in the range ``1`` to ``1048576``. Records that still do not
fit into an otherwise empty batch are logged and dropped.
Action usage
------------
.. _omazuredce.parameter.action.max_batch_bytes-usage:
.. code-block:: rsyslog
action(type="omazuredce" max_batch_bytes="524288" ...)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,46 @@
.. _param-omazuredce-table_name:
.. _omazuredce.parameter.action.table_name:
.. meta::
:description: Reference for the omazuredce table_name parameter.
:keywords: rsyslog, omazuredce, table_name, azure, stream
table_name
==========
.. index::
single: omazuredce; table_name
single: table_name
.. summary-start
Sets the stream or table name appended to the Azure ingestion request path.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: table_name
:Scope: action
:Type: string
:Default: none
:Required?: yes
:Introduced: Not specified
Description
-----------
``table_name`` is appended below ``/streams/`` in the final request URL. The
configured value must match a stream accepted by the target Data Collection
Rule.
Action usage
------------
.. _omazuredce.parameter.action.table_name-usage:
.. code-block:: rsyslog
action(type="omazuredce" table_name="Custom-MyTable_CL" ...)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,54 @@
.. _param-omazuredce-template:
.. _omazuredce.parameter.action.template:
.. meta::
:description: Reference for the omazuredce template parameter.
:keywords: rsyslog, omazuredce, template, azure
template
========
.. index::
single: omazuredce; template
single: template
.. summary-start
Selects the rsyslog template used to render each message before it is added to
the Azure ingestion batch.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: template
:Scope: action
:Type: word
:Default: action=StdJSONFmt
:Required?: no
:Introduced: Not specified
Description
-----------
The selected template must render exactly one valid JSON object per message.
``omazuredce`` parses the rendered text and merges it into the batch payload.
If this parameter is omitted, the module uses the built-in ``StdJSONFmt``
template, which already renders one JSON object per message.
Action usage
------------
.. _omazuredce.parameter.action.template-usage:
.. code-block:: rsyslog
template(name="tplAzureDce" type="list" option.jsonf="on") {
property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="Host" name="hostname" format="jsonf")
property(outname="Message" name="msg" format="jsonf")
}
action(type="omazuredce" template="tplAzureDce" ...)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,45 @@
.. _param-omazuredce-tenant_id:
.. _omazuredce.parameter.action.tenant_id:
.. meta::
:description: Reference for the omazuredce tenant_id parameter.
:keywords: rsyslog, omazuredce, tenant_id, azure, entra
tenant_id
=========
.. index::
single: omazuredce; tenant_id
single: tenant_id
.. summary-start
Sets the Microsoft Entra tenant used when requesting OAuth access tokens.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/omazuredce`.
:Name: tenant_id
:Scope: action
:Type: string
:Default: none
:Required?: yes
:Introduced: Not specified
Description
-----------
``tenant_id`` identifies the Microsoft Entra tenant that issues the token for
the configured application credentials.
Action usage
------------
.. _omazuredce.parameter.action.tenant_id-usage:
.. code-block:: rsyslog
action(type="omazuredce" tenant_id="<tenant-id>" ...)
See also
--------
See also :doc:`../../configuration/modules/omazuredce`.

View File

@ -0,0 +1,27 @@
support_status: core-supported
maturity_level: fresh
primary_contact: "GitHub Discussions & Issues <https://github.com/rsyslog/rsyslog/discussions>"
last_reviewed: 2026-03-17
build_dependencies:
- libcurl development headers
runtime_dependencies:
- Azure Monitor Logs Ingestion API reachable over HTTPS
- Microsoft Entra ID application credentials for the `https://monitor.azure.com/.default` scope
- Azure Data Collection Endpoint (DCE) and Data Collection Rule (DCR)
ci_targets:
- omazuredce-no-dcr-id.sh
- omazuredce-default-template.sh
- omazuredce-bad-template.sh
- omazuredce-good-template.sh
- omazuredce-basic.sh
- omazuredce-basic-url.sh
- omazuredce-batch.sh
- omazuredce-interrupt.sh
- omazuredce-timer.sh
- omazuredce-basic-vg.sh
documentation:
- doc/source/configuration/modules/omazuredce.rst
notes:
- The module is newly added and tests require Azure credentials and variables in the environment.
- Integration tests depend on Azure credentials and endpoint details supplied through `tests/omazuredce-env.sh`.
- The module batches one JSON array per worker and serializes batch/timer access with `pWrkrData.batchLock`.

View File

@ -0,0 +1,8 @@
pkglib_LTLIBRARIES = omazuredce.la
omazuredce_la_SOURCES = omazuredce.c
omazuredce_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBFASTJSON_CFLAGS)
omazuredce_la_LDFLAGS = -module -avoid-version
omazuredce_la_LIBADD = $(CURL_LIBS) $(LIBFASTJSON_LIBS) $(PTHREADS_LIBS)
EXTRA_DIST =

File diff suppressed because it is too large Load Diff

View File

@ -906,6 +906,20 @@ TESTS_OMAZUREEVENTHUBS_VALGRIND = \
omazureeventhubs-basic-vg.sh \
omazureeventhubs-interrupt-vg.sh
TESTS_OMAZUREDCE = \
omazuredce-no-dcr-id.sh \
omazuredce-default-template.sh \
omazuredce-bad-template.sh \
omazuredce-good-template.sh \
omazuredce-basic.sh \
omazuredce-basic-url.sh \
omazuredce-batch.sh \
omazuredce-interrupt.sh \
omazuredce-timer.sh
TESTS_OMAZUREDCE_VALGRIND = \
omazuredce-basic-vg.sh
TESTS_IMDOCKER = \
imdocker-basic.sh \
imdocker-image-name.sh \
@ -1726,6 +1740,9 @@ EXTRA_DIST += $(TESTS_KAFKA)
EXTRA_DIST += $(TESTS_KAFKA_VALGRIND)
EXTRA_DIST += $(TESTS_OMAZUREEVENTHUBS)
EXTRA_DIST += $(TESTS_OMAZUREEVENTHUBS_VALGRIND)
EXTRA_DIST += $(TESTS_OMAZUREDCE)
EXTRA_DIST += $(TESTS_OMAZUREDCE_VALGRIND)
EXTRA_DIST += omazuredce-env.sh
EXTRA_DIST += $(TESTS_IMDOCKER)
EXTRA_DIST += $(TESTS_IMDOCKER_VALGRIND)
EXTRA_DIST += $(TESTS_IMHTTP)
@ -2321,6 +2338,15 @@ endif
endif
endif
if ENABLE_OMAZUREDCE
if ENABLE_OMAZUREDCE_TESTS
TESTS += $(TESTS_OMAZUREDCE)
if HAVE_VALGRIND
TESTS += $(TESTS_OMAZUREDCE_VALGRIND)
endif
endif
endif
if ENABLE_IMDOCKER

View File

@ -0,0 +1,51 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
. ${srcdir:=.}/omazuredce-env.sh
require_plugin "omazuredce"
omazuredce_require_env
export NUMMESSAGES=1
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
template(name="tplAzureDceBroken" type="string" string="{\"message\":\"%msg:::json%\"} trailing-garbage")
local4.* action(
type="omazuredce"
template="tplAzureDceBroken"
client_id="'$AZURE_DCE_CLIENT_ID'"
client_secret=`echo $AZURE_DCE_CLIENT_SECRET`
tenant_id="'$AZURE_DCE_TENANT_ID'"
dce_url="'$AZURE_DCE_URL'"
dcr_id="'$AZURE_DCE_DCR_ID'"
table_name="'$AZURE_DCE_TABLE_NAME'"
max_batch_bytes="1048576"
flush_timeout_ms="0"
action.resumeInterval="1"
action.resumeRetryCount="1"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
injectmsg 0 $NUMMESSAGES
shutdown_when_empty
wait_shutdown
content_check "omazuredce: message template must render a JSON object"
post_count=$(grep -c -F "omazuredce: posted batch records=" < "$RSYSLOG_OUT_LOG")
if [ "${post_count:=0}" -ne 0 ]; then
echo "FAIL: malformed template unexpectedly produced a successful batch post"
cat -n "$RSYSLOG_OUT_LOG"
error_exit 1
fi
exit_test

49
tests/omazuredce-basic-url.sh Executable file
View File

@ -0,0 +1,49 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
. ${srcdir:=.}/omazuredce-env.sh
require_plugin "omazuredce"
omazuredce_require_env
export NUMMESSAGES=10
export AZURE_DCE_URL_ALT="$(omazuredce_url_with_trailing_slash)"
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
template(name="tplAzureDce" type="list" option.jsonftree="on") {
property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="host" name="hostname" format="jsonf")
property(outname="message" name="msg" format="jsonf")
}
local4.* action(
type="omazuredce"
template="tplAzureDce"
client_id="'$AZURE_DCE_CLIENT_ID'"
client_secret=`echo $AZURE_DCE_CLIENT_SECRET`
tenant_id="'$AZURE_DCE_TENANT_ID'"
dce_url="'$AZURE_DCE_URL_ALT'"
dcr_id="'$AZURE_DCE_DCR_ID'"
table_name="'$AZURE_DCE_TABLE_NAME'"
max_batch_bytes="1048576"
flush_timeout_ms="0"
action.resumeInterval="1"
action.resumeRetryCount="1"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
injectmsg 0 $NUMMESSAGES
shutdown_when_empty
wait_shutdown
content_check "omazuredce: posted batch records="
exit_test

3
tests/omazuredce-basic-vg.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
export USE_VALGRIND="YES"
source ${srcdir:-.}/omazuredce-basic.sh

49
tests/omazuredce-basic.sh Executable file
View File

@ -0,0 +1,49 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
. ${srcdir:=.}/omazuredce-env.sh
require_plugin "omazuredce"
export NUMMESSAGES=10
omazuredce_require_env
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
template(name="tplAzureDce" type="list" option.jsonftree="on") {
property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="host" name="hostname" format="jsonf")
property(outname="message" name="msg" format="jsonf")
}
local4.* action(
type="omazuredce"
template="tplAzureDce"
client_id="'$AZURE_DCE_CLIENT_ID'"
client_secret=`echo $AZURE_DCE_CLIENT_SECRET`
tenant_id="'$AZURE_DCE_TENANT_ID'"
dce_url="'$AZURE_DCE_URL'"
dcr_id="'$AZURE_DCE_DCR_ID'"
table_name="'$AZURE_DCE_TABLE_NAME'"
max_batch_bytes="1048576"
flush_timeout_ms="0"
action.resumeInterval="1"
action.resumeRetryCount="1"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
injectmsg 0 $NUMMESSAGES
shutdown_when_empty
wait_shutdown
content_check "omazuredce: posted batch records="
exit_test

55
tests/omazuredce-batch.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
. ${srcdir:=.}/omazuredce-env.sh
require_plugin "omazuredce"
omazuredce_require_env
export NUMMESSAGES=200
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
template(name="tplAzureDceBatch" type="list" option.jsonftree="on") {
property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="host" name="hostname" format="jsonf")
property(outname="message" name="msg" format="jsonf")
}
local4.* action(
type="omazuredce"
template="tplAzureDceBatch"
client_id="'$AZURE_DCE_CLIENT_ID'"
client_secret=`echo $AZURE_DCE_CLIENT_SECRET`
tenant_id="'$AZURE_DCE_TENANT_ID'"
dce_url="'$AZURE_DCE_URL'"
dcr_id="'$AZURE_DCE_DCR_ID'"
table_name="'$AZURE_DCE_TABLE_NAME'"
max_batch_bytes="4096"
flush_timeout_ms="0"
action.resumeInterval="1"
action.resumeRetryCount="1"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
injectmsg 0 $NUMMESSAGES
shutdown_when_empty
wait_shutdown
content_check "omazuredce: posted batch records="
post_count=$(grep -c -F "omazuredce: posted batch records=" < "$RSYSLOG_OUT_LOG")
if [ "${post_count:=0}" -lt 2 ]; then
echo "FAIL: expected multiple omazuredce batch posts, got $post_count"
cat -n "$RSYSLOG_OUT_LOG"
error_exit 1
fi
exit_test

View File

@ -0,0 +1,41 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
. ${srcdir:=.}/omazuredce-env.sh
require_plugin "omazuredce"
export NUMMESSAGES=10
omazuredce_require_env
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
local4.* action(
type="omazuredce"
client_id="'$AZURE_DCE_CLIENT_ID'"
client_secret=`echo $AZURE_DCE_CLIENT_SECRET`
tenant_id="'$AZURE_DCE_TENANT_ID'"
dce_url="'$AZURE_DCE_URL'"
dcr_id="'$AZURE_DCE_DCR_ID'"
table_name="'$AZURE_DCE_TABLE_NAME'"
max_batch_bytes="1048576"
flush_timeout_ms="0"
action.resumeInterval="1"
action.resumeRetryCount="1"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
injectmsg 0 $NUMMESSAGES
shutdown_when_empty
wait_shutdown
content_check "omazuredce: posted batch records="
exit_test

100
tests/omazuredce-env.sh Executable file
View File

@ -0,0 +1,100 @@
#!/bin/bash
omazuredce_require_env() {
if [[ -z "${AZURE_DCE_CLIENT_ID}" ]]; then
echo "SKIP: AZURE_DCE_CLIENT_ID environment variable not set - SKIPPING"
exit 77
fi
if [[ -z "${AZURE_DCE_CLIENT_SECRET}" ]]; then
echo "SKIP: AZURE_DCE_CLIENT_SECRET environment variable not set - SKIPPING"
exit 77
fi
if [[ -z "${AZURE_DCE_TENANT_ID}" ]]; then
echo "SKIP: AZURE_DCE_TENANT_ID environment variable not set - SKIPPING"
exit 77
fi
if [[ -z "${AZURE_DCE_URL}" ]]; then
echo "SKIP: AZURE_DCE_URL environment variable not set - SKIPPING"
exit 77
fi
if [[ -z "${AZURE_DCE_DCR_ID}" ]]; then
echo "SKIP: AZURE_DCE_DCR_ID environment variable not set - SKIPPING"
exit 77
fi
if [[ -z "${AZURE_DCE_TABLE_NAME}" ]]; then
echo "SKIP: AZURE_DCE_TABLE_NAME environment variable not set - SKIPPING"
exit 77
fi
}
omazuredce_url_with_trailing_slash() {
if [[ "${AZURE_DCE_URL}" == */ ]]; then
printf '%s' "${AZURE_DCE_URL}"
else
printf '%s/' "${AZURE_DCE_URL}"
fi
}
omazuredce_url_host() {
local rest
rest=${AZURE_DCE_URL#*://}
rest=${rest%%/*}
if [[ "${rest}" == \[*\] ]]; then
printf '%s\n' "${rest#\[}" | sed 's/\]$//'
elif [[ "${rest}" == \[*\]:* ]]; then
rest=${rest#\[}
printf '%s\n' "${rest%%]*}"
else
printf '%s\n' "${rest%%:*}"
fi
}
omazuredce_url_port() {
local rest explicit_port
rest=${AZURE_DCE_URL#*://}
rest=${rest%%/*}
if [[ "${rest}" == \[*\]:* ]]; then
explicit_port=${rest##*:}
elif [[ "${rest}" == \[*\] ]]; then
explicit_port=
else
explicit_port=${rest##*:}
if [[ "${explicit_port}" == "${rest}" ]]; then
explicit_port=
fi
fi
if [[ -n "${explicit_port}" ]]; then
printf '%s\n' "${explicit_port}"
elif [[ "${AZURE_DCE_URL}" == https://* ]]; then
printf '443\n'
else
printf '80\n'
fi
}
omazuredce_url_ips_v4() {
local host
host=$(omazuredce_url_host)
if [[ "${host}" == *:* ]]; then
return
fi
if command -v getent >/dev/null 2>&1; then
getent ahostsv4 "$host" | awk 'NR == 1 { print $1; exit }'
fi
}
omazuredce_url_ips_v6() {
local host
host=$(omazuredce_url_host)
if [[ "${host}" == *:* ]]; then
printf '%s\n' "${host}"
return
fi
if command -v getent >/dev/null 2>&1; then
getent ahostsv6 "$host" | awk 'NR == 1 { print $1; exit }'
fi
}

View File

@ -0,0 +1,51 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
. ${srcdir:=.}/omazuredce-env.sh
require_plugin "omazuredce"
omazuredce_require_env
export NUMMESSAGES=1
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
template(name="tplAzureDceGood" type="string" string="{\"message\":\"%msg:::json%\"}")
local4.* action(
type="omazuredce"
template="tplAzureDceGood"
client_id="'$AZURE_DCE_CLIENT_ID'"
client_secret=`echo $AZURE_DCE_CLIENT_SECRET`
tenant_id="'$AZURE_DCE_TENANT_ID'"
dce_url="'$AZURE_DCE_URL'"
dcr_id="'$AZURE_DCE_DCR_ID'"
table_name="'$AZURE_DCE_TABLE_NAME'"
max_batch_bytes="1048576"
flush_timeout_ms="0"
action.resumeInterval="1"
action.resumeRetryCount="1"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
injectmsg 0 $NUMMESSAGES
shutdown_when_empty
wait_shutdown
content_check "omazuredce: posted batch records="
error_count=$(grep -c -F "omazuredce: message template must render a JSON object" < "$RSYSLOG_OUT_LOG")
if [ "${error_count:=0}" -ne 0 ]; then
echo "FAIL: valid template unexpectedly triggered template validation error"
cat -n "$RSYSLOG_OUT_LOG"
error_exit 1
fi
exit_test

189
tests/omazuredce-interrupt.sh Executable file
View File

@ -0,0 +1,189 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
echo This test must be run as root [connection interruption requires iptables]
echo "For variables to be passed use --preserve-env=AZURE_DCE_CLIENT_ID,AZURE_DCE_CLIENT_SECRET,AZURE_DCE_TENANT_ID,AZURE_DCE_URL,AZURE_DCE_DCR_ID,AZURE_DCE_TABLE_NAME"
if [ "$EUID" -ne 0 ]; then
exit 77
fi
. ${srcdir:=.}/diag.sh init
. ${srcdir:=.}/omazuredce-env.sh
require_plugin "omazuredce"
omazuredce_require_env
if ! command -v iptables >/dev/null 2>&1; then
echo "SKIP: iptables command not available - SKIPPING"
exit 77
fi
if ! command -v ip6tables >/dev/null 2>&1; then
ip6tables=
fi
export NUMMESSAGES=400
export interrupt_port="$(omazuredce_url_port)"
export TEST_TIMEOUT_WAIT=180
interrupt_status_file="$RSYSLOG_DYNNAME.interrupt.status"
interrupt_detail_file="$RSYSLOG_DYNNAME.interrupt.detail"
interrupt_ipv4_hosts="$(omazuredce_url_ips_v4)"
interrupt_ipv6_hosts="$(omazuredce_url_ips_v6)"
if [[ -z "$interrupt_ipv4_hosts" && -z "$interrupt_ipv6_hosts" ]]; then
echo "SKIP: unable to resolve AZURE_DCE_URL host to an IP address - SKIPPING"
exit 77
fi
if [[ -n "$interrupt_ipv6_hosts" && -z "${ip6tables:-}" ]]; then
if [[ -n "$interrupt_ipv4_hosts" ]]; then
echo "NOTICE: ip6tables command not available, skipping IPv6 interruption targets"
interrupt_ipv6_hosts=
else
echo "SKIP: ip6tables command not available for IPv6-only interruption target - SKIPPING"
exit 77
fi
fi
omazuredce_post_count() {
if [ -f "$RSYSLOG_OUT_LOG" ]; then
grep -c -F "omazuredce: posted batch records=" < "$RSYSLOG_OUT_LOG"
else
echo 0
fi
}
omazuredce_fail_count() {
if [ -f "$RSYSLOG_OUT_LOG" ]; then
grep -c -F "omazuredce: batch post failed:" < "$RSYSLOG_OUT_LOG"
else
echo 0
fi
}
omazuredce_add_reject_rules() {
local host
for host in $interrupt_ipv4_hosts; do
iptables -I OUTPUT -d "$host" -p tcp --dport "$interrupt_port" -j REJECT --reject-with tcp-reset || return 1
iptables -I INPUT -s "$host" -p tcp --sport "$interrupt_port" -j REJECT --reject-with tcp-reset || return 1
done
for host in $interrupt_ipv6_hosts; do
ip6tables -I OUTPUT -d "$host" -p tcp --dport "$interrupt_port" -j REJECT --reject-with tcp-reset || return 1
ip6tables -I INPUT -s "$host" -p tcp --sport "$interrupt_port" -j REJECT --reject-with tcp-reset || return 1
done
}
omazuredce_del_reject_rules() {
local host
for host in $interrupt_ipv4_hosts; do
iptables -D OUTPUT -d "$host" -p tcp --dport "$interrupt_port" -j REJECT --reject-with tcp-reset 2>/dev/null || true
iptables -D INPUT -s "$host" -p tcp --sport "$interrupt_port" -j REJECT --reject-with tcp-reset 2>/dev/null || true
done
for host in $interrupt_ipv6_hosts; do
ip6tables -D OUTPUT -d "$host" -p tcp --dport "$interrupt_port" -j REJECT --reject-with tcp-reset 2>/dev/null || true
ip6tables -D INPUT -s "$host" -p tcp --sport "$interrupt_port" -j REJECT --reject-with tcp-reset 2>/dev/null || true
done
}
omazuredce_cleanup_interrupt() {
if [ -n "${interrupt_bg_pid:-}" ]; then
kill "$interrupt_bg_pid" 2>/dev/null || true
wait "$interrupt_bg_pid" 2>/dev/null || true
fi
omazuredce_del_reject_rules
}
omazuredce_interrupt_traffic() {
local tries
: >"$interrupt_status_file"
tries=0
while [ "$tries" -lt 8 ]; do
if [ "$(omazuredce_post_count)" -ge 2 ]; then
echo "Injecting temporary iptables reject for port ${interrupt_port}"
if ! omazuredce_add_reject_rules; then
echo "skip" >"$interrupt_status_file"
echo "unable to insert iptables/ip6tables reject rules" >"$interrupt_detail_file"
omazuredce_del_reject_rules
return
fi
$TESTTOOL_DIR/msleep 750
omazuredce_del_reject_rules
if [ "$(omazuredce_fail_count)" -gt 0 ]; then
echo "done" >"$interrupt_status_file"
return
fi
tries=$((tries + 1))
else
$TESTTOOL_DIR/msleep 100
fi
done
echo "done" >"$interrupt_status_file"
}
trap omazuredce_cleanup_interrupt EXIT
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
template(name="tplAzureDceInterrupt" type="list" option.jsonftree="on") {
property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="host" name="hostname" format="jsonf")
property(outname="message" name="msg" format="jsonf")
}
local4.* action(
type="omazuredce"
template="tplAzureDceInterrupt"
client_id="'$AZURE_DCE_CLIENT_ID'"
client_secret=`echo $AZURE_DCE_CLIENT_SECRET`
tenant_id="'$AZURE_DCE_TENANT_ID'"
dce_url="'$AZURE_DCE_URL'"
dcr_id="'$AZURE_DCE_DCR_ID'"
table_name="'$AZURE_DCE_TABLE_NAME'"
max_batch_bytes="4096"
flush_timeout_ms="0"
queue.type="FixedArray"
queue.size="20000"
queue.dequeueBatchSize="64"
queue.minDequeueBatchSize="32"
queue.minDequeueBatchSize.timeout="1000"
queue.workerThreads="1"
queue.workerThreadMinimumMessages="32"
queue.timeoutWorkerthreadShutdown="60000"
queue.timeoutEnqueue="2000"
queue.timeoutshutdown="1000"
action.resumeInterval="1"
action.resumeRetryCount="-1"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
injectmsg 0 $NUMMESSAGES
omazuredce_interrupt_traffic &
interrupt_bg_pid=$!
wait_file_lines --count-function omazuredce_post_count "$RSYSLOG_OUT_LOG" 5 "$TEST_TIMEOUT_WAIT"
wait "$interrupt_bg_pid"
interrupt_bg_pid=
if [[ -f "$interrupt_status_file" && "$(cat "$interrupt_status_file")" == "skip" ]]; then
echo "SKIP: $(cat "$interrupt_detail_file") - SKIPPING"
exit 77
fi
shutdown_when_empty
wait_shutdown
content_check "omazuredce: batch post failed:"
content_check "omazuredce: posted batch records="
post_count=$(grep -c -F "omazuredce: posted batch records=" < "$RSYSLOG_OUT_LOG")
if [ "${post_count:=0}" -lt 2 ]; then
echo "FAIL: expected multiple successful omazuredce batch posts after interruption, got $post_count"
cat -n "$RSYSLOG_OUT_LOG"
error_exit 1
fi
exit_test

39
tests/omazuredce-no-dcr-id.sh Executable file
View File

@ -0,0 +1,39 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
require_plugin "omazuredce"
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
template(name="tplAzureDceNoDcrId" type="list" option.jsonftree="on") {
property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="host" name="hostname" format="jsonf")
property(outname="message" name="msg" format="jsonf")
}
local4.* action(
type="omazuredce"
template="tplAzureDceNoDcrId"
client_id="dummy-client-id"
client_secret=`echo dummy-client-secret`
tenant_id="dummy-tenant-id"
dce_url="https://example.com"
table_name="Custom-Test_CL"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
shutdown_when_empty
wait_shutdown
content_check "omazuredce: parameter 'dcr_id' required but not specified"
exit_test

57
tests/omazuredce-timer.sh Executable file
View File

@ -0,0 +1,57 @@
#!/bin/bash
# This file is part of the rsyslog project, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
. ${srcdir:=.}/omazuredce-env.sh
require_plugin "omazuredce"
omazuredce_require_env
export NUMMESSAGES=5
generate_conf
add_conf '
global(processInternalMessages="on" internalmsg.severity="info")
module(load="../plugins/omazuredce/.libs/omazuredce")
template(name="tplAzureDceTimer" type="list" option.jsonftree="on") {
property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="host" name="hostname" format="jsonf")
property(outname="message" name="msg" format="jsonf")
}
local4.* action(
type="omazuredce"
template="tplAzureDceTimer"
client_id="'$AZURE_DCE_CLIENT_ID'"
client_secret=`echo $AZURE_DCE_CLIENT_SECRET`
tenant_id="'$AZURE_DCE_TENANT_ID'"
dce_url="'$AZURE_DCE_URL'"
dcr_id="'$AZURE_DCE_DCR_ID'"
table_name="'$AZURE_DCE_TABLE_NAME'"
max_batch_bytes="1048576"
flush_timeout_ms="200"
action.resumeInterval="1"
action.resumeRetryCount="1"
)
action(type="omfile" file="'$RSYSLOG_OUT_LOG'")
'
startup
injectmsg 0 $NUMMESSAGES
# Verify the timer thread flushes without needing shutdown-triggered cleanup.
content_check_with_count "omazuredce: posted batch records=5" 1 5
shutdown_when_empty
wait_shutdown
post_count=$(grep -c -F "omazuredce: posted batch records=" < "$RSYSLOG_OUT_LOG")
if [ "${post_count:=0}" -ne 1 ]; then
echo "FAIL: expected exactly one timer-driven omazuredce batch post, got $post_count"
cat -n "$RSYSLOG_OUT_LOG"
error_exit 1
fi
exit_test