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.

Files changed (46) hide show
  1. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/PKG-INFO +10 -8
  2. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/README.rst +5 -4
  3. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/changelog.rst +25 -0
  4. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/index.rst +5 -3
  5. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/provider.yaml +2 -1
  6. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/pyproject.toml +5 -4
  7. {apache_airflow_providers_elasticsearch-6.3.1/src/airflow/providers → apache_airflow_providers_elasticsearch-6.3.2/src/airflow}/__init__.py +1 -1
  8. {apache_airflow_providers_elasticsearch-6.3.1/tests/system → apache_airflow_providers_elasticsearch-6.3.2/src/airflow/providers}/__init__.py +1 -1
  9. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/__init__.py +1 -1
  10. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/hooks/elasticsearch.py +1 -5
  11. {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
  12. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/version_compat.py +9 -1
  13. {apache_airflow_providers_elasticsearch-6.3.1/tests/unit → apache_airflow_providers_elasticsearch-6.3.2/tests/system}/__init__.py +1 -1
  14. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/system/elasticsearch/example_elasticsearch_query.py +8 -2
  15. {apache_airflow_providers_elasticsearch-6.3.1/src/airflow → apache_airflow_providers_elasticsearch-6.3.2/tests/unit}/__init__.py +1 -1
  16. {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
  17. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/.latest-doc-only-change.txt +0 -0
  18. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/commits.rst +0 -0
  19. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/conf.py +0 -0
  20. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/configurations-ref.rst +0 -0
  21. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/connections/elasticsearch.rst +0 -0
  22. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/hooks/elasticsearch_python_hook.rst +0 -0
  23. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/hooks/elasticsearch_sql_hook.rst +0 -0
  24. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/hooks/index.rst +0 -0
  25. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/installing-providers-from-sources.rst +0 -0
  26. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/integration-logos/Elasticsearch.png +0 -0
  27. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/logging/index.rst +0 -0
  28. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/redirects.txt +0 -0
  29. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/docs/security.rst +0 -0
  30. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/LICENSE +0 -0
  31. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/get_provider_info.py +0 -0
  32. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/hooks/__init__.py +0 -0
  33. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/log/__init__.py +0 -0
  34. {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
  35. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/src/airflow/providers/elasticsearch/log/es_response.py +0 -0
  36. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/conftest.py +0 -0
  37. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/system/elasticsearch/__init__.py +0 -0
  38. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/__init__.py +0 -0
  39. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/hooks/__init__.py +0 -0
  40. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/hooks/test_elasticsearch.py +0 -0
  41. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/__init__.py +0 -0
  42. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/elasticmock/__init__.py +0 -0
  43. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/elasticmock/fake_elasticsearch.py +0 -0
  44. {apache_airflow_providers_elasticsearch-6.3.1 → apache_airflow_providers_elasticsearch-6.3.2}/tests/unit/elasticsearch/log/elasticmock/utilities/__init__.py +0 -0
  45. {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
  46. {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.1
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: ~=3.10
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.1/changelog.html
27
- Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.1
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.1``
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.1/>`_.
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.1/changelog.html>`_.
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.1``
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.1/>`_.
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.1/changelog.html>`_.
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.1
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.1 sdist package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.1.tar.gz>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.1.tar.gz.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.1.tar.gz.sha512>`__)
136
- * `The apache-airflow-providers-elasticsearch 6.3.1 wheel package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.1-py3-none-any.whl>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.1-py3-none-any.whl.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_elasticsearch-6.3.1-py3-none-any.whl.sha512>`__)
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: 1751473399
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.1"
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 = "~=3.10"
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.1"
101
- "Changelog" = "https://airflow.apache.org/docs/apache-airflow-providers-elasticsearch/6.3.1/changelog.html"
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__) # type: ignore
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__) # type: ignore
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.1"
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 # type: ignore[assignment]
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 "default_host"
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: dict | None = None
298
- ) -> tuple[EsLogMsgType, dict]:
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
- metadata = {"offset": 0}
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
- return missing_log_message, metadata
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
- ] # type: ignore[misc]
384
+ ]
379
385
 
386
+ # Flatten all hits, filter to only desired fields, and construct StructuredLogMessage objects
380
387
  message = header + [
381
- StructuredLogMessage(event=concat_logs(hits)) for hits in logs_by_host.values()
382
- ] # type: ignore[misc]
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"] # type: ignore
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: # type: ignore[attr-defined]
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__) # type: ignore
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__) # type: ignore
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 = {"message": self.test_message, "log_id": self.LOG_ID, "offset": 1}
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 == ["default_host"]
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 == ["default_host"]
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 == ["default_host"]
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 == ["default_host"]
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 == ["default_host"]
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 == ["default_host"]
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
- assert logs[2].event == expected_message
616
+ logs = list(logs)
617
+ assert logs[2].event == self.test_message
605
618
  else:
606
- assert logs[0][0][1] == expected_message
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
- assert logs[2].event == expected_message
652
+ logs = list(logs)
653
+ assert logs[2].event == self.test_message
638
654
  else:
639
- assert logs[0][0][1] == expected_message
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 self.test_message == logs[0][0][1]
683
+ assert logs[0][0][1] == "some random stuff"
665
684
 
666
685
  @pytest.mark.db_test
667
686
  def test_close(self, ti):