From dbcf66f1a428630aa2cd44233a7fec399c990454 Mon Sep 17 00:00:00 2001 From: orrlevinger Date: Mon, 19 Apr 2021 17:15:47 +0300 Subject: [PATCH 1/9] added info, warn, and error to tracer API --- src/lumigo_tracer/__init__.py | 2 +- src/lumigo_tracer/user_utils.py | 70 +++++++++++++++++++++++--------- src/test/unit/test_user_utils.py | 38 +++++++++++++++++ 3 files changed, 89 insertions(+), 21 deletions(-) diff --git a/src/lumigo_tracer/__init__.py b/src/lumigo_tracer/__init__.py index 3bf463ef..d55becab 100644 --- a/src/lumigo_tracer/__init__.py +++ b/src/lumigo_tracer/__init__.py @@ -1,3 +1,3 @@ from .tracer import lumigo_tracer, LumigoChalice # noqa -from .user_utils import report_error, add_execution_tag # noqa +from .user_utils import report_error, add_execution_tag, info, warn, error # noqa from .auto_instrument_handler import _handler # noqa diff --git a/src/lumigo_tracer/user_utils.py b/src/lumigo_tracer/user_utils.py index 93e8f090..678da24f 100644 --- a/src/lumigo_tracer/user_utils.py +++ b/src/lumigo_tracer/user_utils.py @@ -1,12 +1,36 @@ +import json +from typing import Dict + from lumigo_tracer.spans_container import SpansContainer from lumigo_tracer.lumigo_utils import Configuration, warn_client LUMIGO_REPORT_ERROR_STRING = "[LUMIGO_LOG]" MAX_TAGS = 50 +MAX_ELEMENTS_IN_EXTRA = 10 MAX_TAG_KEY_LEN = MAX_TAG_VALUE_LEN = 50 ADD_TAG_ERROR_MSG_PREFIX = "Skipping add_execution_tag: Unable to add tag" +def info(msg: str, error_type: str = "ProgrammaticInfo", extra: Dict[str, str] = None): + log(20, msg, error_type, extra) + + +def warn(msg: str, error_type: str = "ProgrammaticWarn", extra: Dict[str, str] = None): + log(30, msg, error_type, extra) + + +def error(msg: str, error_type: str = "ProgrammaticError", extra: Dict[str, str] = None): + log(40, msg, error_type, extra) + + +def log(level: int, msg: str, error_type: str, extra: Dict[str, str]): + tags_len = SpansContainer.get_span().get_tags_len() + extra = list(filter(lambda element: validate_tag(element[0], str(element[1]), tags_len, True), (extra or {}).items())) + actual = {key: str(value) for key, value in extra[:MAX_ELEMENTS_IN_EXTRA]} + text = json.dumps({"message": msg, "type": error_type, "level": level, **actual}) + print(LUMIGO_REPORT_ERROR_STRING, text) + + def report_error(msg: str): message_with_initials = f"{LUMIGO_REPORT_ERROR_STRING} {msg}" if Configuration.enhanced_print: @@ -16,6 +40,29 @@ def report_error(msg: str): print(message_with_request_id) +def validate_tag(key, value, tags_len, should_log_errors): + if not key or len(key) >= MAX_TAG_KEY_LEN: + if should_log_errors: + warn_client( + f"{ADD_TAG_ERROR_MSG_PREFIX}: key length should be between 1 and {MAX_TAG_KEY_LEN}: {key} - {value}" + ) + return False + if not value or len(value) >= MAX_TAG_VALUE_LEN: + if should_log_errors: + warn_client( + f"{ADD_TAG_ERROR_MSG_PREFIX}: value length should be between 1 and {MAX_TAG_VALUE_LEN}: {key} - {value}" + ) + return False + if tags_len >= MAX_TAGS: + if should_log_errors: + warn_client( + f"{ADD_TAG_ERROR_MSG_PREFIX}: maximum number of tags is {MAX_TAGS}: {key} - {value}" + ) + return False + + return True + + def add_execution_tag(key: str, value: str, should_log_errors: bool = True) -> bool: """ Use this function to add an execution_tag to your function with a dynamic value. @@ -27,28 +74,11 @@ def add_execution_tag(key: str, value: str, should_log_errors: bool = True) -> b :param should_log_errors: Should a log message be printed in case the tag can't be added. """ try: - tags_len = SpansContainer.get_span().get_tags_len() key = str(key) value = str(value) - if not key or len(key) >= MAX_TAG_KEY_LEN: - if should_log_errors: - warn_client( - f"{ADD_TAG_ERROR_MSG_PREFIX}: key length should be between 1 and {MAX_TAG_KEY_LEN}: {key} - {value}" - ) - return False - if not value or len(value) >= MAX_TAG_VALUE_LEN: - if should_log_errors: - warn_client( - f"{ADD_TAG_ERROR_MSG_PREFIX}: value length should be between 1 and {MAX_TAG_VALUE_LEN}: {key} - {value}" - ) - return False - if tags_len >= MAX_TAGS: - if should_log_errors: - warn_client( - f"{ADD_TAG_ERROR_MSG_PREFIX}: maximum number of tags is {MAX_TAGS}: {key} - {value}" - ) - return False - SpansContainer.get_span().add_tag(key, value) + tags_len = SpansContainer.get_span().get_tags_len() + if validate_tag(key, value, tags_len, should_log_errors): + SpansContainer.get_span().add_tag(key, value) except Exception: if should_log_errors: warn_client(ADD_TAG_ERROR_MSG_PREFIX) diff --git a/src/test/unit/test_user_utils.py b/src/test/unit/test_user_utils.py index 03d86534..dd17693b 100644 --- a/src/test/unit/test_user_utils.py +++ b/src/test/unit/test_user_utils.py @@ -1,6 +1,9 @@ from lumigo_tracer.spans_container import SpansContainer from lumigo_tracer.user_utils import ( report_error, + warn, + info, + error, LUMIGO_REPORT_ERROR_STRING, add_execution_tag, MAX_TAG_KEY_LEN, @@ -18,6 +21,41 @@ def test_report_error_with_enhance_print(capsys): assert captured.out == f"{LUMIGO_REPORT_ERROR_STRING} {msg}\n" +def test_info(capsys): + Configuration.enhanced_print = True + msg = '{"message": "This is error message", "type": "ClientError", "level": 20, "a": "3",' \ + ' "b": "True", "c": "aaa", "d": "{}", "aa": "a", "a1": "1", "a2": "2", "a3": "3", "a4": "4", "a5": "5"}' + info('This is error message', 'ClientError', { + "a": 3, + "b": True, + "c": 'aaa', + "d": {}, + "aa": 'a', + "A" * 100: "A" * 100, + "a1": '1', + "a2": '2', + "a3": '3', + "a4": '4', + "a5": '5', + "a6": '6', + "a7": '7', + }) + captured = capsys.readouterr().out.split('\n') + assert captured[1] == f"{LUMIGO_REPORT_ERROR_STRING} {msg}" + + +def test_basic_info_warn_error(capsys): + info('This is error message') + warn('This is error message') + error('This is error message') + captured = capsys.readouterr().out.split('\n') + assert captured[0] == '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticInfo", "level": 20}' + assert captured[1] == '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticWarn", "level": 30}' + assert captured[2] == '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticError", "level": 40}' + + + + def test_report_error_without_enhance_print(capsys): Configuration.enhanced_print = False SpansContainer.get_span().function_span["id"] = "123" From b7ccd4a17d0685cf910faf50ab89f6fc6c8eced7 Mon Sep 17 00:00:00 2001 From: orrlevinger Date: Mon, 19 Apr 2021 17:42:13 +0300 Subject: [PATCH 2/9] added info, warn, and error to tracer API --- src/lumigo_tracer/user_utils.py | 13 +++++-- src/test/unit/test_user_utils.py | 65 +++++++++++++++++++------------- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/lumigo_tracer/user_utils.py b/src/lumigo_tracer/user_utils.py index 678da24f..2e3b830b 100644 --- a/src/lumigo_tracer/user_utils.py +++ b/src/lumigo_tracer/user_utils.py @@ -1,5 +1,5 @@ import json -from typing import Dict +from typing import Dict, Optional from lumigo_tracer.spans_container import SpansContainer from lumigo_tracer.lumigo_utils import Configuration, warn_client @@ -23,10 +23,15 @@ def error(msg: str, error_type: str = "ProgrammaticError", extra: Dict[str, str] log(40, msg, error_type, extra) -def log(level: int, msg: str, error_type: str, extra: Dict[str, str]): +def log(level: int, msg: str, error_type: str, extra: Optional[Dict[str, str]]): tags_len = SpansContainer.get_span().get_tags_len() - extra = list(filter(lambda element: validate_tag(element[0], str(element[1]), tags_len, True), (extra or {}).items())) - actual = {key: str(value) for key, value in extra[:MAX_ELEMENTS_IN_EXTRA]} + extra_filtered = list( + filter( + lambda element: validate_tag(element[0], str(element[1]), tags_len, True), + (extra or {}).items(), + ) + ) + actual = {key: str(value) for key, value in extra_filtered[:MAX_ELEMENTS_IN_EXTRA]} text = json.dumps({"message": msg, "type": error_type, "level": level, **actual}) print(LUMIGO_REPORT_ERROR_STRING, text) diff --git a/src/test/unit/test_user_utils.py b/src/test/unit/test_user_utils.py index dd17693b..75fd375c 100644 --- a/src/test/unit/test_user_utils.py +++ b/src/test/unit/test_user_utils.py @@ -23,37 +23,48 @@ def test_report_error_with_enhance_print(capsys): def test_info(capsys): Configuration.enhanced_print = True - msg = '{"message": "This is error message", "type": "ClientError", "level": 20, "a": "3",' \ - ' "b": "True", "c": "aaa", "d": "{}", "aa": "a", "a1": "1", "a2": "2", "a3": "3", "a4": "4", "a5": "5"}' - info('This is error message', 'ClientError', { - "a": 3, - "b": True, - "c": 'aaa', - "d": {}, - "aa": 'a', - "A" * 100: "A" * 100, - "a1": '1', - "a2": '2', - "a3": '3', - "a4": '4', - "a5": '5', - "a6": '6', - "a7": '7', - }) - captured = capsys.readouterr().out.split('\n') + msg = ( + '{"message": "This is error message", "type": "ClientError", "level": 20, "a": "3",' + ' "b": "True", "c": "aaa", "d": "{}", "aa": "a", "a1": "1", "a2": "2", "a3": "3", "a4": "4", "a5": "5"}' + ) + info( + "This is error message", + "ClientError", + { + "a": 3, + "b": True, + "c": "aaa", + "d": {}, + "aa": "a", + "A" * 100: "A" * 100, + "a1": "1", + "a2": "2", + "a3": "3", + "a4": "4", + "a5": "5", + "a6": "6", + "a7": "7", + }, + ) + captured = capsys.readouterr().out.split("\n") assert captured[1] == f"{LUMIGO_REPORT_ERROR_STRING} {msg}" def test_basic_info_warn_error(capsys): - info('This is error message') - warn('This is error message') - error('This is error message') - captured = capsys.readouterr().out.split('\n') - assert captured[0] == '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticInfo", "level": 20}' - assert captured[1] == '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticWarn", "level": 30}' - assert captured[2] == '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticError", "level": 40}' - - + info("This is error message") + warn("This is error message") + error("This is error message") + info_msg = ( + '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticInfo", "level": 20}' + ) + warn_msg = ( + '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticWarn", "level": 30}' + ) + error_msg = '[LUMIGO_LOG] {"message": "This is error message", "type": "ProgrammaticError", "level": 40}' + captured = capsys.readouterr().out.split("\n") + assert captured[0] == info_msg + assert captured[1] == warn_msg + assert captured[2] == error_msg def test_report_error_without_enhance_print(capsys): From c2267f6af6d6b13489a5c8147ce3605b60a13f37 Mon Sep 17 00:00:00 2001 From: orrlevinger Date: Mon, 19 Apr 2021 17:48:19 +0300 Subject: [PATCH 3/9] added info, warn, and error to tracer API --- src/lumigo_tracer/user_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lumigo_tracer/user_utils.py b/src/lumigo_tracer/user_utils.py index 2e3b830b..4ffebc2c 100644 --- a/src/lumigo_tracer/user_utils.py +++ b/src/lumigo_tracer/user_utils.py @@ -84,6 +84,8 @@ def add_execution_tag(key: str, value: str, should_log_errors: bool = True) -> b tags_len = SpansContainer.get_span().get_tags_len() if validate_tag(key, value, tags_len, should_log_errors): SpansContainer.get_span().add_tag(key, value) + else: + return False except Exception: if should_log_errors: warn_client(ADD_TAG_ERROR_MSG_PREFIX) From 18e93ae09a292af240a495c27884f651223f1c0b Mon Sep 17 00:00:00 2001 From: orrlevinger Date: Tue, 20 Apr 2021 09:59:18 +0300 Subject: [PATCH 4/9] added info, warn, and error to tracer API --- src/test/component/test_component.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/component/test_component.py b/src/test/component/test_component.py index 4727f962..f93cf63a 100644 --- a/src/test/component/test_component.py +++ b/src/test/component/test_component.py @@ -84,7 +84,7 @@ def lambda_test_function(): lambda_test_function() events = SpansContainer.get_span().spans assert len(events) == 1 - assert events[0]["info"]["httpInfo"]["host"] == f"dynamodb.{region}.amazonaws.com" + assert events[0]["info"]["httpInfo"]["hossst"] == f"dynamodb.{region}.amazonaws.com" assert events[0]["info"]["resourceName"] == ddb_resource assert events[0]["info"].get("messageId") == md5hash({"key": {"S": "1"}}) assert "ended" in events[0] From ca74f6458273b0b17bc54f3daf74d6f19f409260 Mon Sep 17 00:00:00 2001 From: orrlevinger Date: Tue, 20 Apr 2021 11:33:54 +0300 Subject: [PATCH 5/9] added info, warn, and error to tracer API --- src/lumigo_tracer/user_utils.py | 81 ++++++++++++++++++++++++---- src/test/component/test_component.py | 2 +- src/test/unit/test_user_utils.py | 39 ++++++++++---- 3 files changed, 101 insertions(+), 21 deletions(-) diff --git a/src/lumigo_tracer/user_utils.py b/src/lumigo_tracer/user_utils.py index 4ffebc2c..c656a6aa 100644 --- a/src/lumigo_tracer/user_utils.py +++ b/src/lumigo_tracer/user_utils.py @@ -1,4 +1,5 @@ import json +import logging from typing import Dict, Optional from lumigo_tracer.spans_container import SpansContainer @@ -11,29 +12,89 @@ ADD_TAG_ERROR_MSG_PREFIX = "Skipping add_execution_tag: Unable to add tag" -def info(msg: str, error_type: str = "ProgrammaticInfo", extra: Dict[str, str] = None): - log(20, msg, error_type, extra) +def info(msg: str, alert_type: str = "ProgrammaticInfo", extra: Dict[str, str] = None): + """ + Use this function to create a log entry in your lumigo platform. + You can use it to dynamically generate alerts programmatically with searchable fields + Then use the the lumigo explore to search and filters logs in an elastic way + + The [info] function will not generate an alert but you can still search by its extra parameters + For example set extra to {"customerId": "123"} than in the explore tab search for "customerId": "123" + to find all logs of that customer KIBANA STYLE!! + + The maximum number of extra fields is 10. + :param msg: a free text to log + :param alert_type: Should be considered as a grouping parameter normally a camelCase + name to indicate the type of this message for example customerCreated. + :param extra: a key value Dict[str, str] keys and values should not be longer than 50 chars or they will be emitted. + """ + log(logging.INFO, msg, alert_type, extra) -def warn(msg: str, error_type: str = "ProgrammaticWarn", extra: Dict[str, str] = None): - log(30, msg, error_type, extra) +def warn(msg: str, alert_type: str = "ProgrammaticWarn", extra: Dict[str, str] = None): + """ + Use this function to create a log entry in your lumigo platform. + You can use it to dynamically generate alerts programmatically with searchable fields + Then use the the lumigo explore to search and filters logs in an elastic way + + The [warn] function will not generate an alert but you can still search by its extra parameters + For example set extra to {"customerId": "123"} than in the explore tab search for "customerId": "123" + to find all logs of that customer KIBANA STYLE!! + + The maximum number of extra fields is 10. + :param msg: a free text to log + :param alert_type: Should be considered as a grouping parameter normally a camelCase + name to indicate the type of this message for example customerCreated. + :param extra: a key value Dict[str, str] keys and values should not be longer than 50 chars or they will be emitted. + """ + log(logging.WARN, msg, alert_type, extra) -def error(msg: str, error_type: str = "ProgrammaticError", extra: Dict[str, str] = None): - log(40, msg, error_type, extra) +def error( + msg: str, + alert_type: Optional[str] = None, + extra: Optional[Dict[str, str]] = None, + err: Optional[Exception] = None, +): + """ + Use this function to create a log entry in your lumigo platform. + You can use it to dynamically generate alerts programmatically with searchable fields + Then use the the lumigo explore to search and filters logs in an elastic way + + The [error] function will generate an alert but you can still search by its extra parameters + For example set extra to {"customerId": "123"} than in the explore tab search for "customerId": "123" + to find all logs of that customer KIBANA STYLE!! + + The maximum number of extra fields is 10. + :param msg: a free text to log + :param alert_type: Should be considered as a grouping parameter normally a camelCase + name to indicate the type of this message for example customerCreated. + :param extra: a key value Dict[str, str] keys and values should not be longer than 50 chars or they will be emitted. + :param err: the actual error object. + """ + + extra = extra or {} + if err and not alert_type: + alert_type = err.__class__.__name__ + alert_type = alert_type or "ProgrammaticError" + if err: + extra["raw_exception"] = str(err) + log(logging.ERROR, msg, alert_type, extra) def log(level: int, msg: str, error_type: str, extra: Optional[Dict[str, str]]): tags_len = SpansContainer.get_span().get_tags_len() - extra_filtered = list( + filtered_extra = list( filter( lambda element: validate_tag(element[0], str(element[1]), tags_len, True), (extra or {}).items(), ) ) - actual = {key: str(value) for key, value in extra_filtered[:MAX_ELEMENTS_IN_EXTRA]} - text = json.dumps({"message": msg, "type": error_type, "level": level, **actual}) - print(LUMIGO_REPORT_ERROR_STRING, text) + extra = {key: str(value) for key, value in filtered_extra[:MAX_ELEMENTS_IN_EXTRA]} + actual = {"message": msg, "type": error_type, "level": level} + if extra: + actual["extra"] = extra + print(LUMIGO_REPORT_ERROR_STRING, json.dumps(actual)) def report_error(msg: str): diff --git a/src/test/component/test_component.py b/src/test/component/test_component.py index f93cf63a..4727f962 100644 --- a/src/test/component/test_component.py +++ b/src/test/component/test_component.py @@ -84,7 +84,7 @@ def lambda_test_function(): lambda_test_function() events = SpansContainer.get_span().spans assert len(events) == 1 - assert events[0]["info"]["httpInfo"]["hossst"] == f"dynamodb.{region}.amazonaws.com" + assert events[0]["info"]["httpInfo"]["host"] == f"dynamodb.{region}.amazonaws.com" assert events[0]["info"]["resourceName"] == ddb_resource assert events[0]["info"].get("messageId") == md5hash({"key": {"S": "1"}}) assert "ended" in events[0] diff --git a/src/test/unit/test_user_utils.py b/src/test/unit/test_user_utils.py index 75fd375c..9c190e21 100644 --- a/src/test/unit/test_user_utils.py +++ b/src/test/unit/test_user_utils.py @@ -21,16 +21,12 @@ def test_report_error_with_enhance_print(capsys): assert captured.out == f"{LUMIGO_REPORT_ERROR_STRING} {msg}\n" -def test_info(capsys): - Configuration.enhanced_print = True - msg = ( - '{"message": "This is error message", "type": "ClientError", "level": 20, "a": "3",' - ' "b": "True", "c": "aaa", "d": "{}", "aa": "a", "a1": "1", "a2": "2", "a3": "3", "a4": "4", "a5": "5"}' - ) - info( - "This is error message", - "ClientError", - { +def test_err_without_alert_type_with_exception(capsys): + msg = '{"message": "This is error message", "type": "RuntimeError", "level": 40, "extra": {"a": "3", "b": "True", "c": "aaa", "d": "{}", "aa": "a", "a1": "1", "a2": "2", "a3": "3", "a4": "4", "a5": "5"}}' + error( + err=RuntimeError("Failed to open database"), + msg="This is error message", + extra={ "a": 3, "b": True, "c": "aaa", @@ -50,6 +46,29 @@ def test_info(capsys): assert captured[1] == f"{LUMIGO_REPORT_ERROR_STRING} {msg}" +def test_err_with_type_and_exception(capsys): + msg = ( + '{"message": "This is error message", "type": "DBError",' + ' "level": 40, "extra": {"raw_exception": "Failed to open database"}}' + ) + error( + err=RuntimeError("Failed to open database"), + msg="This is error message", + alert_type="DBError", + ) + captured = capsys.readouterr().out.split("\n") + assert captured[0] == f"{LUMIGO_REPORT_ERROR_STRING} {msg}" + + +def test_err_with_no_type_and_no_exception(capsys): + msg = '{"message": "This is error message", "type": "ProgrammaticError", "level": 40}' + error( + msg="This is error message", + ) + captured = capsys.readouterr().out.split("\n") + assert captured[0] == f"{LUMIGO_REPORT_ERROR_STRING} {msg}" + + def test_basic_info_warn_error(capsys): info("This is error message") warn("This is error message") From a86af45d37adae6fb489a654abe4a007e3d695a9 Mon Sep 17 00:00:00 2001 From: orrlevinger Date: Tue, 20 Apr 2021 11:58:22 +0300 Subject: [PATCH 6/9] added info, warn, and error to tracer API --- src/lumigo_tracer/user_utils.py | 4 ++-- src/test/unit/test_user_utils.py | 12 +++--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/lumigo_tracer/user_utils.py b/src/lumigo_tracer/user_utils.py index c656a6aa..e75e681b 100644 --- a/src/lumigo_tracer/user_utils.py +++ b/src/lumigo_tracer/user_utils.py @@ -83,10 +83,9 @@ def error( def log(level: int, msg: str, error_type: str, extra: Optional[Dict[str, str]]): - tags_len = SpansContainer.get_span().get_tags_len() filtered_extra = list( filter( - lambda element: validate_tag(element[0], str(element[1]), tags_len, True), + lambda element: validate_tag(element[0], element[1], 0, True), (extra or {}).items(), ) ) @@ -107,6 +106,7 @@ def report_error(msg: str): def validate_tag(key, value, tags_len, should_log_errors): + value = str(value) if not key or len(key) >= MAX_TAG_KEY_LEN: if should_log_errors: warn_client( diff --git a/src/test/unit/test_user_utils.py b/src/test/unit/test_user_utils.py index 9c190e21..914e5a23 100644 --- a/src/test/unit/test_user_utils.py +++ b/src/test/unit/test_user_utils.py @@ -8,7 +8,7 @@ add_execution_tag, MAX_TAG_KEY_LEN, MAX_TAG_VALUE_LEN, - MAX_TAGS, + MAX_TAGS, MAX_ELEMENTS_IN_EXTRA, ) from lumigo_tracer.lumigo_utils import Configuration, EXECUTION_TAGS_KEY @@ -22,7 +22,7 @@ def test_report_error_with_enhance_print(capsys): def test_err_without_alert_type_with_exception(capsys): - msg = '{"message": "This is error message", "type": "RuntimeError", "level": 40, "extra": {"a": "3", "b": "True", "c": "aaa", "d": "{}", "aa": "a", "a1": "1", "a2": "2", "a3": "3", "a4": "4", "a5": "5"}}' + msg = '{"message": "This is error message", "type": "RuntimeError", "level": 40, "extra": {"a": "3", "b": "True", "c": "aaa", "d": "{}", "aa": "a", "a0": "0", "a1": "1", "a2": "2", "a3": "3", "a4": "4"}}' error( err=RuntimeError("Failed to open database"), msg="This is error message", @@ -33,13 +33,7 @@ def test_err_without_alert_type_with_exception(capsys): "d": {}, "aa": "a", "A" * 100: "A" * 100, - "a1": "1", - "a2": "2", - "a3": "3", - "a4": "4", - "a5": "5", - "a6": "6", - "a7": "7", + **{f"a{i}": i for i in range(MAX_ELEMENTS_IN_EXTRA)} }, ) captured = capsys.readouterr().out.split("\n") From b3d039357617f8c1f6a86497268d35e86e09f1ff Mon Sep 17 00:00:00 2001 From: OrrLumigo <81093776+OrrLumigo@users.noreply.github.com> Date: Tue, 20 Apr 2021 12:01:13 +0300 Subject: [PATCH 7/9] Update src/lumigo_tracer/user_utils.py Co-authored-by: saartochner <47108628+saartochner@users.noreply.github.com> --- src/lumigo_tracer/user_utils.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/lumigo_tracer/user_utils.py b/src/lumigo_tracer/user_utils.py index e75e681b..a9b10094 100644 --- a/src/lumigo_tracer/user_utils.py +++ b/src/lumigo_tracer/user_utils.py @@ -15,18 +15,12 @@ def info(msg: str, alert_type: str = "ProgrammaticInfo", extra: Dict[str, str] = None): """ Use this function to create a log entry in your lumigo platform. - You can use it to dynamically generate alerts programmatically with searchable fields - Then use the the lumigo explore to search and filters logs in an elastic way - - The [info] function will not generate an alert but you can still search by its extra parameters - For example set extra to {"customerId": "123"} than in the explore tab search for "customerId": "123" - to find all logs of that customer KIBANA STYLE!! + You can use it to dynamically generate alerts programmatically with searchable fields. + Then use the lumigo explore to search and filters logs in free text. - The maximum number of extra fields is 10. :param msg: a free text to log - :param alert_type: Should be considered as a grouping parameter normally a camelCase - name to indicate the type of this message for example customerCreated. - :param extra: a key value Dict[str, str] keys and values should not be longer than 50 chars or they will be emitted. + :param alert_type: Should be considered as a grouping parameter. This indicates the type of this message. Default: ProgrammaticInfo + :param extra: a key-value dict. Limited to 10 keys and 50 characters per value. """ log(logging.INFO, msg, alert_type, extra) From 129a8d0a52c4dd1f618b7f09f8d75e2bd2d8eccb Mon Sep 17 00:00:00 2001 From: orrlevinger Date: Tue, 20 Apr 2021 12:10:25 +0300 Subject: [PATCH 8/9] added info, warn, and error to tracer API --- src/lumigo_tracer/user_utils.py | 33 ++++++++++---------------------- src/test/unit/test_user_utils.py | 5 +++-- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/lumigo_tracer/user_utils.py b/src/lumigo_tracer/user_utils.py index a9b10094..ab56d61c 100644 --- a/src/lumigo_tracer/user_utils.py +++ b/src/lumigo_tracer/user_utils.py @@ -28,18 +28,12 @@ def info(msg: str, alert_type: str = "ProgrammaticInfo", extra: Dict[str, str] = def warn(msg: str, alert_type: str = "ProgrammaticWarn", extra: Dict[str, str] = None): """ Use this function to create a log entry in your lumigo platform. - You can use it to dynamically generate alerts programmatically with searchable fields - Then use the the lumigo explore to search and filters logs in an elastic way - - The [warn] function will not generate an alert but you can still search by its extra parameters - For example set extra to {"customerId": "123"} than in the explore tab search for "customerId": "123" - to find all logs of that customer KIBANA STYLE!! + You can use it to dynamically generate alerts programmatically with searchable fields. + Then use the lumigo explore to search and filters logs in free text. - The maximum number of extra fields is 10. :param msg: a free text to log - :param alert_type: Should be considered as a grouping parameter normally a camelCase - name to indicate the type of this message for example customerCreated. - :param extra: a key value Dict[str, str] keys and values should not be longer than 50 chars or they will be emitted. + :param alert_type: Should be considered as a grouping parameter. This indicates the type of this message. Default: ProgrammaticWarn + :param extra: a key-value dict. Limited to 10 keys and 50 characters per value. """ log(logging.WARN, msg, alert_type, extra) @@ -52,27 +46,20 @@ def error( ): """ Use this function to create a log entry in your lumigo platform. - You can use it to dynamically generate alerts programmatically with searchable fields - Then use the the lumigo explore to search and filters logs in an elastic way - - The [error] function will generate an alert but you can still search by its extra parameters - For example set extra to {"customerId": "123"} than in the explore tab search for "customerId": "123" - to find all logs of that customer KIBANA STYLE!! + You can use it to dynamically generate alerts programmatically with searchable fields. + Then use the lumigo explore to search and filters logs in free text. - The maximum number of extra fields is 10. :param msg: a free text to log - :param alert_type: Should be considered as a grouping parameter normally a camelCase - name to indicate the type of this message for example customerCreated. - :param extra: a key value Dict[str, str] keys and values should not be longer than 50 chars or they will be emitted. + :param alert_type: Should be considered as a grouping parameter. This indicates the type of this message. Default: take the given exception type or ProgrammaticError if its None + :param extra: a key-value dict. Limited to 10 keys and 50 characters per value. By default we're taking the excpetion raw message :param err: the actual error object. """ extra = extra or {} - if err and not alert_type: - alert_type = err.__class__.__name__ - alert_type = alert_type or "ProgrammaticError" if err: extra["raw_exception"] = str(err) + alert_type = alert_type or err.__class__.__name__ + alert_type = alert_type or "ProgrammaticError" log(logging.ERROR, msg, alert_type, extra) diff --git a/src/test/unit/test_user_utils.py b/src/test/unit/test_user_utils.py index 914e5a23..dc022b7c 100644 --- a/src/test/unit/test_user_utils.py +++ b/src/test/unit/test_user_utils.py @@ -8,7 +8,8 @@ add_execution_tag, MAX_TAG_KEY_LEN, MAX_TAG_VALUE_LEN, - MAX_TAGS, MAX_ELEMENTS_IN_EXTRA, + MAX_TAGS, + MAX_ELEMENTS_IN_EXTRA, ) from lumigo_tracer.lumigo_utils import Configuration, EXECUTION_TAGS_KEY @@ -33,7 +34,7 @@ def test_err_without_alert_type_with_exception(capsys): "d": {}, "aa": "a", "A" * 100: "A" * 100, - **{f"a{i}": i for i in range(MAX_ELEMENTS_IN_EXTRA)} + **{f"a{i}": i for i in range(MAX_ELEMENTS_IN_EXTRA)}, }, ) captured = capsys.readouterr().out.split("\n") From 39a2d73ccae7d261e6b35761a86ff547e734009b Mon Sep 17 00:00:00 2001 From: orrlevinger Date: Tue, 20 Apr 2021 12:32:10 +0300 Subject: [PATCH 9/9] added info, warn, and error to tracer API --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e10af1b8..20117f60 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -115,7 +115,7 @@ jobs: <<: *defaults steps: - checkout_code - - checkout_credentials + - checkout_utils # run tests! - run: echo "export AWS_DEFAULT_REGION=us-west-2" >> $BASH_ENV - run: mkdir -p ~/.aws