|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
| 15 | +from logging import WARNING |
| 16 | +from types import MethodType |
| 17 | +from typing import Sequence |
15 | 18 | from unittest import TestCase |
16 | | -from unittest.mock import patch |
| 19 | +from unittest.mock import Mock, patch |
17 | 20 |
|
18 | 21 | from grpc import Compression |
19 | 22 |
|
20 | 23 | from opentelemetry.exporter.otlp.proto.grpc.exporter import ( |
| 24 | + ExportServiceRequestT, |
21 | 25 | InvalidCompressionValueException, |
| 26 | + OTLPExporterMixin, |
| 27 | + RpcError, |
| 28 | + SDKDataT, |
| 29 | + StatusCode, |
22 | 30 | environ_to_compression, |
23 | 31 | ) |
24 | 32 |
|
@@ -47,3 +55,57 @@ def test_environ_to_compression(self): |
47 | 55 | ) |
48 | 56 | with self.assertRaises(InvalidCompressionValueException): |
49 | 57 | environ_to_compression("test_invalid") |
| 58 | + |
| 59 | + @patch("opentelemetry.exporter.otlp.proto.grpc.exporter.expo") |
| 60 | + def test_export_warning(self, mock_expo): |
| 61 | + |
| 62 | + mock_expo.configure_mock(**{"return_value": [0]}) |
| 63 | + |
| 64 | + rpc_error = RpcError() |
| 65 | + |
| 66 | + def code(self): |
| 67 | + return None |
| 68 | + |
| 69 | + rpc_error.code = MethodType(code, rpc_error) |
| 70 | + |
| 71 | + class OTLPMockExporter(OTLPExporterMixin): |
| 72 | + |
| 73 | + _result = Mock() |
| 74 | + _stub = Mock( |
| 75 | + **{"return_value": Mock(**{"Export.side_effect": rpc_error})} |
| 76 | + ) |
| 77 | + |
| 78 | + def _translate_data( |
| 79 | + self, data: Sequence[SDKDataT] |
| 80 | + ) -> ExportServiceRequestT: |
| 81 | + pass |
| 82 | + |
| 83 | + otlp_mock_exporter = OTLPMockExporter() |
| 84 | + |
| 85 | + with self.assertLogs(level=WARNING) as warning: |
| 86 | + # pylint: disable=protected-access |
| 87 | + otlp_mock_exporter._export(Mock()) |
| 88 | + self.assertEqual( |
| 89 | + warning.records[0].message, |
| 90 | + "Failed to export Mock, error code: None", |
| 91 | + ) |
| 92 | + |
| 93 | + def code(self): # pylint: disable=function-redefined |
| 94 | + return StatusCode.CANCELLED |
| 95 | + |
| 96 | + def trailing_metadata(self): |
| 97 | + return {} |
| 98 | + |
| 99 | + rpc_error.code = MethodType(code, rpc_error) |
| 100 | + rpc_error.trailing_metadata = MethodType(trailing_metadata, rpc_error) |
| 101 | + |
| 102 | + with self.assertLogs(level=WARNING) as warning: |
| 103 | + # pylint: disable=protected-access |
| 104 | + otlp_mock_exporter._export(Mock()) |
| 105 | + self.assertEqual( |
| 106 | + warning.records[0].message, |
| 107 | + ( |
| 108 | + "Transient error StatusCode.CANCELLED encountered " |
| 109 | + "while exporting Mock, retrying in 0s." |
| 110 | + ), |
| 111 | + ) |
0 commit comments