I'm currently using selenium to get console logs from a chrome browser. My setup code is this and it works well for getting console logs
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# enable browser logging
d = DesiredCapabilities.CHROME
d['goog:loggingPrefs'] = { 'browser':'ALL' }
driver = webdriver.Chrome(desired_capabilities=d)
# load the desired webpage
driver.get(http://192.168.5.5)
# print messages
for entry in driver.get_log('browser'):
print(entry)
The problem is that entry is a dictionary that contains a string of Objects. I can not access what is inside this Object. In a real browser I can expand on these objects and see further information which is usually in the form of a dictionary. How do I get access to these console log object's in python like I would on a browser? It does not have to be through selenium if it is not possible in selenium.
Edit:
Example of the output from entry:
{'level': 'INFO', 'message': 'http://192.168.5.5/app.e52b3dcc.bundle.js 58:31633 "[END REQUEST]: Response:" Object Object', 'source': 'console-api', 'timestamp': 1663609942539}
Example of the object expanded in the browser (The copy and paste doesn't look as good here but you get the idea):
```END REQUEST]: Response:
Object
data1
:
"SOMEPIECEOFDATA"
response
:
{moreData: {…}, status: 1, type: 'response'}
[[Prototype]]
:
Object
Your code is essentially valid. Take this page with your question for example:
caps['goog:loggingPrefs'] = {'browser':'ALL' }
[...]
url = 'https://stackoverflow.com/questions/73778005/python-browser-console-log-objects'
driver.get(url)
logs = driver.get_log('browser')
for item in logs:
print(item)
Result in terminal:
{'level': 'WARNING', 'message': "security - Error with Feature-Policy header: Unrecognized feature: 'speaker'.", 'source': 'security', 'timestamp': 1663614945300}
{'level': 'WARNING', 'message': 'https://pagead2.googlesyndication.com/gpt/pubads_impl_2022091301.js 9:37758 "The following functions are deprecated: googletag.pubads().setTagForChildDirectedTreatment(), googletag.pubads().clearTagForChildDirectedTreatment(), googletag.pubads().setRequestNonPersonalizedAds(), and googletag.pubads().setTagForUnderAgeOfConsent(). Please use googletag.pubads().setPrivacySettings() instead."', 'source': 'console-api', 'timestamp': 1663614947286}
Maybe you need to investigate the logging process itself?
Related
I am using Selenium with ChromeDriver to get the performance log from Chrome.
caps = DesiredCapabilities.CHROME
caps['loggingPrefs'] = {'performance': 'ALL'}
driver = webdriver.Chrome(desired_capabilities=caps)
driver.get("some.website")
time.sleep(5)
for entry in driver.get_log('performance'):
print(entry)
Inspecting these messages, I found a timestamp field with weird value (779922.902049). So my question is what is the format of this timestamp field?
{'message': '{"message":{"method":"Network.responseReceived","params":{"frameId":"29983.1","loaderId":"29983.1","requestId":"29983.1","response":{"connectionId":0,"connectionReused":false,"encodedDataLength":0,"fromDiskCache":fals
e,"fromServiceWorker":false,"headers":{"Access-Control-Allow-Origin":"*","Content-Type":"text/plain;charset=US-ASCII"},"mimeType":"text/plain","protocol":"data","securityState":"unknown","status":200,"statusText":"OK","url":"data:
,"},"timestamp":779922.902049,"type":"Document"}},"webview":"e6d532fe-f007-4397-bf28-4c4a26c79e4d"}', 'level': 'INFO', 'timestamp': 1523607170083}
{'message': '{"message":{"method":"Network.loadingFinished","params":{"encodedDataLength":0,"requestId":"29983.1","timestamp":779922.902067}},"webview":"e6d532fe-f007-4397-bf28-4c4a26c79e4d"}', 'level': 'INFO', 'timestamp': 152360
7170083}
Note that there is another timestamp field in these above message which is milliseconds since epoch. But it is not the field I am asking.
I found that it is number of seconds from last system boot time (i.e. system uptime). I cannot find any document which describe the format of this timestamp though.
For example, in my web-app I have a link with url www.example.com/profile?name=name. When I click to that link, I'm getting a page, where I can change profile's information, BUT after clicking to that link, url in adress bar turns into www.example.com/profile&name=name.
More interesting: when I make some changes and click SAVE - url reverts to www.example.com/profile?name=name.
If I don't click SAVE, just refresh page, i'm getting error 404.
How can it be possible?
P.S My view function
#check_document_access_permission()
def notebook(request, is_embeddable=False):
if not SHOW_NOTEBOOKS.get():
return serve_403_error(request)
notebook_id = request.GET.get('notebook', request.GET.get('editor'))
is_yarn_mode = False
try:
from spark.conf import LIVY_SERVER_SESSION_KIND
is_yarn_mode = LIVY_SERVER_SESSION_KIND.get()
except:
LOG.exception('Spark is not enabled')
return render('notebook.mako', request, {
'editor_id': notebook_id or None,
'notebooks_json': '{}',
'is_embeddable': request.GET.get('is_embeddable', False),
'options_json': json.dumps({
'languages': get_ordered_interpreters(request.user),
'session_properties': SparkApi.get_properties(),
'is_optimizer_enabled': has_optimizer(),
'is_navigator_enabled': has_navigator(request.user),
'editor_type': 'notebook'
}),
'is_yarn_mode': is_yarn_mode,
})
I found error.
In frontend was JS function, which incorrectly changed url.
I have installed a module called Google Scraper (https://github.com/NikolaiT/GoogleScraper) and I copied this code from his profile:
import sys
from GoogleScraper import scrape_with_config, GoogleSearchError
from GoogleScraper.database import ScraperSearch, SERP, Link
def basic_usage():
# See in the config.cfg file for possible values
config = {
'SCRAPING': {
'use_own_ip': 'True',
'keyword': 'Let\'s go bubbles!',
'search_engines': 'yandex',
'num_pages_for_keyword': 1
},
'SELENIUM': {
'sel_browser': 'chrome',
},
'GLOBAL': {
'do_caching': 'False'
}
}
try:
sqlalchemy_session = scrape_with_config(config)
except GoogleSearchError as e:
print(e)
# let's inspect what we got
for search in sqlalchemy_session.query(ScraperSearch).all():
for serp in search.serps:
print(serp)
for link in serp.links:
print(link)
There should a list of links printed, but nothing happens. I guess that the SQLalchemy part is not recognized... I have not used this before. I installed a module called SQLalchemy but do I need to set up something else? What could cause this code not to work?
I want to build an automation testing, so I have to know the errors that appear in the console of chrome.
there is an option to get the error lines that appear in the console?
In order to see the console: right click somewhere in the page, click "inspect element" and then go to "console".
I don't know C# but here's Java code that does the job, I hope you can translate it to C#
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class ChromeConsoleLogging {
private WebDriver driver;
#BeforeMethod
public void setUp() {
System.setProperty("webdriver.chrome.driver", "c:\\path\\to\\chromedriver.exe");
DesiredCapabilities caps = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.ALL);
caps.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
driver = new ChromeDriver(caps);
}
#AfterMethod
public void tearDown() {
driver.quit();
}
public void analyzeLog() {
LogEntries logEntries = driver.manage().logs().get(LogType.BROWSER);
for (LogEntry entry : logEntries) {
System.out.println(new Date(entry.getTimestamp()) + " " + entry.getLevel() + " " + entry.getMessage());
//do something useful with the data
}
}
#Test
public void testMethod() {
driver.get("http://mypage.com");
//do something on page
analyzeLog();
}
}
Pay attention to setUp method in above code. We use LoggingPreferences object to enable logging. There are a few types of logs, but if you want to track console errors then LogType.BROWSER is the one that you should use. Then we pass that object to DesiredCapabilities and further to ChromeDriver constructor and voila - we have an instance of ChromeDriver with logging enabled.
After performing some actions on page we call analyzeLog() method. Here we simply extract the log and iterate through its entries. Here you can put assertions or do any other reporting you want.
My inspiration was this code by Michael Klepikov that explains how to extract performance logs from ChromeDriver.
You can get logs this way:
Driver().Manage().Logs.GetLog();
By specifying what log you are interested in you can get the browser log, that is:
Driver().Manage().Logs.GetLog(LogType.Browser);
Also remember to setup your driver accordingly:
ChromeOptions options = new ChromeOptions();
options.SetLoggingPreference(LogType.Browser, LogLevel.All);
driver = new ChromeDriver("path to driver", options);
This is the c# code for logging the brower log from chrome.
private void CheckLogs()
{
List<LogEntry> logs = Driver.Manage().Logs.GetLog(LogType.Browser).ToList();
foreach (LogEntry log in logs)
{
Log(log.Message);
}
}
here is my code for the actual log:
public void Log(string value, params object[] values)
{
// allow indenting
if (!String.IsNullOrEmpty(value) && value.Length > 0 && value.Substring(0, 1) != "*")
{
value = " " + value;
}
// write the log
Console.WriteLine(String.Format(value, values));
}
As per issue 6832 logging is not implemented yet for C# bindings. So there might not be an easy way to get this working as of now.
Here is a solution to get Chrome logs using the C#, Specflow and Selenium 4.0.0-alpha05.
Pay attention that the same code doesn't work with Selenium 3.141.0.
[AfterScenario]
public void AfterScenario(ScenarioContext context)
{
if (context.TestError != null)
{
GetChromeLogs(context); //Chrome logs are taken only if test fails
}
Driver.Quit();
}
private void GetChromeLogs()
{
var chromeLogs = Driver.Manage().Logs.GetLog(LogType.Browser).ToList();
}
public void Test_DetectMissingFilesToLoadWebpage()
{
try
{
List<LogEntry> logs = driver.Manage().Logs.GetLog(LogType.Browser).ToList();
foreach (LogEntry log in logs)
{
while(logs.Count > 0)
{
String logInfo = log.ToString();
if (log.Message.Contains("Failed to load resource: the server responded with a status of 404 (Not Found)"))
{
Assert.Fail();
}
else
{
Assert.Pass();
}
}
}
}
catch (NoSuchElementException e)
{
test.Fail(e.StackTrace);
}
}
You could do something like this in C#. It is a complete test case. Then print the console output as String i.e logInfo in your report. For some reason, Log(log.Message) from the solution above this one gave me build errors.So, I replaced it.
C# bindings to the Chrome console logs are finally available in Selenium 4.0.0-alpha05. Selenium 3.141.0 and prior do not have support.
Before instantiating a new ChromeDriver object, set the logging preference in a ChromeOptions object and pass that into ChromeDriver:
ChromeOptions options = new ChromeOptions();
options.SetLoggingPreference(LogType.Browser, LogLevel.All);
ChromeDriver driver = new ChromeDriver(options);
Then, to write the Chrome console logs to a flat file:
public void WriteConsoleErrors()
{
string strPath = "C:\\ConsoleErrors.txt";
if (!File.Exists(strPath))
{
File.Create(strPath).Dispose();
}
using (StreamWriter sw = File.AppendText(strPath))
{
var entries = driver.Manage().Logs.GetLog(LogType.Browser);
foreach (var entry in entries)
{
sw.WriteLine(entry.ToString());
}
}
}
driver.manage().logs().get("browser")
Gets all logs printed on the console. I was able to get all logs except Violations. Please have a look here Chrome Console logs not printing Violations
I'm using Selenium to run tests in Chrome via the Python API bindings, and I'm having trouble figuring out how to configure Chrome to make the console.log output from the loaded test available. I see that there are get_log() and log_types() methods on the WebDriver object, and I've seen Get chrome's console log which shows how to do things in Java. But I don't see an equivalent of Java's LoggingPreferences type in the Python API. Is there some way to accomplish what I need?
Ok, finally figured it out:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# enable browser logging
d = DesiredCapabilities.CHROME
d['loggingPrefs'] = { 'browser':'ALL' }
driver = webdriver.Chrome(desired_capabilities=d)
# load the desired webpage
driver.get('http://foo.com')
# print messages
for entry in driver.get_log('browser'):
print(entry)
Entries whose source field equals 'console-api' correspond to console messages, and the message itself is stored in the message field.
Starting from chromedriver, 75.0.3770.8, you have to use goog:loggingPrefs instead of loggingPrefs:
d['goog:loggingPrefs'] = { 'browser':'ALL' }
To complete the answer: starting from chromedriver 75.0.3770.8, you have to use goog:loggingPrefs instead of loggingPrefs.
See Chromedriver changelog: http://chromedriver.chromium.org/downloads or this bug: https://bugs.chromium.org/p/chromedriver/issues/detail?id=2976
if you are using the python logging module (and you should be)... here is a way to add the selenium browser logs to the python logging system..
the get_browser_log_entries() function grabs the logs from eth provded driver, emits them to the python logging module as chrome. (ie chrome.console-api, chrome.network etc..) using the timestamp from the browser.(in case there is a delay before you call get_log)
it could probably do with some better exception handling (like if logging is not turned on ) etc.. but it works most of the time..
hop
import logging
from selenium import webdriver
def get_browser_log_entries(driver):
"""get log entreies from selenium and add to python logger before returning"""
loglevels = { 'NOTSET':0 , 'DEBUG':10 ,'INFO': 20 , 'WARNING':30, 'ERROR':40, 'SEVERE':40, 'CRITICAL':50}
#initialise a logger
browserlog = logging.getLogger("chrome")
#get browser logs
slurped_logs = driver.get_log('browser')
for entry in slurped_logs:
#convert broswer log to python log format
rec = browserlog.makeRecord("%s.%s"%(browserlog.name,entry['source']),loglevels.get(entry['level']),'.',0,entry['message'],None,None)
rec.created = entry['timestamp'] /1000 # log using original timestamp.. us -> ms
try:
#add browser log to python log
browserlog.handle(rec)
except:
print(entry)
#and return logs incase you want them
return slurped_logs
def demo():
caps = webdriver.DesiredCapabilities.CHROME.copy()
caps['goog:loggingPrefs'] = { 'browser':'ALL' }
driver = webdriver.Chrome(desired_capabilities=caps )
driver.get("http://localhost")
consolemsgs = get_browser_log_entries(driver)
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)7s:%(message)s')
logging.info("start")
demo()
logging.info("end")
Note that calling driver.get_log('browser') will cause the next call to return nothing until more logs are written to the console.
I would suggest saving the logs to a variable first. For example below logs_2 will equal [].
If you need something in the console to test you can use:
self.driver.execute_script("""
function myFunction() {
console.log("Window loaded")
}
if(window.attachEvent) {
window.attachEvent('onload', myFunction());
} else {
if(window.onload) {
var curronload = window.onload;
var newonload = function(evt) {
curronload(evt);
myFunction(evt);
};
window.onload = newonload;
} else {
window.onload = myFunction();
}
}
""")
logs_1 = driver.get_log('browser')
print("A::", logs_1 )
logs_2 = driver.get_log('browser')
print("B::", logs_2 )
for entry in logs_1:
print("Aa::",entry)
for entry in logs_2:
print("Bb::",entry)
See the answer from msridhar for what should go above my example code.