-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added approaches to move loganalyzer to pytest. #1
Conversation
Signed-off-by: Yuriy Volynets <yuriyv@mellanox.com>
doc/loganalyzer_to_pytest.md
Outdated
Module "loganalyzer.py" with class "Loganalyzer". | ||
"Loganalyzer" class - executes shell commands on DUT. | ||
**"Loganalyzer" class interface:** | ||
- __init__(match: list, expect: list, ignore: list) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While creating Loganalyzer instance, it would be better to pass the DUT information to it. DUT information is needed by subsequent methods.
doc/loganalyzer_to_pytest.md
Outdated
- extract_syslog() - calls "extract_syslog" from "log_processor.py" | ||
- upload_search_files(dest) - upload match, expect, ignore files to the DUT | ||
- parse_summary_file() - convert generated on DUT "result.loganalysis.{TEST_NAME}..." file to json. | ||
- parse_result_file() - convert generated on DUT "summary.loganalysis.{TEST_NAME}" file to json. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the methods that are internally used by Loganalyzer, we can consider hide them using the "_" prefix.
doc/loganalyzer_to_pytest.md
Outdated
Usage example: | ||
|
||
def test(localhost, ansible_adhoc, testbed): | ||
loganalyzer = Loganalyzer(match="{PATH}/loganalyzer_common_match.txt", expect="{PATH}/loganalyzer_common_expect.txt", ignore="{PATH}/loganalyzer_common_ignore.txt") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The loganalyzer can load and copy the common match/expect/ignore files by default. And we can consider adding extra argument for skipping the common pattern files.
doc/loganalyzer_to_pytest.md
Outdated
result = loganalyzer.analyze() | ||
if result["summary"]["TOTAL MATCHES"] != 0: | ||
loganalyzer.fetch_fail_artifacts(dst="test/{}".format(loganalyzer.unic_test_name)) | ||
pytest.fail("SOME_MESSAGE\n{}\n{}".format(result["summary"], result["match_messages"])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When test failed, I think we need to keep the capability of generating dump and copy related files to sonic-mgmt container for further analysis. While generating dump, we can consider collecting logs within 1 hour by default. If more logs are needed, the time range should can be passed in by an extra argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"When test failed, I think we need to keep the capability of generating dump and copy related files to sonic-mgmt container for further analysis." Agree but maybe better will be to have this functionality in some pytest fixture which has access to the DUT?
doc/loganalyzer_to_pytest.md
Outdated
loganalyzer.fetch_fail_artifacts(dst="test/{}".format(loganalyzer.unic_test_name)) | ||
pytest.fail("SOME_MESSAGE\n{}\n{}".format(result["summary"], result["match_messages"])) | ||
|
||
#### Approach 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I vote for approach 1 because less work is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added new commit with udpdates but based on the approach 2. Because it will be more flexible and will require less work done on the DUT side.
doc/loganalyzer_to_pytest.md
Outdated
- init() - Add start marker to the DUT syslog. | ||
- analyze() - Extract syslog and copy it to ansible host. Analyze extracted syslog files localy. Return python dictionary object. | ||
Return example: | ||
{"summary": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The formatting in rendered view is messed up
doc/loganalyzer_to_pytest.md
Outdated
loganalyzer.init() | ||
|
||
# Add search marker specific for None MAC test | ||
loganalyzer.update_match(action="add", type="match", "Runtime error: can't parse mac address 'None'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think action='pop' is needed. I would better recreate the loganalyzer object rather than keeping in mind which matches I removed and which not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disagree. 1 - Probably this class will be wrapped in pytets fixture, so object recreation does not fit.
2 - We need interface to add/remove specific regexp entries to tune search, so such interface will be ok in such case.
3 - If there is a need we can add "extend" flag to "load_common_config()" which can clear config:
- if "extend is True", load common configuration and add to the existed.
- if "extend is False", clear previous configuration and load common.
doc/loganalyzer_to_pytest.md
Outdated
loganalyzer.init() | ||
|
||
# Add search marker specific for None MAC test | ||
loganalyzer.update_match(action="add", type="match", "Runtime error: can't parse mac address 'None'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add_match/add_expect/add_ignore seems to me better interface than passing a type.
BTW, 'type' is a bad name for key/variable in python
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it will be better but in such case also will be needed del_match/del_expect/del_ignore. So it increase number of methods for similar functionality.
doc/loganalyzer_to_pytest.md
Outdated
|
||
from loganalyzer import Loganalyzer | ||
def test(localhost, ansible_adhoc, testbed): | ||
loganalyzer = Loganalyzer() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the default in this case, why load_common_config is a different method? What if the user will not call load_common_config/update_match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this approach, when loganalyzer is initializing:
loganalyzer = Loganalyzer()
It does not have configured search regexp (does not know what markers to search in the logs).
As we have common regular expressions for the DUT (now defined in match, expect and ignore files) they can be loaded/read to the loganalyzer object by calling "loganalyzer.load_common_config()".
In most cases we will need common regexp to be loaded so this can be moved to the "init".
"update_match()" - not required to be used. It can be used if there is a need to remove or update (add test specific) configured regular expressions to search.
doc/loganalyzer_to_pytest.md
Outdated
- init() - Add start marker to the DUT syslog. | ||
- analyze() - Extract syslog and copy it to ansible host. Analyze extracted syslog files localy. Return python dictionary object. | ||
Return example: | ||
{"summary": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a dict with one key. What is the benefit of having everything under key "summary"?
doc/loganalyzer_to_pytest.md
Outdated
loganalyzer.init() | ||
|
||
# Add search marker specific for None MAC test | ||
loganalyzer.update_match(action="add", type="match", "Runtime error: can't parse mac address 'None'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having the option to load a list of regexp is good, but there are a lot of tests which have files with regexps, how can one load these files using "update_match"?
doc/loganalyzer_to_pytest.md
Outdated
loganalyzer.init() | ||
|
||
# Add search marker specific for None MAC test | ||
loganalyzer.update_match(action="add", type="match", "Runtime error: can't parse mac address 'None'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does update_match overrides common or adds incrementaly?
How can one use, lets say, common 'match'/'ignore' but specific 'expect'?
I vote for approach #2, because there is no haste, so we can do things better than they are right now |
Signed-off-by: Yuriy Volynets <yuriyv@mellanox.com>
doc/loganalyzer_to_pytest.md
Outdated
- __init__(ansible_host: ansible_host) | ||
- load_common_config() - Load regular expressions from common configuration files: match, expect and ignore which are located in some configuration directory or with current module. Clear previous configured match, expect and ignore. Save loaded configuration. | ||
- parse_regexp_file(file_path) - read and parse regular expressions from specified file. Return list of strings of defined regular expressions. | ||
- run_cmd(callable, *args, **kwargs) - call function and analyze DUT logs, return the same result as "analyze" function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use a wrapper here rather than directly call the functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is analog to the "roles/test/tasks/run_command_with_log_analyzer.yml" - add start marker, execute function, add stop marker, analyze logs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. It looks good.
- analyze() - Extract syslog and copy it to ansible host. Analyze extracted syslog files localy. Return python dictionary object. | ||
Return example: | ||
{"counters": {"match": 1, "expected_match": 0, "expected_missing_match": 0}, | ||
"match_files": {"/tmp/syslog": {"match": 0, "expected_match": 32}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the log analyzer may be called mutliple times, the logs may be copied to sonic-mgmt container multiple times. I think we need to consider putting the copied files under different temp folders to avoid conflicts.
After analyzing is done, should we cleanup the copied temp log files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"I think we need to consider putting the copied files under different temp folders to avoid conflicts." - Yes it is planned like this.
"After analyzing is done, should we cleanup the copied temp log files?" - Yes we should clean up temp log file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yvolynets-mlnx Can the loganalyzer print whole temp file with DEBUG level. I assume we will run with DEBUG on jenkins and this part of log that is analyzed will be visible in output. Useful I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends on the DUT health, it colud take many lines. We need more comments about this to decide whether to add it automatically.
doc/loganalyzer_to_pytest.md
Outdated
|
||
#### Development | ||
Module "loganalyzer.py" with class "Loganalyzer". Class is intendent to do: | ||
- Add start marker to the DUT syslog |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would the start marker be looked like? Should we consider haveing the start marker string contain testname? If so, testname need to be passed in to the init method as an argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Existed roles\test\files\tools\loganalyzer\loganalyzer.py will be reused, so logic with adding start/stop markers and processing the logs will be the same (will be reused). And yes, start marker is based on the test name.
doc/loganalyzer_to_pytest.md
Outdated
- parse_regexp_file(file_path) - read and parse regular expressions from specified file. Return list of strings of defined regular expressions. | ||
- run_cmd(callable, *args, **kwargs) - call function and analyze DUT logs, return the same result as "analyze" function | ||
- init() - Add start marker to the DUT syslog. | ||
- analyze() - Extract syslog and copy it to ansible host. Analyze extracted syslog files localy. Return python dictionary object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extract syslog and copy it to sonic-mgmt container?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logs will be stored to the host where pytest was started. For now it will be sonic-mgmt container. It will decrease work which are doing on the device side.
doc/loganalyzer_to_pytest.md
Outdated
"/tmp/syslog2": ["Message 1", "Message 2", "Message n"] | ||
} | ||
} | ||
- save_full_log(file_path) - save downloaded DUT syslog logs to the Ansible host folder specified in 'path' input parameter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Save log to DUT or to sonic-mgmt container?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To sonic-mgmt container
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
save_full_log(file_path) - will be better if this will download /tmp/syslog from the DUT to the Ansible host. Because temp logs which are composed by analyze method will be deleted.
Signed-off-by: Yuriy Volynets <yuriyv@mellanox.com>
"Loganalyzer" class interface: | ||
- __init__(ansible_host: ansible_host, run_dir="/tmp") | ||
- load_common_config() - Clear previous configured match, expect and ignore. Load regular expressions from common configuration files: match, expect and ignore which are located in some configuration directory or with current module. Save loaded configuration to the self.match_regex, self.expect_regex and self.ignore_regex attributes. | ||
- parse_regexp_file(file_path) - Read and parse regular expressions from specified file. Return list of strings of defined regular expressions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably a @classmethod
?
Update Interface-Link-bring-up-sequence.md
Signed-off-by: Yuriy Volynets yuriyv@mellanox.com