Skip to content

Commit 5713ad2

Browse files
authored
Merge pull request #187 from reportportal/develop
Release
2 parents 1593bc1 + 2d7980b commit 5713ad2

28 files changed

+646
-177
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
# Changelog
22

33
## [Unreleased]
4+
### Added
5+
- Ability to pass client instance in `RPLogHandler` constructor, by @HardNorth
6+
- Issue [#179](https://github.com/reportportal/client-Python/issues/179): batch logging request payload size tracking, by @HardNorth
47
### Fixed
5-
- Issue [#182](https://github.com/reportportal/client-Python/issues/182): logger crash on attachments, by @HardNorth
8+
- Issue [#184](https://github.com/reportportal/client-Python/issues/184): early logger initialization exception, by @dagansandler
9+
10+
## [5.2.2]
11+
### Fixed
12+
- Issue [#182](https://github.com/reportportal/client-Python/issues/182): logger crash on empty client, by @HardNorth
613

714
## [5.2.1]
815
### Fixed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ requires = [
44
"setuptools>=40.0",
55
"setuptools-scm",
66
"wheel",
7+
"importlib-metadata"
78
]
89
build-backend = "setuptools.build_meta"

reportportal_client/_local/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
# Copyright (c) 2022 https://reportportal.io .
1+
"""Report Portal client context storing and retrieving module."""
2+
3+
# Copyright (c) 2022 EPAM Systems
24
# Licensed under the Apache License, Version 2.0 (the "License");
35
# you may not use this file except in compliance with the License.
46
# You may obtain a copy of the License at
@@ -10,7 +12,7 @@
1012
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1113
# See the License for the specific language governing permissions and
1214
# limitations under the License
13-
"""Report Portal client context storing and retrieving module."""
15+
1416
from threading import local
1517

1618
__INSTANCES = local()

reportportal_client/_local/__init__.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2022 https://reportportal.io .
1+
# Copyright (c) 2022 EPAM Systems
22
# Licensed under the Apache License, Version 2.0 (the "License");
33
# you may not use this file except in compliance with the License.
44
# You may obtain a copy of the License at

reportportal_client/client.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from requests.adapters import HTTPAdapter, Retry
2121

2222
from ._local import set_current
23-
from .core.log_manager import LogManager
23+
from .core.log_manager import LogManager, MAX_LOG_BATCH_PAYLOAD_SIZE
2424
from .core.rp_requests import (
2525
HttpRequest,
2626
ItemStartRequest,
@@ -58,24 +58,28 @@ def __init__(self,
5858
max_pool_size=50,
5959
launch_id=None,
6060
http_timeout=(10, 10),
61+
log_batch_payload_size=MAX_LOG_BATCH_PAYLOAD_SIZE,
6162
**_):
6263
"""Initialize required attributes.
6364
64-
:param endpoint: Endpoint of the report portal service
65-
:param project: Project name to report to
66-
:param token: Authorization token
67-
:param log_batch_size: Option to set the maximum number of
68-
logs that can be processed in one batch
69-
:param is_skipped_an_issue: Option to mark skipped tests as not
70-
'To Investigate' items on the server side
71-
:param verify_ssl: Option to skip ssl verification
72-
:param max_pool_size: Option to set the maximum number of
73-
connections to save the pool.
74-
:param launch_id: a launch id to use instead of starting own
75-
one
76-
:param http_timeout: a float in seconds for connect and read
77-
timeout. Use a Tuple to specific connect
78-
and read separately.
65+
:param endpoint: Endpoint of the report portal service
66+
:param project: Project name to report to
67+
:param token: Authorization token
68+
:param log_batch_size: Option to set the maximum number of
69+
logs that can be processed in one batch
70+
:param is_skipped_an_issue: Option to mark skipped tests as not
71+
'To Investigate' items on the server
72+
side
73+
:param verify_ssl: Option to skip ssl verification
74+
:param max_pool_size: Option to set the maximum number of
75+
connections to save the pool.
76+
:param launch_id: a launch id to use instead of starting
77+
own one
78+
:param http_timeout: a float in seconds for connect and read
79+
timeout. Use a Tuple to specific connect
80+
and read separately.
81+
:param log_batch_payload_size: maximum size in bytes of logs that can
82+
be processed in one batch
7983
"""
8084
set_current(self)
8185
self._batch_logs = []
@@ -89,6 +93,7 @@ def __init__(self,
8993
self.is_skipped_an_issue = is_skipped_an_issue
9094
self.launch_id = launch_id
9195
self.log_batch_size = log_batch_size
96+
self.log_batch_payload_size = log_batch_payload_size
9297
self.token = token
9398
self.verify_ssl = verify_ssl
9499
self.http_timeout = http_timeout
@@ -109,7 +114,8 @@ def __init__(self,
109114

110115
self._log_manager = LogManager(
111116
self.endpoint, self.session, self.api_v2, self.launch_id,
112-
self.project, log_batch_size=log_batch_size)
117+
self.project, max_entry_number=log_batch_size,
118+
max_payload_size=log_batch_payload_size)
113119

114120
def finish_launch(self,
115121
end_time,

reportportal_client/client.pyi

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class RPClient:
2020
is_skipped_an_issue: bool = ...
2121
launch_id: Text = ...
2222
log_batch_size: int = ...
23+
log_batch_payload_size: int = ...
2324
project: Text = ...
2425
token: Text = ...
2526
verify_ssl: bool = ...
@@ -37,7 +38,8 @@ class RPClient:
3738
retries: int = ...,
3839
max_pool_size: int = ...,
3940
launch_id: Text = ...,
40-
http_timeout: Union[float, Tuple[float, float]] = ...
41+
http_timeout: Union[float, Tuple[float, float]] = ...,
42+
log_batch_payload_size: int = ...
4143
) -> None: ...
4244

4345
def finish_launch(self,

reportportal_client/core/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
1+
# Copyright (c) 2022 EPAM Systems
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License
13+
114
"""This package contains core reportportal-client modules."""

reportportal_client/core/log_manager.py

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
"""This module contains management functionality for processing logs.
2-
3-
Copyright (c) 2018 https://reportportal.io .
4-
Licensed under the Apache License, Version 2.0 (the "License");
5-
you may not use this file except in compliance with the License.
6-
You may obtain a copy of the License at
7-
https://www.apache.org/licenses/LICENSE-2.0
8-
Unless required by applicable law or agreed to in writing, software
9-
distributed under the License is distributed on an "AS IS" BASIS,
10-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11-
See the License for the specific language governing permissions and
12-
limitations under the License.
13-
"""
1+
"""This module contains management functionality for processing logs."""
2+
3+
# Copyright (c) 2022 EPAM Systems
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License
1415

1516
import logging
1617
from threading import Lock
1718

1819
from six.moves import queue
1920

21+
from reportportal_client import helpers
2022
from reportportal_client.core.rp_requests import (
2123
HttpRequest,
2224
RPFile,
@@ -28,31 +30,38 @@
2830

2931
logger = logging.getLogger(__name__)
3032

33+
MAX_LOG_BATCH_PAYLOAD_SIZE = 65000000
34+
3135

3236
class LogManager(object):
3337
"""Manager of the log items."""
3438

3539
def __init__(self, rp_url, session, api_version, launch_id, project_name,
36-
log_batch_size=20, verify_ssl=True):
40+
max_entry_number=20, verify_ssl=True,
41+
max_payload_size=MAX_LOG_BATCH_PAYLOAD_SIZE):
3742
"""Initialize instance attributes.
3843
39-
:param rp_url: Report portal URL
40-
:param session: HTTP Session object
41-
:param api_version: RP API version
42-
:param launch_id: Parent launch UUID
43-
:param project_name: RP project name
44-
:param log_batch_size: The amount of log objects that need to be
45-
gathered before processing
46-
:param verify_ssl: Indicates that it is necessary to verify SSL
47-
certificates within HTTP request
44+
:param rp_url: Report portal URL
45+
:param session: HTTP Session object
46+
:param api_version: RP API version
47+
:param launch_id: Parent launch UUID
48+
:param project_name: RP project name
49+
:param max_entry_number: The amount of log objects that need to be
50+
gathered before processing
51+
:param verify_ssl: Indicates that it is necessary to verify SSL
52+
certificates within HTTP request
53+
:param max_payload_size: maximum size in bytes of logs that can be
54+
processed in one batch
4855
"""
4956
self._lock = Lock()
50-
self._logs_batch = []
57+
self._batch = []
58+
self._payload_size = helpers.TYPICAL_MULTIPART_FOOTER_LENGTH
5159
self._worker = None
5260
self.api_version = api_version
5361
self.queue = queue.PriorityQueue()
5462
self.launch_id = launch_id
55-
self.log_batch_size = log_batch_size
63+
self.max_entry_number = max_entry_number
64+
self.max_payload_size = max_payload_size
5665
self.project_name = project_name
5766
self.rp_url = rp_url
5867
self.session = session
@@ -63,24 +72,31 @@ def __init__(self, rp_url, session, api_version, launch_id, project_name,
6372
.format(rp_url=rp_url, version=self.api_version,
6473
project_name=self.project_name))
6574

66-
def _log_process(self, log_req):
67-
"""Process the given log request.
68-
69-
:param log_req: RPRequestLog object
70-
"""
71-
self._logs_batch.append(log_req)
72-
if len(self._logs_batch) >= self.log_batch_size:
73-
self._send_batch()
74-
7575
def _send_batch(self):
7676
"""Send existing batch logs to the worker."""
77-
batch = RPLogBatch(self._logs_batch)
77+
batch = RPLogBatch(self._batch)
7878
http_request = HttpRequest(
7979
self.session.post, self._log_endpoint, files=batch.payload,
8080
verify_ssl=self.verify_ssl)
8181
batch.http_request = http_request
8282
self._worker.send(batch)
83-
self._logs_batch.clear()
83+
self._batch = []
84+
self._payload_size = helpers.TYPICAL_MULTIPART_FOOTER_LENGTH
85+
86+
def _log_process(self, log_req):
87+
"""Process the given log request.
88+
89+
:param log_req: RPRequestLog object
90+
"""
91+
with self._lock:
92+
rq_size = log_req.multipart_size
93+
if self._payload_size + rq_size >= self.max_payload_size:
94+
if len(self._batch) > 0:
95+
self._send_batch()
96+
self._batch.append(log_req)
97+
self._payload_size += rq_size
98+
if len(self._batch) >= self.max_entry_number:
99+
self._send_batch()
84100

85101
def log(self, time, message=None, level=None, attachment=None,
86102
item_id=None):
@@ -111,7 +127,7 @@ def stop(self):
111127
"""Send last batches to the worker followed by the stop command."""
112128
if self._worker:
113129
with self._lock:
114-
if self._logs_batch:
130+
if self._batch:
115131
self._send_batch()
116132
logger.debug('Waiting for worker {0} to complete'
117133
'processing batches.'.format(self._worker))
Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,72 @@
1+
# Copyright (c) 2022 EPAM Systems
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License
13+
114
from logging import Logger
2-
from requests import Session
315
from threading import Lock
16+
from typing import Dict, List, Optional, Text
417

18+
from requests import Session
519
from six.moves import queue
620

721
from reportportal_client.core.rp_requests import (
8-
HttpRequest as HttpRequest,
9-
RPFile as RPFile,
10-
RPLogBatch as RPLogBatch,
1122
RPRequestLog as RPRequestLog
1223
)
1324
from reportportal_client.core.worker import APIWorker as APIWorker
14-
from typing import Dict, List, Optional, Text
1525

1626
logger: Logger
1727

28+
MAX_LOG_BATCH_PAYLOAD_SIZE: int
29+
30+
1831
class LogManager:
1932
_lock: Lock = ...
2033
_log_endpoint: Text = ...
21-
_logs_batch: List = ...
34+
_batch: List = ...
35+
_payload_size: int = ...
2236
_worker: Optional[APIWorker] = ...
2337
api_version: Text = ...
2438
queue: queue.PriorityQueue = ...
2539
launch_id: Text = ...
26-
log_batch_size: int = ...
40+
max_entry_number: int = ...
2741
project_name: Text = ...
2842
rp_url: Text = ...
2943
session: Session = ...
3044
verify_ssl: bool = ...
45+
max_payload_size: int = ...
46+
3147
def __init__(self,
3248
rp_url: Text,
3349
session: Session,
3450
api_version: Text,
3551
launch_id: Text,
3652
project_name: Text,
37-
log_batch_size: int = ...,
38-
verify_ssl: bool = ...) -> None: ...
53+
max_entry_number: int = ...,
54+
verify_ssl: bool = ...,
55+
max_payload_size: int = ...) -> None: ...
3956

4057
def _log_process(self, log_req: RPRequestLog) -> None: ...
58+
4159
def _send_batch(self) -> None: ...
60+
4261
def log(self,
4362
time: Text,
4463
message: Optional[Text] = ...,
4564
level: Optional[Text] = ...,
4665
attachment: Optional[Dict] = ...,
4766
item_id: Optional[Text] = ...) -> None: ...
67+
4868
def start(self) -> None: ...
69+
4970
def stop(self) -> None: ...
71+
5072
def stop_force(self) -> None: ...

reportportal_client/core/rp_file.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
"""This module contains classes representing RP file object."""
22

3+
# Copyright (c) 2022 EPAM Systems
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License
15+
316
import uuid
417

518

0 commit comments

Comments
 (0)