apache-airflow-providers-elasticsearch 6.3.1__tar.gz → 6.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of apache-airflow-providers-elasticsearch might be problematic. Click here for more details.
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/PKG-INFO +10 -8
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/README.rst +5 -4
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/changelog.rst +25 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/index.rst +5 -3
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/provider.yaml +2 -1
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/pyproject.toml +5 -4
- {apache_airflow_providers_elasticsearch-6.3.1/src/airflow/providers → apache_airflow_providers_elasticsearch-6.3.2/src/airflow}/__init__.py +1 -1
- {apache_airflow_providers_elasticsearch-6.3.1/tests/system → apache_airflow_providers_elasticsearch-6.3.2/src/airflow/providers}/__init__.py +1 -1
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/__init__.py +1 -1
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/hooks/elasticsearch.py +1 -5
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/log/es_task_handler.py +25 -14
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/version_compat.py +9 -1
- {apache_airflow_providers_elasticsearch-6.3.1/tests/unit → apache_airflow_providers_elasticsearch-6.3.2/tests/system}/__init__.py +1 -1
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/system/elasticsearch/example_elasticsearch_query.py +8 -2
- {apache_airflow_providers_elasticsearch-6.3.1/src/airflow → apache_airflow_providers_elasticsearch-6.3.2/tests/unit}/__init__.py +1 -1
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/test_es_task_handler.py +34 -15
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/.latest-doc-only-change.txt +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/commits.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/conf.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/configurations-ref.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/connections/elasticsearch.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/hooks/elasticsearch_python_hook.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/hooks/elasticsearch_sql_hook.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/hooks/index.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/installing-providers-from-sources.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/integration-logos/Elasticsearch.png +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/logging/index.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/redirects.txt +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/security.rst +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/LICENSE +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/get_provider_info.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/hooks/__init__.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/log/__init__.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/log/es_json_formatter.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/log/es_response.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/conftest.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/system/elasticsearch/__init__.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/__init__.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/hooks/__init__.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/hooks/test_elasticsearch.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/__init__.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/elasticmock/__init__.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/elasticmock/fake_elasticsearch.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/elasticmock/utilities/__init__.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/test_es_json_formatter.py +0 -0
- {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/test_es_response.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apache-airflow-providers-elasticsearch
|
|
3
|
-
Version: 6.3.
|
|
3
|
+
Version: 6.3.2
|
|
4
4
|
Summary: Provider package apache-airflow-providers-elasticsearch for Apache Airflow
|
|
5
5
|
Keywords: airflow-provider,elasticsearch,airflow,integration
|
|
6
6
|
Author-email: Apache Software Foundation <dev@airflow.apache.org>
|
|
7
7
|
Maintainer-email: Apache Software Foundation <dev@airflow.apache.org>
|
|
8
|
-
Requires-Python:
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
9
|
Description-Content-Type: text/x-rst
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Environment :: Console
|
|
@@ -18,13 +18,14 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
22
|
Classifier: Topic :: System :: Monitoring
|
|
22
23
|
Requires-Dist: apache-airflow>=2.10.0
|
|
23
24
|
Requires-Dist: apache-airflow-providers-common-sql>=1.27.0
|
|
24
25
|
Requires-Dist: elasticsearch>=8.10,<9
|
|
25
26
|
Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
|
|
26
|
-
Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.
|
|
27
|
-
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.
|
|
27
|
+
Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.2/changelog.html
|
|
28
|
+
Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.2
|
|
28
29
|
Project-URL: Mastodon, https://fosstodon.org/@airflow
|
|
29
30
|
Project-URL: Slack Chat, https://s.apache.org/airflow-slack
|
|
30
31
|
Project-URL: Source Code, https://github.com/apache/airflow
|
|
@@ -55,8 +56,9 @@ Project-URL: YouTube, https://www.youtube.com/channel/UCSXwxpWZQ7XZ1WL3wqevChA/
|
|
|
55
56
|
|
|
56
57
|
Package ``apache-airflow-providers-elasticsearch``
|
|
57
58
|
|
|
58
|
-
Release: ``6.3.
|
|
59
|
+
Release: ``6.3.2``
|
|
59
60
|
|
|
61
|
+
Release Date: ``|PypiReleaseDate|``
|
|
60
62
|
|
|
61
63
|
`Elasticsearch <https://www.elastic.co/elasticsearch>`__
|
|
62
64
|
|
|
@@ -68,7 +70,7 @@ This is a provider package for ``elasticsearch`` provider. All classes for this
|
|
|
68
70
|
are in ``airflow.providers.elasticsearch`` python package.
|
|
69
71
|
|
|
70
72
|
You can find package information and changelog for the provider
|
|
71
|
-
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.
|
|
73
|
+
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.2/>`_.
|
|
72
74
|
|
|
73
75
|
Installation
|
|
74
76
|
------------
|
|
@@ -77,7 +79,7 @@ You can install this package on top of an existing Airflow 2 installation (see `
|
|
|
77
79
|
for the minimum Airflow version supported) via
|
|
78
80
|
``pip install apache-airflow-providers-elasticsearch``
|
|
79
81
|
|
|
80
|
-
The package supports the following python versions: 3.10,3.11,3.12
|
|
82
|
+
The package supports the following python versions: 3.10,3.11,3.12,3.13
|
|
81
83
|
|
|
82
84
|
Requirements
|
|
83
85
|
------------
|
|
@@ -110,5 +112,5 @@ Dependent package
|
|
|
110
112
|
============================================================================================================ ==============
|
|
111
113
|
|
|
112
114
|
The changelog for the provider package can be found in the
|
|
113
|
-
`changelog <https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.
|
|
115
|
+
`changelog <https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.2/changelog.html>`_.
|
|
114
116
|
|
|
@@ -23,8 +23,9 @@
|
|
|
23
23
|
|
|
24
24
|
Package ``apache-airflow-providers-elasticsearch``
|
|
25
25
|
|
|
26
|
-
Release: ``6.3.
|
|
26
|
+
Release: ``6.3.2``
|
|
27
27
|
|
|
28
|
+
Release Date: ``|PypiReleaseDate|``
|
|
28
29
|
|
|
29
30
|
`Elasticsearch <https://www.elastic.co/elasticsearch>`__
|
|
30
31
|
|
|
@@ -36,7 +37,7 @@ This is a provider package for ``elasticsearch`` provider. All classes for this
|
|
|
36
37
|
are in ``airflow.providers.elasticsearch`` python package.
|
|
37
38
|
|
|
38
39
|
You can find package information and changelog for the provider
|
|
39
|
-
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.
|
|
40
|
+
in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.2/>`_.
|
|
40
41
|
|
|
41
42
|
Installation
|
|
42
43
|
------------
|
|
@@ -45,7 +46,7 @@ You can install this package on top of an existing Airflow 2 installation (see `
|
|
|
45
46
|
for the minimum Airflow version supported) via
|
|
46
47
|
``pip install apache-airflow-providers-elasticsearch``
|
|
47
48
|
|
|
48
|
-
The package supports the following python versions: 3.10,3.11,3.12
|
|
49
|
+
The package supports the following python versions: 3.10,3.11,3.12,3.13
|
|
49
50
|
|
|
50
51
|
Requirements
|
|
51
52
|
------------
|
|
@@ -78,4 +79,4 @@ Dependent package
|
|
|
78
79
|
============================================================================================================ ==============
|
|
79
80
|
|
|
80
81
|
The changelog for the provider package can be found in the
|
|
81
|
-
`changelog <https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.
|
|
82
|
+
`changelog <https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.2/changelog.html>`_.
|
|
@@ -27,6 +27,31 @@
|
|
|
27
27
|
Changelog
|
|
28
28
|
---------
|
|
29
29
|
|
|
30
|
+
6.3.2
|
|
31
|
+
.....
|
|
32
|
+
|
|
33
|
+
Bug Fixes
|
|
34
|
+
~~~~~~~~~
|
|
35
|
+
|
|
36
|
+
* ``Make Elasticsearch/OpensearchTaskHandler to render log well (#53639)``
|
|
37
|
+
* ``Resolve OOM When Reading Large Logs in Webserver (#49470)``
|
|
38
|
+
|
|
39
|
+
Misc
|
|
40
|
+
~~~~
|
|
41
|
+
|
|
42
|
+
* ``fix mypy unreachable code warnings for elasticsearch provider (#53464)``
|
|
43
|
+
* ``Add Python 3.13 support for Airflow. (#46891)``
|
|
44
|
+
* ``Cleanup mypy ignore in elasticsearch provider where possible (#53277)``
|
|
45
|
+
* ``Remove type ignore across codebase after mypy upgrade (#53243)``
|
|
46
|
+
* ``Make elasticsearch provider compatible with mypy 1.16.1 (#53109)``
|
|
47
|
+
* ``Remove upper-binding for "python-requires" (#52980)``
|
|
48
|
+
* ``Temporarily switch to use >=,< pattern instead of '~=' (#52967)``
|
|
49
|
+
* ``Move all BaseHook usages to version_compat in Elastic Search (#52805)``
|
|
50
|
+
|
|
51
|
+
.. Below changes are excluded from the changelog. Move them to
|
|
52
|
+
appropriate section above if needed. Do not delete the lines(!):
|
|
53
|
+
* ``Deprecate decorators from Core (#53629)``
|
|
54
|
+
|
|
30
55
|
6.3.1
|
|
31
56
|
.....
|
|
32
57
|
|
|
@@ -79,7 +79,9 @@ apache-airflow-providers-elasticsearch package
|
|
|
79
79
|
`Elasticsearch <https://www.elastic.co/elasticsearch>`__
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-
Release: 6.3.
|
|
82
|
+
Release: 6.3.2
|
|
83
|
+
|
|
84
|
+
Release Date: ``|PypiReleaseDate|``
|
|
83
85
|
|
|
84
86
|
Provider package
|
|
85
87
|
----------------
|
|
@@ -132,5 +134,5 @@ Downloading official packages
|
|
|
132
134
|
You can download officially released packages and verify their checksums and signatures from the
|
|
133
135
|
`Official Apache Download site <https://downloads.apache.org/airflow/providers/>`_
|
|
134
136
|
|
|
135
|
-
* `The apache-airflow-providers-elasticsearch 6.3.
|
|
136
|
-
* `The apache-airflow-providers-elasticsearch 6.3.
|
|
137
|
+
* `The apache-airflow-providers-elasticsearch 6.3.2 sdist package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.2.tar.gz>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.2.tar.gz.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.2.tar.gz.sha512>`__)
|
|
138
|
+
* `The apache-airflow-providers-elasticsearch 6.3.2 wheel package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.2-py3-none-any.whl>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.2-py3-none-any.whl.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.2-py3-none-any.whl.sha512>`__)
|
|
@@ -22,12 +22,13 @@ description: |
|
|
|
22
22
|
`Elasticsearch <https://www.elastic.co/elasticsearch>`__
|
|
23
23
|
|
|
24
24
|
state: ready
|
|
25
|
-
source-date-epoch:
|
|
25
|
+
source-date-epoch: 1753690618
|
|
26
26
|
# Note that those versions are maintained by release manager - do not update them manually
|
|
27
27
|
# with the exception of case where other provider in sources has >= new provider version.
|
|
28
28
|
# In such case adding >= NEW_VERSION and bumping to NEW_VERSION in a provider have
|
|
29
29
|
# to be done in the same PR
|
|
30
30
|
versions:
|
|
31
|
+
- 6.3.2
|
|
31
32
|
- 6.3.1
|
|
32
33
|
- 6.3.0
|
|
33
34
|
- 6.2.2
|
|
@@ -25,7 +25,7 @@ build-backend = "flit_core.buildapi"
|
|
|
25
25
|
|
|
26
26
|
[project]
|
|
27
27
|
name = "apache-airflow-providers-elasticsearch"
|
|
28
|
-
version = "6.3.
|
|
28
|
+
version = "6.3.2"
|
|
29
29
|
description = "Provider package apache-airflow-providers-elasticsearch for Apache Airflow"
|
|
30
30
|
readme = "README.rst"
|
|
31
31
|
authors = [
|
|
@@ -47,9 +47,10 @@ classifiers = [
|
|
|
47
47
|
"Programming Language :: Python :: 3.10",
|
|
48
48
|
"Programming Language :: Python :: 3.11",
|
|
49
49
|
"Programming Language :: Python :: 3.12",
|
|
50
|
+
"Programming Language :: Python :: 3.13",
|
|
50
51
|
"Topic :: System :: Monitoring",
|
|
51
52
|
]
|
|
52
|
-
requires-python = "
|
|
53
|
+
requires-python = ">=3.10"
|
|
53
54
|
|
|
54
55
|
# The dependencies should be modified in place in the generated file.
|
|
55
56
|
# Any change in the dependencies is preserved when the file is regenerated
|
|
@@ -97,8 +98,8 @@ apache-airflow-providers-common-sql = {workspace = true}
|
|
|
97
98
|
apache-airflow-providers-standard = {workspace = true}
|
|
98
99
|
|
|
99
100
|
[project.urls]
|
|
100
|
-
"Documentation" = "https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.
|
|
101
|
-
"Changelog" = "https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.
|
|
101
|
+
"Documentation" = "https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.2"
|
|
102
|
+
"Changelog" = "https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.2/changelog.html"
|
|
102
103
|
"Bug Tracker" = "https://github.com/apache/airflow/issues"
|
|
103
104
|
"Source Code" = "https://github.com/apache/airflow"
|
|
104
105
|
"Slack Chat" = "https://s.apache.org/airflow-slack"
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
# KIND, either express or implied. See the License for the
|
|
15
15
|
# specific language governing permissions and limitations
|
|
16
16
|
# under the License.
|
|
17
|
-
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
17
|
+
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
# KIND, either express or implied. See the License for the
|
|
15
15
|
# specific language governing permissions and limitations
|
|
16
16
|
# under the License.
|
|
17
|
-
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
17
|
+
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
|
|
|
29
29
|
|
|
30
30
|
__all__ = ["__version__"]
|
|
31
31
|
|
|
32
|
-
__version__ = "6.3.
|
|
32
|
+
__version__ = "6.3.2"
|
|
33
33
|
|
|
34
34
|
if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
|
|
35
35
|
"2.10.0"
|
|
@@ -26,11 +26,7 @@ from urllib import parse
|
|
|
26
26
|
from elasticsearch import Elasticsearch
|
|
27
27
|
|
|
28
28
|
from airflow.providers.common.sql.hooks.sql import DbApiHook
|
|
29
|
-
|
|
30
|
-
try:
|
|
31
|
-
from airflow.sdk import BaseHook
|
|
32
|
-
except ImportError:
|
|
33
|
-
from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
|
|
29
|
+
from airflow.providers.elasticsearch.version_compat import BaseHook
|
|
34
30
|
|
|
35
31
|
if TYPE_CHECKING:
|
|
36
32
|
from elastic_transport import ObjectApiResponse
|
|
@@ -29,7 +29,7 @@ import time
|
|
|
29
29
|
from collections import defaultdict
|
|
30
30
|
from collections.abc import Callable
|
|
31
31
|
from operator import attrgetter
|
|
32
|
-
from typing import TYPE_CHECKING, Any, Literal
|
|
32
|
+
from typing import TYPE_CHECKING, Any, Literal, cast
|
|
33
33
|
from urllib.parse import quote, urlparse
|
|
34
34
|
|
|
35
35
|
# Using `from elasticsearch import *` would break elasticsearch mocking used in unit test.
|
|
@@ -56,6 +56,7 @@ if TYPE_CHECKING:
|
|
|
56
56
|
from datetime import datetime
|
|
57
57
|
|
|
58
58
|
from airflow.models.taskinstance import TaskInstance, TaskInstanceKey
|
|
59
|
+
from airflow.utils.log.file_task_handler import LogMetadata
|
|
59
60
|
|
|
60
61
|
|
|
61
62
|
LOG_LINE_DEFAULTS = {"exc_text": "", "stack_info": ""}
|
|
@@ -66,6 +67,7 @@ LOG_LINE_DEFAULTS = {"exc_text": "", "stack_info": ""}
|
|
|
66
67
|
# not exist, the task handler should use the log_id_template attribute instead.
|
|
67
68
|
USE_PER_RUN_LOG_ID = hasattr(DagRun, "get_log_template")
|
|
68
69
|
|
|
70
|
+
TASK_LOG_FIELDS = ["timestamp", "event", "level", "chan", "logger"]
|
|
69
71
|
|
|
70
72
|
VALID_ES_CONFIG_KEYS = set(inspect.signature(elasticsearch.Elasticsearch.__init__).parameters.keys())
|
|
71
73
|
# Remove `self` from the valid set of kwargs
|
|
@@ -159,11 +161,11 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
159
161
|
es_kwargs = es_kwargs or {}
|
|
160
162
|
if es_kwargs == "default_es_kwargs":
|
|
161
163
|
es_kwargs = get_es_kwargs_from_config()
|
|
162
|
-
host = self.format_url(host)
|
|
164
|
+
self.host = self.format_url(host)
|
|
163
165
|
super().__init__(base_log_folder)
|
|
164
166
|
self.closed = False
|
|
165
167
|
|
|
166
|
-
self.client = elasticsearch.Elasticsearch(host, **es_kwargs)
|
|
168
|
+
self.client = elasticsearch.Elasticsearch(self.host, **es_kwargs)
|
|
167
169
|
# in airflow.cfg, host of elasticsearch has to be http://dockerhostXxxx:9200
|
|
168
170
|
|
|
169
171
|
self.frontend = frontend
|
|
@@ -184,7 +186,7 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
184
186
|
)
|
|
185
187
|
|
|
186
188
|
self.formatter: logging.Formatter
|
|
187
|
-
self.handler: logging.FileHandler | logging.StreamHandler
|
|
189
|
+
self.handler: logging.FileHandler | logging.StreamHandler | None = None
|
|
188
190
|
self._doc_type_map: dict[Any, Any] = {}
|
|
189
191
|
self._doc_type: list[Any] = []
|
|
190
192
|
|
|
@@ -286,7 +288,7 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
286
288
|
def _group_logs_by_host(self, response: ElasticSearchResponse) -> dict[str, list[Hit]]:
|
|
287
289
|
grouped_logs = defaultdict(list)
|
|
288
290
|
for hit in response:
|
|
289
|
-
key = getattr_nested(hit, self.host_field, None) or
|
|
291
|
+
key = getattr_nested(hit, self.host_field, None) or self.host
|
|
290
292
|
grouped_logs[key].append(hit)
|
|
291
293
|
return grouped_logs
|
|
292
294
|
|
|
@@ -294,8 +296,8 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
294
296
|
return True
|
|
295
297
|
|
|
296
298
|
def _read(
|
|
297
|
-
self, ti: TaskInstance, try_number: int, metadata:
|
|
298
|
-
) -> tuple[EsLogMsgType,
|
|
299
|
+
self, ti: TaskInstance, try_number: int, metadata: LogMetadata | None = None
|
|
300
|
+
) -> tuple[EsLogMsgType, LogMetadata]:
|
|
299
301
|
"""
|
|
300
302
|
Endpoint for streaming log.
|
|
301
303
|
|
|
@@ -306,7 +308,9 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
306
308
|
:return: a list of tuple with host and log documents, metadata.
|
|
307
309
|
"""
|
|
308
310
|
if not metadata:
|
|
309
|
-
|
|
311
|
+
# LogMetadata(TypedDict) is used as type annotation for log_reader; added ignore to suppress mypy error
|
|
312
|
+
metadata = {"offset": 0} # type: ignore[assignment]
|
|
313
|
+
metadata = cast("LogMetadata", metadata)
|
|
310
314
|
if "offset" not in metadata:
|
|
311
315
|
metadata["offset"] = 0
|
|
312
316
|
|
|
@@ -346,7 +350,9 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
346
350
|
"Otherwise, the logs for this task instance may have been removed."
|
|
347
351
|
)
|
|
348
352
|
if AIRFLOW_V_3_0_PLUS:
|
|
349
|
-
|
|
353
|
+
from airflow.utils.log.file_task_handler import StructuredLogMessage
|
|
354
|
+
|
|
355
|
+
return [StructuredLogMessage(event=missing_log_message)], metadata
|
|
350
356
|
return [("", missing_log_message)], metadata # type: ignore[list-item]
|
|
351
357
|
if (
|
|
352
358
|
# Assume end of log after not receiving new log for N min,
|
|
@@ -375,11 +381,16 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
375
381
|
sources=[host for host in logs_by_host.keys()],
|
|
376
382
|
), # type: ignore[call-arg]
|
|
377
383
|
StructuredLogMessage(event="::endgroup::"),
|
|
378
|
-
]
|
|
384
|
+
]
|
|
379
385
|
|
|
386
|
+
# Flatten all hits, filter to only desired fields, and construct StructuredLogMessage objects
|
|
380
387
|
message = header + [
|
|
381
|
-
StructuredLogMessage(
|
|
382
|
-
|
|
388
|
+
StructuredLogMessage(
|
|
389
|
+
**{k: v for k, v in hit.to_dict().items() if k.lower() in TASK_LOG_FIELDS}
|
|
390
|
+
)
|
|
391
|
+
for hits in logs_by_host.values()
|
|
392
|
+
for hit in hits
|
|
393
|
+
]
|
|
383
394
|
else:
|
|
384
395
|
message = [
|
|
385
396
|
(host, concat_logs(hits)) # type: ignore[misc]
|
|
@@ -421,7 +432,7 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
421
432
|
|
|
422
433
|
index_patterns = self._get_index_patterns(ti)
|
|
423
434
|
try:
|
|
424
|
-
max_log_line = self.client.count(index=index_patterns, query=query)["count"]
|
|
435
|
+
max_log_line = self.client.count(index=index_patterns, query=query)["count"]
|
|
425
436
|
except NotFoundError as e:
|
|
426
437
|
self.log.exception("The target index pattern %s does not exist", index_patterns)
|
|
427
438
|
raise e
|
|
@@ -508,7 +519,7 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
|
|
|
508
519
|
|
|
509
520
|
# Reopen the file stream, because FileHandler.close() would be called
|
|
510
521
|
# first in logging.shutdown() and the stream in it would be set to None.
|
|
511
|
-
if self.handler.stream is None or self.handler.stream.closed:
|
|
522
|
+
if self.handler.stream is None or self.handler.stream.closed:
|
|
512
523
|
self.handler.stream = self.handler._open() # type: ignore[union-attr]
|
|
513
524
|
|
|
514
525
|
# Mark the end of file using end of log mark,
|
|
@@ -33,10 +33,18 @@ def get_base_airflow_version_tuple() -> tuple[int, int, int]:
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
AIRFLOW_V_3_0_PLUS = get_base_airflow_version_tuple() >= (3, 0, 0)
|
|
36
|
+
AIRFLOW_V_3_1_PLUS: bool = get_base_airflow_version_tuple() >= (3, 1, 0)
|
|
37
|
+
|
|
38
|
+
if AIRFLOW_V_3_1_PLUS:
|
|
39
|
+
from airflow.sdk import BaseHook
|
|
40
|
+
else:
|
|
41
|
+
from airflow.hooks.base import BaseHook # type: ignore[attr-defined,no-redef]
|
|
36
42
|
|
|
37
43
|
if AIRFLOW_V_3_0_PLUS:
|
|
38
44
|
from airflow.utils.log.file_task_handler import StructuredLogMessage
|
|
39
45
|
|
|
40
46
|
EsLogMsgType = list[StructuredLogMessage] | str
|
|
41
47
|
else:
|
|
42
|
-
EsLogMsgType = list[tuple[str, str]] # type: ignore[misc]
|
|
48
|
+
EsLogMsgType = list[tuple[str, str]] # type: ignore[assignment,misc]
|
|
49
|
+
|
|
50
|
+
__all__ = ["AIRFLOW_V_3_0_PLUS", "AIRFLOW_V_3_1_PLUS", "BaseHook", "EsLogMsgType"]
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
# KIND, either express or implied. See the License for the
|
|
15
15
|
# specific language governing permissions and limitations
|
|
16
16
|
# under the License.
|
|
17
|
-
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
17
|
+
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
@@ -24,10 +24,17 @@ import os
|
|
|
24
24
|
from datetime import datetime
|
|
25
25
|
|
|
26
26
|
from airflow import models
|
|
27
|
-
from airflow.decorators import task
|
|
28
27
|
from airflow.providers.elasticsearch.hooks.elasticsearch import ElasticsearchPythonHook, ElasticsearchSQLHook
|
|
29
28
|
from airflow.providers.standard.operators.python import PythonOperator
|
|
30
29
|
|
|
30
|
+
from tests_common.test_utils.version_compat import AIRFLOW_V_3_0_PLUS
|
|
31
|
+
|
|
32
|
+
if AIRFLOW_V_3_0_PLUS:
|
|
33
|
+
from airflow.sdk import task
|
|
34
|
+
else:
|
|
35
|
+
# Airflow 2 path
|
|
36
|
+
from airflow.decorators import task # type: ignore[attr-defined,no-redef]
|
|
37
|
+
|
|
31
38
|
ENV_ID = os.environ.get("SYSTEM_TESTS_ENV_ID")
|
|
32
39
|
DAG_ID = "elasticsearch_dag"
|
|
33
40
|
CONN_ID = "elasticsearch_default"
|
|
@@ -64,7 +71,6 @@ def use_elasticsearch_hook():
|
|
|
64
71
|
|
|
65
72
|
# [END howto_elasticsearch_python_hook]
|
|
66
73
|
|
|
67
|
-
|
|
68
74
|
with models.DAG(
|
|
69
75
|
DAG_ID,
|
|
70
76
|
schedule="@once",
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
# KIND, either express or implied. See the License for the
|
|
15
15
|
# specific language governing permissions and limitations
|
|
16
16
|
# under the License.
|
|
17
|
-
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
17
|
+
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
@@ -117,7 +117,12 @@ class TestElasticsearchTaskHandler:
|
|
|
117
117
|
self.index_name = "test_index"
|
|
118
118
|
self.doc_type = "log"
|
|
119
119
|
self.test_message = "some random stuff"
|
|
120
|
-
self.body = {
|
|
120
|
+
self.body = {
|
|
121
|
+
"message": self.test_message,
|
|
122
|
+
"log_id": self.LOG_ID,
|
|
123
|
+
"offset": 1,
|
|
124
|
+
"event": self.test_message,
|
|
125
|
+
}
|
|
121
126
|
self.es.index(index=self.index_name, doc_type=self.doc_type, body=self.body, id=1)
|
|
122
127
|
|
|
123
128
|
def teardown_method(self):
|
|
@@ -208,8 +213,9 @@ class TestElasticsearchTaskHandler:
|
|
|
208
213
|
)
|
|
209
214
|
|
|
210
215
|
if AIRFLOW_V_3_0_PLUS:
|
|
216
|
+
logs = list(logs)
|
|
211
217
|
assert logs[0].event == "::group::Log message source details"
|
|
212
|
-
assert logs[0].sources == ["
|
|
218
|
+
assert logs[0].sources == ["http://localhost:9200"]
|
|
213
219
|
assert logs[1].event == "::endgroup::"
|
|
214
220
|
assert logs[2].event == "some random stuff"
|
|
215
221
|
|
|
@@ -235,8 +241,9 @@ class TestElasticsearchTaskHandler:
|
|
|
235
241
|
)
|
|
236
242
|
|
|
237
243
|
if AIRFLOW_V_3_0_PLUS:
|
|
244
|
+
logs = list(logs)
|
|
238
245
|
assert logs[0].event == "::group::Log message source details"
|
|
239
|
-
assert logs[0].sources == ["
|
|
246
|
+
assert logs[0].sources == ["http://localhost:9200"]
|
|
240
247
|
assert logs[1].event == "::endgroup::"
|
|
241
248
|
assert logs[2].event == "some random stuff"
|
|
242
249
|
|
|
@@ -304,10 +311,11 @@ class TestElasticsearchTaskHandler:
|
|
|
304
311
|
ts = pendulum.now().add(seconds=-seconds)
|
|
305
312
|
logs, metadatas = self.es_task_handler.read(ti, 1, {"offset": 0, "last_log_timestamp": str(ts)})
|
|
306
313
|
if AIRFLOW_V_3_0_PLUS:
|
|
314
|
+
logs = list(logs)
|
|
307
315
|
if seconds > 5:
|
|
308
316
|
# we expect a log not found message when checking began more than 5 seconds ago
|
|
309
317
|
expected_pattern = r"^\*\*\* Log .* not found in Elasticsearch.*"
|
|
310
|
-
assert re.match(expected_pattern, logs) is not None
|
|
318
|
+
assert re.match(expected_pattern, logs[0].event) is not None
|
|
311
319
|
assert metadatas["end_of_log"] is True
|
|
312
320
|
else:
|
|
313
321
|
# we've "waited" less than 5 seconds so it should not be "end of log" and should be no log message
|
|
@@ -360,8 +368,9 @@ class TestElasticsearchTaskHandler:
|
|
|
360
368
|
},
|
|
361
369
|
)
|
|
362
370
|
if AIRFLOW_V_3_0_PLUS:
|
|
371
|
+
logs = list(logs)
|
|
363
372
|
assert logs[0].event == "::group::Log message source details"
|
|
364
|
-
assert logs[0].sources == ["
|
|
373
|
+
assert logs[0].sources == ["http://localhost:9200"]
|
|
365
374
|
assert logs[1].event == "::endgroup::"
|
|
366
375
|
assert logs[2].event == "some random stuff"
|
|
367
376
|
|
|
@@ -382,8 +391,9 @@ class TestElasticsearchTaskHandler:
|
|
|
382
391
|
def test_read_with_none_metadata(self, ti):
|
|
383
392
|
logs, metadatas = self.es_task_handler.read(ti, 1)
|
|
384
393
|
if AIRFLOW_V_3_0_PLUS:
|
|
394
|
+
logs = list(logs)
|
|
385
395
|
assert logs[0].event == "::group::Log message source details"
|
|
386
|
-
assert logs[0].sources == ["
|
|
396
|
+
assert logs[0].sources == ["http://localhost:9200"]
|
|
387
397
|
assert logs[1].event == "::endgroup::"
|
|
388
398
|
assert logs[2].event == "some random stuff"
|
|
389
399
|
|
|
@@ -431,8 +441,9 @@ class TestElasticsearchTaskHandler:
|
|
|
431
441
|
ts = pendulum.now()
|
|
432
442
|
logs, metadatas = self.es_task_handler.read(ti, 1, {})
|
|
433
443
|
if AIRFLOW_V_3_0_PLUS:
|
|
444
|
+
logs = list(logs)
|
|
434
445
|
assert logs[0].event == "::group::Log message source details"
|
|
435
|
-
assert logs[0].sources == ["
|
|
446
|
+
assert logs[0].sources == ["http://localhost:9200"]
|
|
436
447
|
assert logs[1].event == "::endgroup::"
|
|
437
448
|
assert logs[2].event == "some random stuff"
|
|
438
449
|
|
|
@@ -520,8 +531,9 @@ class TestElasticsearchTaskHandler:
|
|
|
520
531
|
},
|
|
521
532
|
)
|
|
522
533
|
if AIRFLOW_V_3_0_PLUS:
|
|
534
|
+
logs = list(logs)
|
|
523
535
|
assert logs[0].event == "::group::Log message source details"
|
|
524
|
-
assert logs[0].sources == ["
|
|
536
|
+
assert logs[0].sources == ["http://localhost:9200"]
|
|
525
537
|
assert logs[1].event == "::endgroup::"
|
|
526
538
|
assert logs[2].event == "some random stuff"
|
|
527
539
|
|
|
@@ -586,6 +598,7 @@ class TestElasticsearchTaskHandler:
|
|
|
586
598
|
|
|
587
599
|
self.body = {
|
|
588
600
|
"message": self.test_message,
|
|
601
|
+
"event": self.test_message,
|
|
589
602
|
"log_id": f"{self.DAG_ID}-{self.TASK_ID}-2016_01_01T00_00_00_000000-1",
|
|
590
603
|
"offset": 1,
|
|
591
604
|
"asctime": "2020-12-24 19:25:00,962",
|
|
@@ -599,11 +612,13 @@ class TestElasticsearchTaskHandler:
|
|
|
599
612
|
logs, _ = self.es_task_handler.read(
|
|
600
613
|
ti, 1, {"offset": 0, "last_log_timestamp": str(ts), "end_of_log": False}
|
|
601
614
|
)
|
|
602
|
-
expected_message = "[2020-12-24 19:25:00,962] {taskinstance.py:851} INFO - some random stuff - "
|
|
603
615
|
if AIRFLOW_V_3_0_PLUS:
|
|
604
|
-
|
|
616
|
+
logs = list(logs)
|
|
617
|
+
assert logs[2].event == self.test_message
|
|
605
618
|
else:
|
|
606
|
-
assert
|
|
619
|
+
assert (
|
|
620
|
+
logs[0][0][1] == "[2020-12-24 19:25:00,962] {taskinstance.py:851} INFO - some random stuff - "
|
|
621
|
+
)
|
|
607
622
|
|
|
608
623
|
@pytest.mark.db_test
|
|
609
624
|
def test_read_with_json_format_with_custom_offset_and_host_fields(self, ti):
|
|
@@ -618,6 +633,7 @@ class TestElasticsearchTaskHandler:
|
|
|
618
633
|
|
|
619
634
|
self.body = {
|
|
620
635
|
"message": self.test_message,
|
|
636
|
+
"event": self.test_message,
|
|
621
637
|
"log_id": f"{self.DAG_ID}-{self.TASK_ID}-2016_01_01T00_00_00_000000-1",
|
|
622
638
|
"log": {"offset": 1},
|
|
623
639
|
"host": {"name": "somehostname"},
|
|
@@ -632,11 +648,13 @@ class TestElasticsearchTaskHandler:
|
|
|
632
648
|
logs, _ = self.es_task_handler.read(
|
|
633
649
|
ti, 1, {"offset": 0, "last_log_timestamp": str(ts), "end_of_log": False}
|
|
634
650
|
)
|
|
635
|
-
expected_message = "[2020-12-24 19:25:00,962] {taskinstance.py:851} INFO - some random stuff - "
|
|
636
651
|
if AIRFLOW_V_3_0_PLUS:
|
|
637
|
-
|
|
652
|
+
logs = list(logs)
|
|
653
|
+
assert logs[2].event == self.test_message
|
|
638
654
|
else:
|
|
639
|
-
assert
|
|
655
|
+
assert (
|
|
656
|
+
logs[0][0][1] == "[2020-12-24 19:25:00,962] {taskinstance.py:851} INFO - some random stuff - "
|
|
657
|
+
)
|
|
640
658
|
|
|
641
659
|
@pytest.mark.db_test
|
|
642
660
|
def test_read_with_custom_offset_and_host_fields(self, ti):
|
|
@@ -649,6 +667,7 @@ class TestElasticsearchTaskHandler:
|
|
|
649
667
|
|
|
650
668
|
self.body = {
|
|
651
669
|
"message": self.test_message,
|
|
670
|
+
"event": self.test_message,
|
|
652
671
|
"log_id": self.LOG_ID,
|
|
653
672
|
"log": {"offset": 1},
|
|
654
673
|
"host": {"name": "somehostname"},
|
|
@@ -661,7 +680,7 @@ class TestElasticsearchTaskHandler:
|
|
|
661
680
|
if AIRFLOW_V_3_0_PLUS:
|
|
662
681
|
pass
|
|
663
682
|
else:
|
|
664
|
-
assert
|
|
683
|
+
assert logs[0][0][1] == "some random stuff"
|
|
665
684
|
|
|
666
685
|
@pytest.mark.db_test
|
|
667
686
|
def test_close(self, ti):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|