Tideways and Xhgui using Lando
While I prefer using Valet+ for my Drupal development, I have been asked a few times to share my Lando + Tideways setup. I can’t go into too many details at this point, because it’s been a while since I’ve used this, but here’s my setup. I’ve included some documentation within some of the files (especially at the bottom of .lando.yml).
You can see some explanation and screenshots of Tideways and Xhgui in my Tideways and Xhgui using Dev Desktop post if you need a bit of an introduction. Also, you may be interested in seeing how I got Tideways running with Valet+.
This example is for Drupal 7. You can rework it easily to work with Drupal 8. The .conf may not be required in either case.
Folder/File Structure
1 2 3 4 5 6 |
├── .lando.yml ├── docroot... └── lando ├── drupal7.conf ├── php.ini └── xhgui.yml |
.lando.yml
UPDATE June 4, 2019: If you’re on a new version of Lando you may have to shuffle around your overrides a bit: https://docs.devwithlando.io/guides/updating-to-rc2.html#overrides
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# See documentation at bottom # This will be used in the web server's URL. # Use only numbers, letters and hyphens. name: mysite # drupal8 || drupal7 || lamp recipe: drupal7 # Additional docker compose files. compose: - lando/xhgui.yml # Recipe configuration config: # PHP Version (as string). php: '7.1' # Use only with drupal7 and drupal8 recipes. # nginx || apache via: nginx # Path from app root (comment-out if files are at root level) webroot: docroot # Use only with drupal7 and drupal8. # Recommended: # for Drupal 7: `drush: 8.1.15` # for Drupal 8: `drush: composer` # See https://docs.devwithlando.io/tutorials/drupal8.html#recipe drush: 8.1.15 # true || false xdebug: true config: # See chosen recipe's official documentation for # php, mysql, apache, nginx, etc. config file options. # Add a php.ini file for php overrides. # You may have to `lando restart` to activate changes. php: lando/php.ini # Add a few overrides to the drupal 7 default conf. server: lando/drupal7.conf # Service overrides. # Use `lando info` to see which services are defined by the chosen recipe. services: appserver: run_as_root: # If you add/edit/remove php libraries you may need to `lando rebuild` and `lando resart` # Tideways (this version requires PHP 7.0+). - cd /tmp && git clone https://github.com/tideways/php-profiler-extension.git - cd /tmp/php-profiler-extension && phpize && ./configure && make && make install - echo 'extension=tideways_xhprof.so' > /usr/local/etc/php/conf.d/tideways_xhprof.ini overrides: environment: DB_USER: main_user DB_PASSWORD: main_pass DB_NAME: main_db DB_PORT: 3306 database: # You can connect externally via "external_connection" info from `lando info`. portforward: true type: mysql:5.7 creds: # These credentials are used only for this specific instance. # You can use the same credentials for each Lando site. user: main_user password: main_pass database: main_db # ------------------------------------------------------------------------------------------ # Initial Site Setup # 1. Copy .lando.yml and the lando directory into your site's root or a fresh folder # 2. Edit .lando.yml (set appropriate recipe and config options) # If you specify a webroot (e.g., docroot) it should exist before you proceed) # 3. Update your database credentials in your code (e.g., settings.local.php) # The "host" will be "database" in your site configuration # The user, password, database are specified above # 4. Start the environment with `lando start` # All URLs will appear in green if successful # 5. Import database data (lando db-import) if you have an existing database # 6. Run `lando reboot` (to make sure php libraries load correctly) # 7. Browse to any of the green URLs # # Drupal Usage # Use `lando drush CMD HERE` e.g., `lando drush cr` # # Connecting to MySQL Externally (e.g., Sequel Pro on host machine) # Connect to 127.0.0.1 with the db credentials specified in the database # config above. Use the port number shown in the "external_connection" # information provided by `lando info`. # # Troubleshooting # If you're making changes to this file (.lando.yml) and things aren't working as expected # even after `lando rebuild`, try `lando restart`. # # If your main URL isn't running on port 80 you probably have something else already using # port 80. Multiple lando apps can use port 80, but only if nothing else is already using # port 80. # # Tideways / XHGUI Usage # # Tideways is not "always on" with this current setup. You must explicitly start # collecting data before the thing you want to profile, and stop collecting data # afterwards. When your code is run a file will be created in <thisdir>/lando/tideways/ # (or whatever you set in the file_put_contents() tideways disable command show below). # # You can then visit the "/import" path of the xhgui service in your browser. # Upload the file then use XHGUI to analyze the data. # `lando info` will show you your xhgui URL/port. e.g., http://localhost:8090 # # Here are a few minified one-liners to enable and disable tideways. # Don't forget to update the description value in the 'tideways-disable' line: # # /**tideways-enable*/tideways_xhprof_enable(TIDEWAYS_XHPROF_FLAGS_CPU+TIDEWAYS_XHPROF_FLAGS_MEMORY); # # doSomethingHereThatYouWantToProfile(); # # /**tideways-disable*/$description="YOUR DESCRIPTION HERE";$data=[];$data['profile']=tideways_xhprof_disable();$time=array_key_exists('REQUEST_TIME',$_SERVER)?$_SERVER['REQUEST_TIME']:time();$request_time_float=explode('.',$_SERVER['REQUEST_TIME_FLOAT']);if(!isset($request_time_float[1])){$request_time_float[1]=0;}$request_ts=['sec'=>$time,'usec'=>0];$request_ts_micro=['sec'=>$request_time_float[0],'usec'=>$request_time_float[1]];$data['meta']=['url'=>$description,'SERVER'=>$_SERVER,'get'=>$_GET,'env'=>$_ENV,'request_ts'=>$request_ts,'request_ts_micro'=>$request_ts_micro,'request_date'=>date('Y-m-d',$time),];file_put_contents('/app/lando/tideways/'.date('Y-m-d_H-i-s').'--'.preg_replace('/[^a-z0-9.]+/i','',$description).'.xhprof',json_encode($data)); # # TODO (nice to have): auto-populate xhgui's database # TODO (nice to have): auto configure tideways ini (instead of requiring local overrides) # TODO (nice to have for someone, maybe?): capture every request |
drupal7.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
server { listen 80 default_server; listen 443 ssl; server_name appserver; ssl_certificate /certs/cert.crt; ssl_certificate_key /certs/cert.key; ssl_verify_client off; port_in_redirect off; client_max_body_size 100M; root ${LANDO_WEBROOT}; location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } # Very rarely should these ever be accessed outside of your lan location ~* \.(txt|log)$ { allow 192.168.0.0/16; deny all; } location ~ \..*/.*\.php$ { return 403; } location ~ ^/sites/.*/private/ { return 403; } # Allow "Well-Known URIs" as per RFC 5785 location ~* ^/.well-known/ { allow all; } # Block access to "hidden" files and directories whose names begin with a # period. This includes directories used by version control systems such # as Subversion or Git to store control files. location ~ (^|/)\. { return 403; } location / { # try_files $uri @rewrite; # For Drupal <= 6 try_files $uri /index.php?$query_string; # For Drupal >= 7 } location @rewrite { rewrite ^/(.*)$ /index.php?q=$1; } # Don't allow direct access to PHP files in the vendor directory. location ~ /vendor/.*\.php$ { deny all; return 404; } # In Drupal 8, we must also match new paths where the '.php' appears in # the middle, such as update.php/selection. The rule we use is strict, # and only allows this pattern with the update.php front controller. # This allows legacy path aliases in the form of # blog/index.php/legacy-path to continue to route to Drupal nodes. If # you do not have any paths like that, then you might prefer to use a # laxer rule, such as: # location ~ \.php(/|$) { # The laxer rule will continue to work if Drupal uses this new URL # pattern with front controllers other than update.php in a future # release. location ~ '\.php$|^/update.php' { fastcgi_split_path_info ^(.+?\.php)(|/.*)$; # Security note: If you're running a version of PHP older than the # latest 5.3, you should have "cgi.fix_pathinfo = 0;" in php.ini. # See http://serverfault.com/q/627903/94922 for details. include fastcgi_params; # Block httpoxy attacks. See https://httpoxy.org/. fastcgi_param HTTP_PROXY ""; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param QUERY_STRING $query_string; fastcgi_intercept_errors on; # PHP 5 socket location. #fastcgi_pass unix:/var/run/php5-fpm.sock; # PHP 7 socket location. #fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; #lando fastcgi_pass fpm:9000; fastcgi_read_timeout 300; } # Fighting with Styles? This little gem is amazing. # location ~ ^/sites/.*/files/imagecache/ { # For Drupal <= 6 location ~ ^/sites/.*/files/styles/ { # For Drupal >= 7 try_files $uri @rewrite; } # Handle private files through Drupal. Private file's path can come # with a language prefix. location ~ ^(/[a-z\-]+)?/system/files/ { # For Drupal >= 7 try_files $uri /index.php?$query_string; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; } } |
php.ini
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
[PHP] ;;;;;;;;;;;;;;; ; PHP Globals ; ;;;;;;;;;;;;;;; short_open_tag = Off output_buffering = 4096 allow_call_time_pass_reference = Off variables_order = "GPCS" request_order = "GP" register_long_arrays = Off register_argc_argv = Off magic_quotes_gpc = Off enable_dl = Off allow_url_fopen = On realpath_cache_size = "800K" realpath_cache_ttl = "86400" disable_functions = ;include_path = ".:/usr/share/pear:/usr/share/php" [Date] date.timezone = "UTC" ;;;;;;;;;;;;;;;;;;;;;; ;; PACKAGE SETTINGS ;; ;;;;;;;;;;;;;;;;;;;;;; ; Xdebug xdebug.max_nesting_level = 256 xdebug.show_exception_trace = 0 xdebug.collect_params = 0 xdebug.remote_enable = 1 ;;;;;;;;;;;;;;;;;;;;;;; ;; PANTHEON SETTINGS ;; ;;;;;;;;;;;;;;;;;;;;;;; ; Globals expose_php = on max_execution_time = 300 max_input_time = 900 max_input_vars = 10000 memory_limit = 196M upload_max_filesize = 100M post_max_size = 100M error_reporting = E_ALL & ~E_DEPRECATED ignore_repeated_errors = on html_errors = off display_errors = on log_errors = on ; Using this to insert essential Pantheon functionality. ;auto_prepend_file = prepend.php |
xhgui.yml
1 2 3 4 5 6 |
version: '3' services: xhgui: image: clarencep/xhgui ports: - "80" |
One Comment
Allan Chappell
I was following this as a guide… I noticed you added a drupal7.conf with what you said were a few overrides. I’m trying to make this happen for a d8 site so I wanted to see the differences you came up with so that I could extrapolate a configuration there…
The diff between your config and the current lando drupal7 config is as follows.
$ diff -u landod7.conf drupal7.conf
--- landod7.conf 2020-09-23 16:43:41.910590077 -0500
+++ drupal7.conf 2020-09-23 16:43:27.618215508 -0500
@@ -2,22 +2,16 @@
listen 80 default_server;
listen 443 ssl;
- server_name localhost;
+ server_name appserver;
ssl_certificate /certs/cert.crt;
ssl_certificate_key /certs/cert.key;
ssl_verify_client off;
- ssl_session_cache shared:SSL:1m;
- ssl_session_timeout 5m;
-
- ssl_ciphers HIGH:!aNULL:!MD5;
- ssl_prefer_server_ciphers on;
-
port_in_redirect off;
client_max_body_size 100M;
- root "{{LANDO_WEBROOT}}";
+ root ${LANDO_WEBROOT};
location = /favicon.ico {
log_not_found off;
@@ -36,7 +30,7 @@
deny all;
}
- location ~ \..*/.*\.php$ {
+ location ~ \..*/.*\.php {
return 403;
}
@@ -100,11 +94,12 @@
#fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
#lando
fastcgi_pass fpm:9000;
+ fastcgi_read_timeout 300;
}
# Fighting with Styles? This little gem is amazing.
# location ~ ^/sites/.*/files/imagecache/ { # For Drupal = 7
+ location ~ ^/sites/.*/files/styles/ { # For Drupal >= 7
try_files $uri @rewrite;
}
@@ -118,5 +113,4 @@
expires max;
log_not_found off;
}
-
}
me thinks the only possible big change would be in the server_name? and possible the fastcgi_read_timeout 300? and possible the location regex…
Any thoughts?