mirror of
https://github.com/rsyslog/rsyslog.git
synced 2026-03-19 14:09:30 +01:00
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:
parent
0bbf1ab111
commit
0006fffe0d
@ -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
|
||||
|
||||
34
configure.ac
34
configure.ac
@ -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"
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
195
doc/source/configuration/modules/omazuredce.rst
Normal file
195
doc/source/configuration/modules/omazuredce.rst
Normal 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"
|
||||
)
|
||||
47
doc/source/reference/parameters/omazuredce-client_id.rst
Normal file
47
doc/source/reference/parameters/omazuredce-client_id.rst
Normal 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`.
|
||||
46
doc/source/reference/parameters/omazuredce-client_secret.rst
Normal file
46
doc/source/reference/parameters/omazuredce-client_secret.rst
Normal 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`.
|
||||
52
doc/source/reference/parameters/omazuredce-dce_url.rst
Normal file
52
doc/source/reference/parameters/omazuredce-dce_url.rst
Normal 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`.
|
||||
46
doc/source/reference/parameters/omazuredce-dcr_id.rst
Normal file
46
doc/source/reference/parameters/omazuredce-dcr_id.rst
Normal 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`.
|
||||
@ -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`.
|
||||
@ -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`.
|
||||
46
doc/source/reference/parameters/omazuredce-table_name.rst
Normal file
46
doc/source/reference/parameters/omazuredce-table_name.rst
Normal 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`.
|
||||
54
doc/source/reference/parameters/omazuredce-template.rst
Normal file
54
doc/source/reference/parameters/omazuredce-template.rst
Normal 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`.
|
||||
45
doc/source/reference/parameters/omazuredce-tenant_id.rst
Normal file
45
doc/source/reference/parameters/omazuredce-tenant_id.rst
Normal 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`.
|
||||
27
plugins/omazuredce/MODULE_METADATA.yaml
Normal file
27
plugins/omazuredce/MODULE_METADATA.yaml
Normal 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`.
|
||||
8
plugins/omazuredce/Makefile.am
Normal file
8
plugins/omazuredce/Makefile.am
Normal 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 =
|
||||
1074
plugins/omazuredce/omazuredce.c
Normal file
1074
plugins/omazuredce/omazuredce.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
51
tests/omazuredce-bad-template.sh
Executable file
51
tests/omazuredce-bad-template.sh
Executable 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
49
tests/omazuredce-basic-url.sh
Executable 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
3
tests/omazuredce-basic-vg.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
export USE_VALGRIND="YES"
|
||||
source ${srcdir:-.}/omazuredce-basic.sh
|
||||
49
tests/omazuredce-basic.sh
Executable file
49
tests/omazuredce-basic.sh
Executable 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
55
tests/omazuredce-batch.sh
Executable 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
|
||||
41
tests/omazuredce-default-template.sh
Executable file
41
tests/omazuredce-default-template.sh
Executable 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
100
tests/omazuredce-env.sh
Executable 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
|
||||
}
|
||||
51
tests/omazuredce-good-template.sh
Executable file
51
tests/omazuredce-good-template.sh
Executable 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
189
tests/omazuredce-interrupt.sh
Executable 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
39
tests/omazuredce-no-dcr-id.sh
Executable 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
57
tests/omazuredce-timer.sh
Executable 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
|
||||
Loading…
x
Reference in New Issue
Block a user