Category Archives: PHP

Magento 2.3.3 indexer stuck at reindexing

We have recently added 13K products to our Magento 2 based store. When we tried to run the reindexing process the indexer kept being stuck half way and our store became unreachable. We had to restart mariadb and run the indexer again to complete the reindexing successfully. Since we have a number of jobs running during the night including reindexing we had to find out why this is happening.

After reading up on the problem it became clear that it is some kind of a resource issue. We tried running the reindexing process granting 4G ram for the php process that runs the indexing but the issue was still the same. The command we used was:

php -d memory_limit=4G bin/magento indexer:reindex

After checking magento’s system.log we found the following warnings:

[2020-01-18 09:39:36] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 100000; Allocated memory size: 600000000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []
[2020-01-18 09:39:37] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 100000; Allocated memory size: 600000000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []
[2020-01-18 09:39:38] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 100000; Allocated memory size: 600000000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []
[2020-01-18 09:39:38] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 100000; Allocated memory size: 600000000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []
[2020-01-18 09:39:38] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 100000; Allocated memory size: 600000000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []
[2020-01-18 09:39:38] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 100000; Allocated memory size: 600000000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []
[2020-01-18 09:39:39] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 100000; Allocated memory size: 600000000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []
[2020-01-18 09:39:44] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 100000; Allocated memory size: 600000000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []
[2020-01-18 09:39:48] main.WARNING: Memory size allocated for the temporary table is more than 20% of innodb_buffer_pool_size. Please update innodb_buffer_pool_size or decrease batch size value (which decreases memory usages for the temporary table). Current batch size: 1000; Allocated memory size: 32500000 bytes; InnoDB buffer pool size: 134217728 bytes. [] []

After reading up on this issue we added the following parameter to the maridb’s 50-server.cnf configration file under the [mysqld] section:

innodb_buffer_pool_size=3G

If you use mysql instead of mariadb the file you need to modify is my.cnf.

UPDATE: This didn’t solve the issue permanently we also had to change settings in vendor/magento/module-catalog/etc/di.xml file. batchRowsCount in Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\BatchSizeCalculator to 1000

<preference for="Magento\Catalog\Pricing\Price\MinimalPriceCalculatorInterface" type="Magento\Catalog\Pricing\Price\MinimalTierPriceCalculator" />
<type name="Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\BatchSizeCalculator">
    <arguments>
        <argument name="batchRowsCount" xsi:type="array">
            <item name="default" xsi:type="number">1000</item>
        </argument>
        <argument name="estimators" xsi:type="array">
            <item name="default" xsi:type="object">Magento\Catalog\Model\Indexer\Price\BatchSizeManagement</item>
        </argument>
    </arguments>
</type>

..and the batchRowsCount in Magento\Catalog\Model\Indexer\Category\Product\Action\Full to 10000

   <type name="Magento\Catalog\Model\Indexer\Category\Product\Action\Full">
        <arguments>
            <argument name="batchRowsCount" xsi:type="number">10000</argument>
            <argument name="batchSizeManagement" xsi:type="object">Magento\Catalog\Model\Indexer\CategoryProductBatchSize</argument>
        </arguments>
    </type>

These settings reduce the batch size for the indexer making it lighter on server’s resources. Let’s see how it goes now.

Allowed memory size of 792723456 bytes exhausted at Magento 2 extension installation

When you install a fresh Magento 2 system, you might encounter a nasty error when you would like to install additional extensions for your magento 2 setup. The error shows on the Magento console first:

Check Component Dependency. We found conflicting component dependencies.

In my case this error was related to the fact that the system has run out of memory while it was checking the component dependencies. The Apache error log contained the following:

[Thu Aug 15 17:21:35.703406 2019] [php7:error] [pid 5918] [client 192.168.0.101:63386] PHP Fatal error:  Allowed memory size of 792723456 bytes exhausted (tried to allocate 4096 bytes) in /var/www/html/vendor/composer/composer/src/Composer/DependencyResolver/RuleSetGenerator.php on line 129, referer: http://192.168.0.85/setup/

[Thu Aug 15 17:21:35.712310 2019] [php7:error] [pid 5918] [client 192.168.0.101:63386] PHP Fatal error:  Allowed memory size of 792723456 bytes exhausted (tried to allocate 45056 bytes) in /var/www/html/vendor/magento/framework/Session/SessionManager.php on line 150, referer: http://192.168.0.85/setup/

[Thu Aug 15 17:21:35.723690 2019] [php7:error] [pid 5924] [client 192.168.0.101:63388] PHP Fatal error:  Uncaught Exception: Warning: session_start(): Failed to decode session object. Session has been destroyed in /var/www/html/vendor/magento/framework/Session/SessionManager.php on line 206 in /var/www/html/vendor/magento/framework/App/ErrorHandler.php:61\nStack trace:\n#0 [internal function]: Magento\\Framework\\App\\ErrorHandler->handler(2, 'session_start()...', '/var/www/html/v...', 206, Array)\n#1 /var/www/html/vendor/magento/framework/Session/SessionManager.php(206): session_start()\n#2 /var/www/html/generated/code/Magento/Backend/Model/Auth/Session/Interceptor.php(167): Magento\\Framework\\Session\\SessionManager->start()\n#3 /var/www/html/vendor/magento/framework/Session/SessionManager.php(140): Magento\\Backend\\Model\\Auth\\Session\\Interceptor->start()\n#4 /var/www/html/vendor/magento/module-backend/Model/Auth/Session.php(101): Magento\\Framework\\Session\\SessionManager->__construct(Object(Magento\\Framework\\App\\Request\\Http), Object(Magento\\Framework\\Session\\SidResolver\\Proxy), Object(Magento\\Backend\\Model\\Session\\AdminC in /var/www/html/vendor/magento/framework/App/ErrorHandler.php on line 61, referer: http://192.168.0.85/setup/

[Thu Aug 15 17:21:35.726328 2019] [php7:error] [pid 6010] [client 192.168.0.101:63389] PHP Fatal error:  Uncaught Exception: Warning: session_start(): Failed to decode session object. Session has been destroyed in /var/www/html/vendor/magento/framework/Session/SessionManager.php on line 206 in /var/www/html/vendor/magento/framework/App/ErrorHandler.php:61\nStack trace:\n#0 [internal function]: Magento\\Framework\\App\\ErrorHandler->handler(2, 'session_start()...', '/var/www/html/v...', 206, Array)\n#1 /var/www/html/vendor/magento/framework/Session/SessionManager.php(206): session_start()\n#2 /var/www/html/generated/code/Magento/Backend/Model/Auth/Session/Interceptor.php(167): Magento\\Framework\\Session\\SessionManager->start()\n#3 /var/www/html/vendor/magento/framework/Session/SessionManager.php(140): Magento\\Backend\\Model\\Auth\\Session\\Interceptor->start()\n#4 /var/www/html/vendor/magento/module-backend/Model/Auth/Session.php(101): Magento\\Framework\\Session\\SessionManager->__construct(Object(Magento\\Framework\\App\\Request\\Http), Object(Magento\\Framework\\Session\\SidResolver\\Proxy), Object(Magento\\Backend\\Model\\Session\\AdminC in /var/www/html/vendor/magento/framework/App/ErrorHandler.php on line 61, referer: http://192.168.0.85/setup/

The solution to this issue is to raise the memory limits which would be an easy one if it wasn’t defined at least at 2 location.

First edit the relevant section of the php.ini make sure you are editing the one that is used by the apache2 server. If you are using ubuntu it is usually in the following location:

/etc/php/[version]/apache2/php.ini

Change the memory_limit variable to 2048M from 756M

memory_limit = 2048M

Then open the .htaccess file from your magento root directory and change the memory_limit variable to 2048M from 756M. Be aware that this parameter is defined TWICE in the .htaccess file so change the value in BOTH locations then restart the apache2 server

service apache2 restart

Create the phpinfo.php file in your magento root directory if you don’t already have it. Just create the file and paste the one line shown below in it, then save it.

Now go to your base server url plus the phpini.php file like:

http://192.168.0.85/phpinfo.php

Once the page is open navigate to the memory limit section and check if the settings have changed

The local and master value should both show 2048M.

This solution has solved my issue if you have less memory at your server you might want to experiment with gradually increasing the memory from 756M to 1024M, etc and see if it works with the new amount.

Installing configuring the Appdynamics PHP Agent manually on Ubuntu 16.04.4

The first step is to install the Appdynamics PHP Agent which will monitor the internals of PHP on this Ubuntu Server. We have downloaded the agent from https://downloads.appdynamics.com.

This agent has no pre-defined configuration file included so we need to do the installation and configuration manually. Upload the agent and unpack it into a desired location.

root@HUAPPD001-P1:/app/appdynamics/phpagent# bzip2 -d appdynamics-php-agent-x64-linux-4.4.3.1216.tar.bz2
root@HUAPPD001-P1:/app/appdynamics/phpagent# tar xvf appdynamics-php-agent-x64-linux-4.4.3.1216.tar
root@HUAPPD001-P1:/app/appdynamics/phpagent/appdynamics-php-agent-linux_x64# mv * /app/appdynamics/phpagent/
root@HUAPPD001-P1:/app/appdynamics/phpagent/appdynamics-php-agent-linux_x64# cd ..
root@HUAPPD001-P1:/app/appdynamics/phpagent# rm -rf appdynamics-php-agent-linux_x64
root@HUAPPD001-P1:/app/appdynamics/phpagent# ls -ltr
total 64
-rw-r--r-- 1 root root 2343 máj 5 02:50 Install.txt
drwxrwxr-x 9 root root 4096 máj 5 03:00 proxy
-rw-r--r-- 1 root root 5062 máj 5 03:00 phpcheck.sh
drwxrwxr-x 4 root root 4096 máj 5 03:00 php
drwxrwxrwx 2 root root 4096 máj 5 03:00 logs
-rw-rw-r-- 1 root root 35 máj 5 03:00 LICENSE.txt
-rwxrwxr-x 1 root root 30113 máj 5 03:00 install.sh
-rw-r--r-- 1 root root 305 máj 5 03:00 appdynamics_api_header.php

To install the application we will have to call the install.sh command. This command will perform the following:

  • Copy appdynamics_agent.so to the php extension library. This extension is called automatically anytime a php page is invoked.
  • Copy the appdynamics_agent.ini to the same directory where the php.ini resides
  • Configure the controller-info.xml file.
  • Creates the runProxy executable to start the agent.

The following parameters are mandatory – in this order – for the install.sh:

  • -a account-name@account-access-key which is your unique name and key assigned to you by appdynamics.
  • controller’s hostname  ( make sure host is resolvable and you can connect to the controller’s connection port.
  • controller’s port
  • Application’s name ( Appdynamics application you want the agent to report to )
  • Application tier ( The tier inside the application, it doesn’t have to be pre-created )
  • Application node ( The node belonging to the tier, it doesn’t have to be pre-created )

The full syntax looks like this:

./install.sh -a=account-name@account-access-key hostname-of-controller 8090 WordPress_Test_Environment WordPress_Server_Php wp-server

Install script for AppDynamics PHP Agent 4.4.3.0GA.5b071fef580bca60d0ed12ddb96d7be8864f342c
Found PHP installation in /usr/bin

Detected PHP Version:
 PHP 7.0.30-0ubuntu0.16.04.1 (cli) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
 with Zend OPcache v7.0.30-0ubuntu0.16.04.1, Copyright (c) 1999-2017, by Zend Technologies

PHP version id: 7.0
PHP extensions directory: /usr/lib/php/20151012
PHP ini directory: /etc/php/7.0/cli/conf.d
Controller Host: hostname
Controller Port: 8090
Application Name: WordPress_Test_Environment
Tier Name: WordPress_Server_Php
Node Name: wp-server
Account Name: account-name
Access Key: access-key
SSL Enabled: false
HTTP Proxy Host:
HTTP Proxy Port:
HTTP Proxy User:
HTTP Proxy Password File:

Writing '/app/appdynamics/phpagent/php/conf/appdynamics_agent_log4cxx.xml'
Writing '/etc/php/7.0/cli/conf.d/appdynamics_agent.ini'
Writing '/app/appdynamics/phpagent/proxy/conf/controller-info.xml'
rm -f "/usr/lib/php/20151012/appdynamics_agent.so"
ln -s "/app/appdynamics/phpagent/php/modules/appdynamics_agent_php_7.0.so" "/usr/lib/php/20151012/appdynamics_agent.so"
Writing '/app/appdynamics/phpagent/proxy/

As you can see above the installer found most of the settings automatically and installed the agent. In our case the location of the php.ini was incorrect so we manually locate the php.ini files by executing:

find / -name php.ini
/etc/php/7.0/apache2/php.ini
/etc/php/7.0/cli/php.ini

We found 2 php.ini‘s on our system, one of them is responsible for the settings for the client run php scripts and the other one  is responsible for the apache webserver run php processes. We want to monitor wordpress and mysql so we need to modify the apache one.

  • Open /etc/php/7.0/cli/conf.d/appdynamics_agent.ini
  • Copy all the settings in appdynamics_agent.ini to the end of the php.ini located in /etc/php/7.0/apache2/
  • Restart the apache2 server: service apache2 restart

Now we need to generate some traffic for the appdynamics controller. We have created a load plan with the Paessler Web Server Stress Tool and started loading the website heavily.

In a few minutes data starts flowing into the appdynamics application dashboard.

Transactions also show up in the other views.

Database calls are automatically detected and queries are displayed.

Installing Appdynamics Machine Agent on Ubuntu 16.04.4

Downloading and installing the Appdynamics Machine Agent

We have recently set up a test environment with a PHP/MySQL based test Ubuntu 16.04.4 server. We will now set up monitoring for Linux OS, PHP 7.0 and MySQL.

The first step is to install the PHP Agent the next step is to downloading the machine agent. Open your Appdynamics console and select the Getting Started Wizard.

Then click the Server button on the What do you want to monitor? screen.

At the next screen check if the connection details are correct then click the click here to download  button to acquire the Machine Agent.

Upload the downloaded zip file to your ubuntu server, unpack it to a desired location. This is where you want to run the machine agent from.

Check if the hostname of the appdynamics server is resolvable by simply pinging it, and also check if you can telnet into the port defined in the Configure the Controller step ( above ). The Machine Agent zip should contain the configuration files pre-configured with all the connection details, so in this case we do not have to do this manually. Run the machine agent as root using the following command:

[Your-agent-director]/bin/machine-agent &

root@HUAPPD001-P1:/app/appdynamics/machineagent/bin# ./machine-agent
Using java executable at /app/appdynamics/machineagent/jre/bin/java
Using Java Version [1.8.0_111] for Agent
Using Agent Version [Machine Agent v4.4.3.1214 GA Build Date 2018-04-28 05:12:10]
[INFO] Agent logging directory set to: [/app/appdynamics/machineagent]
Machine Agent Install Directory :/app/appdynamics/machineagent
Machine Agent Temp Directory :/app/appdynamics/machineagent/tmp
Tasks Root Directory :/app/appdynamics/machineagent/controlchannel
[INFO] Agent logging directory set to: [/app/appdynamics/machineagent]
Redirecting all logging statements to the configured logger
15:05:30.460 [system-thread-0] DEBUG com.appdynamics.common.framework.util.EmbeddedModeSecurityManager - Installed
15:05:30.490 [system-thread-0] INFO com.appdynamics.analytics.agent.AnalyticsAgent - Starting analytics agent with arguments [-p, /app/appdynamics/machineagent/monitors/analytics-agent/conf/analytics-agent.properties, -yr, analytics-agent.yml]
Started AppDynamics Machine Agent Successfully.

Once the agent is started it should automatically show up on the appdynamics console in the servers section.

Click on the machine’s name to open the detailed OS monitoring dashboard.

If you run into connection errors you can check and change the connection settings in the configuration file:

[Your-agent-director]/conf/controller-info.xml

Assign the machine agent automatically to an application and to its tiers and nodes

If you only want to use the machine agent on this server, you can hard wire the Application, Tier and Node details in the contoller-info.xml. Please note that if you use for example the PHP Agent on the same box this might stop the PHP Agent to connect to the controller.

There is no need to create the tiers and nodes manually they will be created on the dashboard automatically. We only added the WordPress_Test_Environment Application before the agent assignment. You will need to add the following to the controller-info.xml configuration file:

<force-agent-registration>true</force-agent-registration>
<application-name>WordPress_Test_Environment</application-name>
<tier-name>WordPress_Server</tier-name>
<node-name>huappd001-p1</node-name>

Change the name of the application, tier and node according to your specifications and restart the agent. Once the agent is restarted navigate into the application and verify if the machine agent has been added successfully.

Install PHP DB2 libraries on CentOS

We came across the requirement to manipulate DB2 using PHP scripts. In order to be able to do that you need to the DB2 libraries installed on your machine. First of all install DB2 Express ( desired version, we used 11.1 ). Make sure you are installing the development libraries with the product as you will need this when you compile the DB2 PHP libraries. Once the server is installed check out the content of the following directory /home/db2inst1/sqllib/include/ if you see a bunch of files in there you have the development pack installed and you are good to go. if you used a different instance name obviously check in there 🙂

The following command sequence will get the rest sorted, we assume you already have php installed on your machine.

  • yum install php-pear
  • yum install php-devel
  • yum install gcc
  • pecl install ibm_db2

The installer will ask where the DB2 directories are located,  just define the directory of your instance. Since we have db2inst1 as the instance the DB2 directory is located at /home/db2inst1/sqllib.

The installer will now compile the PHP libraries. Once it is done just add extension=ibm_db2.so into your php.ini file and you are good to go.

Adding a MySQL Data Source to TEPS using JDBC

We had a requirement to display data from a remote MySQL database on TEPS. There is absolutely no documentation on how to do this so I attempt to explain how we managed to sort this out.

1: Check if you can get to the MySQL database from the TEPS server. You can run the following PHP script if it is not giving an error the connection is working fine! Replace
the highlighted variables with your own details.

<?php

// opening DB connection

$dbhost = ‘database_hostname‘;
$dbuser = ‘database_username‘;
$dbpass = ‘database_password‘;

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die (‘Error connecting to mysql’);

$dbname = ‘database_name‘;
mysql_select_db($dbname);

?>

2: Add the MySQL data source to the TEPS datasource list. We used the following command:

/opt/IBM/ITM/bin/tacmd configurePortalServer -s DSUSER2 -p UID=database_user PWD=database_password CONNECTION_TYPE=JDBC KFWJDBCDRIVER=com.mysql.jdbc.Driver KFWDSURL=jdbc:mysql://database_hostname:3306/database_name

This will create the DSUSER2 datasource.

3: Download MySQL JDBC connection driver from http://dev.mysql.com/downloads/connector/j/

4: Add MySQL JDBC connection driver to cq.ini this will ensure that the driver is loaded.

KFW_JVM__CTJDBC__CLASSPATH=$CANDLEHOME$/$BINARCH$/$PRODUCTCODE$/lib/tepjdbc.jar:/app/mysql-connector-java-5.1.24-bin.jar:$KFW_EWAS_HOME$/derby/lib/derby.jar:$KFW_JDBC_DRIVER$

5: Restart TEPS

Once teps is restarted the new data source should show up when you try to create a custom query on TEPS. Simply enter the SQL you would like to run against the MySQL database and the data should show up on teps in table format.

Matrice – Prestashop 1.4.3 – Undefined variable: nb_products FIX

I am rebuilding one of our webshops and run into this nasty error when clicking on the home category from the TOP navigation menu.

Notice: Undefined variable: nb_products in /var/www/html/shopname/tools/smarty/sysplugins/smarty_internal_data.php on line 291 There are no products.

We are using the Matrice theme which is truly amazing however there seems to be an issue here with it. If you run into the same as a quick fix just change the following in the category.tpl:

 

{if $nb_products == 0}{l s=’There are no products.’}

{else}

{if $nb_products == 1}{l s=’There is’}{else}{l s=’There are’}{/if}&#160;
{$nb_products}&#160;
{if $nb_products == 1}{l s=’product.’}{else}{l s=’products.’}{/if}

{/if}

 

to

<!–

{if $nb_products == 0}{l s=’There are no products.’}

{else}

–>

{if $nb_products == 1}{l s=’There is’}{else}{l s=’There are’}{/if}&#160;
{$nb_products}&#160;
{if $nb_products == 1}{l s=’product.’}{else}{l s=’products.’}{/if}
<!–

{/if}

–>

Make sure that you are changing the Matrice theme not the default one 🙂

Handling Hungarian character set from PHP – Ő Ű problem

I have started to write an app in php and run into the good old character set problem.Ő and Ű characters were not displayed correctly however I have converted the data back and forth. The key is to use UTF-8 encoding.

You have to tell php what encoding to use you can achieve this either using the HTML or the PHP definition. Whichever suits you. Add this to the header section of the HTML code:

<meta http-equiv=”content-type” content=”text/html; charset=UTF-8″ >

You can achieve the same using the header php command:

header(“Content-Type: text/html; charset=utf-8”);

Now we have to make sure that the data coming from the mysql database is UTF-8 encoded. Add this right after the database connection line.

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die (‘Error connecting to mysql’); // Add UTF-8 converting after this line
mysql_query(“SET NAMES UTF8”);

Make sure that the php file itself is saved from the editor in UTF-8 format. Each progamming editor has the capability to change the character encoding.

Finally check your database if  the tables and the database are utf8_hungarian_ci encoded. MySQL connection collation should be set to utf8_general_ci.

That should be it 🙂