ActiveRecord SQL queries not getting logged - mysql

I have been facing a weird problem for some time, wherein ActiveRecord queries are not getting logged in the terminal, or in the Rails console (using ActiveRecord::Base.logger = Logger.new(STDOUT)).
This is the exception that I get:
Could not log "sql.active_record" event. NameError: undefined
local variable or method `s'
for # ActiveSupport::Notifications::Event:0x007f9ae02a60c0.
I tried out a few things, including reinstalling Rails, but to no avail.
Apart from wondering why this is happening, I’m unable to check the actual SQL queries fired against the database as a result.

I ran into something similar a ways back.
I was able to fix it by adding
# config/environments/development.rb
config.logger = Logger.new(STDOUT)
and
# config/environment.rb
# To prevent log buffering
$stdout.sync = true

This problem was due to a stray (and accidental) 's' being inserted in the instrumenter.rb file. Removing the character helped me fix the problem. I'm not sure about why reinstalling rails did not help me though.

Related

MYSQL Select db & Select table issue. Configuration confusion [duplicate]

In my local/development environment, the MySQLi query is performing OK. However, when I upload it on my web host environment, I get this error:
Fatal error: Call to a member function bind_param() on a non-object in...
Here is the code:
global $mysqli;
$stmt = $mysqli->prepare("SELECT id, description FROM tbl_page_answer_category WHERE cur_own_id = ?");
$stmt->bind_param('i', $cur_id);
$stmt->execute();
$stmt->bind_result($uid, $desc);
To check my query, I tried to execute the query via control panel phpMyAdmin and the result is OK.
TL;DR
Always have mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); in your mysqli connection code and always check the PHP errors.
Always replace every PHP variable in the SQL query with a question mark, and execute the query using prepared statement. It will help to avoid syntax errors of all sorts.
Explanation
Sometimes your MySQLi code produces an error like mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given..., Call to a member function bind_param()... or similar. Or even without any error, but the query doesn't work all the same. It means that your query failed to execute.
Every time a query fails, MySQL has an error message that explains the reason. In the older PHP versions such errors weren't transferred to PHP, and all you'd get is a cryptic error message mentioned above. Hence it is very important to configure PHP and MySQLi to report MySQL errors to you. And once you get the error message, fixing it will be a piece of cake.
How to get the error message in MySQLi
First of all, always have this line before MySQLi connect in all your environments:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
After that, all MySQL errors will be transferred into PHP exceptions. An uncaught exception, in turn, makes a PHP fatal error. Thus, in case of a MySQL error, you'll get a conventional PHP error. That will instantly make you aware of the error cause. And the stack trace will lead you to the exact spot where the error occurred.
How to get the error message from PHP
Here is a gist of my article on PHP error reporting:
Reporting errors on a development and live servers must be different. On the development server it is convenient to have errors shown on-screen, but on a live server error messages must be logged instead, so you could find them in the error log later.
Therefore, you must set corresponding configuration options to the following values:
On a development server
error_reporting should be set to E_ALL value;
log_errors should be set to 1 (it is convenient to have logs on a development PC too)
display_errors should be set to 1
On a production server
error_reporting should be set to E_ALL value;
log_errors should be set to 1
display_errors should be set to 0
After that, when MySQL query fails, you will get a PHP error that explains the reason. On a live server, in order to get the error message, you'll have to check the error log.
In case of AJAX call, on a dev server open DevTools (F12), then Network tab. Then initiate the request which result you want to see, and it will appear in the Network tab. Click on it and then the Response tab. There you will see the exact output. On a live server check the error log.
How to actually use it
Just remove any code that checks for the error manually, all those or die(), if ($result), try..catch and such. Simply write your database interaction code right away:
$stmt = $this->con->prepare("INSERT INTO table(name, quantity) VALUES (?,?)");
$stmt->bind_param("si", $name, $quantity);
$stmt->execute();
Again, without any conditions around. If an error occurs, it will be treated like any other error in your code. For example, on a development PC it will just appear on-screen, while on a live site it will be logged for the programmer, whereas for the user's convenience you could use an error handler (but that's a different story which is off topic for MySQLi, but you may read about it in the article linked above).
What to do with the error message you get
First of all you have to locate the problem query. The error message contains the file name and the line number of the exact spot where the error occurred. For the simple code that's enough, but if your code is using functions or classes you may need to follow the stack trace to locate the problem query.
After getting the error message, you have to read and comprehend it. It sounds too obvious if not condescending, but learners often overlook the fact that the error message is not just an alarm signal, but it actually contains a detailed explanation of the problem. And all you need is to read the error message and fix the issue.
Say, if it says that a particular table doesn't exist, you have to check spelling, typos, and letter case. Also you have to make sure that your PHP script connects to a correct database
Or, if it says there is an error in the SQL syntax, then you have to examine your SQL. And the problem spot is right before the query part cited in the error message.
If you don't understand the error message, try to google it. And when browsing the results, stick to answers that explain the error rather than bluntly give the solution. A solution may not work in your particular case, but the explanation will help you to understand the problem and make you able to fix the issue by yourself.
You have to also trust the error message. If it says that number of tokens doesn't match the number of bound variables then it is so. The same goes for the absent tables or columns. Given the choice, whether it's your own mistake or the error message is wrong, always stick to the former. Again it sounds condescending, but hundreds of questions on this very site prove this advise extremely useful.
A list of things you should never ever do in regard of error reporting
Never use an error suppression operator (#)! It makes a programmer unable read the error message and therefore unable to fix the error
Do not use die() or echo or any other function to print the error message on the screen unconditionally. PHP can report errors by itself and do it the right way depends on the environment - so just leave it for PHP.
Do not add a condition to test the query result manually (like if($result)). With error exceptions enabled such condition will just be useless.
Do not use the try..catch operator for echoing the error message. This operator should be used to perform some error handling, like a transaction rollback. But never use it just to report errors - as we learned above, PHP can already do it, the right way.
P.S.
Sometimes there is no error, but no results either. Then it means, there is no data in the database to match your criteria. In this case you have to admit this fact, even if you can swear the data and the criteria are all right. They are not. You have to check them again.
I've got an article that can help in this matter, How to debug database interactions. Although it is written for PDO, the principle is the same. Just follow those instructions step by step and either have your problem solved or have an answerable question for Stack Overflow.

Cannot send commands to remote machine using ssh2-python package

Problem
Hello my problem is that I want to use the ssh2-python package to remotely read a a bunch of files, but I can't seem to send commands to the remote host machine.
Originally I started with the paramiko package and I did get that to work, but I am dealing with a lot of large memory files (which is why I can't bring them to the local machine) and it is a bit too slow. I am currently running Python 3.6.3 & ssh2-python 0.18.0.post1 and have tried changing versions of ssh2-python, but it didn't help.
Code
import socket
from ssh2.session import Session
host_ip=socket.gethostbyname('hostname')
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host_ip,22))
session=Session()
session.handshake(sock)
print(session.userauth_list('username'))
session.userauth_password('username','password')
channel=session.open_session()
channel.execute('echo Hello')
Code Prints the Following
0
['publickey', 'gssapi-keyex', 'gssapi-with-mic', 'password']
0
0
Expectation/Thoughts
I expected the code to print Hello, but instead it just printed 0. It also printed 0 after the handshake and after the call to the authentication method and I have no idea why. It seems like I am in contact with the remote machine as it did print out which authentications it would take, but it doesn't appear to me that I am actually logged in and can do anything. I would really like to use this package as from what I read online it is significantly faster paramiko, (alternatives would be good to) but I can't seem to figure out what is going on here.
Please help and thanks in advance!
You may in fact be connected and executing commands, but channel.execute('ls') returns '0' (it's exit/status code).
If you want to read your response from the server:
channel.execute('echo Hello')
size, data = channel.read()
while size:
size, dt = channel.read()
data += dt
print(data.decode())
The API documentation for ssh2-python is rather sparse, but the examples should get you through some of the basics: https://github.com/ParallelSSH/ssh2-python/tree/master/examples
A complete version of the above is in example_echo.py

MySQL connection failing on same query. Trying to reconnect with default user

I am getting the following error on the same query:
Warning: mysql_query(): Access denied for user 'www-data'#'localhost' (using password: NO)
The error only occurs on the first try from any particular IP. After I refresh the page, the script runs fine. To be more specific, I will run it from a browser in one location, and it will error. If I refresh the page, the problem is fixed. That is until I try from another location.
From what I gather, its losing the connection to the database server and trying to reconnect with the default username. What's confusing me is that it fails on the same query each time. Let's call this query_X. Multiple queries run before query_X including selects, inserts, and updates. Query_X looks like this:
UPDATE game_users
SET status_cd=$tmp_status,
expire_date=date_add('$currentExpire', interval $l_license_duration_days day)
WHERE game_user_id=$l_game_user_id
As an example, the variables being passed are:
$tmp_status = 1;
$currentExpire = '2011-12-05';
$l_license_duration_days = 30;
$l_game_user_id = 1;
What is it about this query that makes the connection fail, and why does refreshing the page fix the problem?
Fyi, I'm using persistent connect.
Edit: I just tried again from an ip that I tried last night. And I received the error again. That is on the first run of the script. After I ran the page a second time, it worked fine.
Edit: It will also error the first time it's run on a particular browser, even if it is on the same IP, i.e. it will error once on firefox and then be fine, error on chrome once and then be fine, etc.
Edit: I've narrowed it down to a mail() function that was happening just before query_X. I still don't know why the mail function is closing the mySQL connection. I've decided to put the mail function (which works properly and sends the email) at the end of the php file, where I would close the connection anyways. It's a hack, but I've spent too much time on this already.
It looks like you closed the connection before some call to mysql_query(). The message of access denied should happen on the mysql_connect() phase.
Are you sure the error is in the query and not in the connect / close functions?

sfErrorNotifierPlugin: The "default" context does not exist

I have installed the sfErrorNotifierPlugin. When both options reportErrors/reportPHPErrors reportPHPWarnings/reportWarnings are set to false, everything is ok. But I want to catch PHP exceptions and warnings to receive E-mails, but then all my tasks fail, including clear-cache. After few hours of tests I'm 100% sure that the problem is with set_exception_handler/set_error_handler.
There's a similar question:
sfErrorNotifierPlugin on symfony task but the author there is having problems with a custom task. In my case, even built-in tasks fail.
I haven't used sfErrorNotifierPlugin, but I have run into 'The “default” context does not exist.' messages before. It happens when a call is made to sfContext::getInstance() and the context simply doesn't exist. I've had this happen a lot from within custom tasks. One solution is to add sfContext::createInstance() before the call to sfContext::getInstance(). This will ensure that a context exists.
There's an interesting blog post on 'Why sfContext::getInstance() is bad' that goes into more detail - http://webmozarts.com/2009/07/01/why-sfcontextgetinstance-is-bad/
Well, the problem could not be solved this way, unfortunately. Using sfErrorNotifierPlugin, I have enabled reporting PHP warning/errors (apart from symfony exceptions) and this resulted in huge problems, e.g. built-in tasks such as clear-cache failed.
The solution I chose was to load the plugin only in non-task mode (project configuration class):
public function setup()
{
$this->enableAllPluginsExcept('sfPropelPlugin');
if ('cli' == php_sapi_name()) $this->disablePlugins('sfErrorNotifierPlugin');
}
WHen a task is executed, everything works normally. When an app is fired from the browser, emails are sent when exception/warning occurs (maybe someone will find it useful).
Arms has explained the problem correctly. But usually context does not exist when executing backend/maintenance tasks on the console. And it is easier if you handle the condition yourself.
Check, if you really need the context?
If you do, what exactly do you need it for?
Sometimes you only want a user to populate a created_by field. You can work around by hard-coding a user ID.
If you want to do something more integrated, create a page (which will have a context) and trigger the task from there.
you can test the existance of the instance before doing something inside a class. Like:
if(sfContext::hasInstance())
$this->microsite_id = sfContext::getInstance()->getUser()->getAttribute('active_microsite');
I've been experiencing the same problem using the plugin sfErrorNotifier.
In my specific case, I noticed a warning was raised:
Warning: ob_start(): function '' not found or invalid function name in /var/www/ncsoft_qa/lib/vendor/symfony/lib/config/sfApplicationConfiguration.class.php on line 155
Notice: ob_start(): failed to create buffer in /var/www/ncsoft_qa/lib/vendor/symfony/lib/config/sfApplicationConfiguration.class.php on line 155
So, checking the file: sfApplicationConfiguration.class.php class, line 155,
I've replaced the ' ' for a null, then the warnings disappears, and also the error!
ob_start(sfConfig::get('sf_compressed') ? 'ob_gzhandler' : ''); bad
ob_start(sfConfig::get('sf_compressed') ? 'ob_gzhandler' : null); good

Rails update_attribute did not hit the mysql database

It only happens in production, when we update some of the records through browser, the change was not saved. it does not seem to be a cache problem as we verified that the data in mysql was still the old data. However, the controller did get hit and flash message returned as if the change was made successfully.
However, we can make the change manually in rails console or mysql withhout any problem.
Any ideas why this is happening?
btw, we recently reconfigure the site to use SSL, it might have something to do with that.
Is there anything that could've prevented the model from being saved?
One way to ensure that the attributes are set and the model is saved is to use the exception raising version which can help fix problems like this:
def update
#model = Model.find(params[:id])
#model.update_attributes(params[:model])
redirect_to(model_path(#model))
end
This could be improved to a more reliable method:
def update
#model = Model.find(params[:id])
# Use exception-throwing update_attributes!
#model.update_attributes!(params[:model])
redirect_to(model_path(#model))
rescue ActiveRecord::RecordNotFound
render(:partial => 'not_found')
rescue ActiveRecord::RecordInvalid
# Delegate back to edit action, something's invalid
edit
render(:action => 'edit')
end
There are occasions where update_attributes may not successfully save.
If you can perform the same update on the same data with the same methods then that is peculiar.