https://mattia-giupponi.medium.com/advanced-installation-of-geonode-on-ubuntu-a00dbbc23532
Set ubuntu user password
sudo su -
passwd ubuntu
New Password: A2%j-Ub_RrRr14
Retype
sudo su ubuntu
# Install Python
# sudo apt install -y python3.11-dev python3.11-venv virtualenvwrapper
sudo apt install -y python3-all-dev python3.10-dev python3.10-venv virtualenvwrapper
Install Java
sudo apt install openjdk-11-jdk-headless default-jdk-headless -y
Check for git install
sudo apt install git
Update ubuntu environment
sudo add-apt-repository ppa:ubuntugis/ppa
sudo apt update -y; sudo apt upgrade -y;
Install Dependencies
sudo apt install -y build-essential gdal-bin \
python3-gdal \
libxml2 libxml2-dev gettext zlib1g-dev libmemcached-dev\
libxslt1-dev libjpeg-dev libpng-dev libpq-dev libgdal-dev \
software-properties-common build-essential \
git unzip gcc zlib1g-dev libgeos-dev libproj-dev
# Install Postgresql DB - Version to 15
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
sudo wget --no-check-certificate --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt update -y; sudo apt install -y postgresql-15 postgresql-15-postgis-3 postgresql-15-postgis-3-scripts postgresql-15 postgresql-client-15
# Create geonode user
sudo service postgresql start
sudo -u postgres createuser -P geonode
# Use password: geonode
# Create geonode and geonode_data DBs
sudo -u postgres createdb -O geonode geonode
sudo -u postgres createdb -O geonode geonode_data
# Create PostGIS Extensions
# Use psql
sudo -u postgres psql -d geonode -c 'CREATE EXTENSION postgis;'
sudo -u postgres psql -d geonode -c 'GRANT ALL ON geometry_columns TO PUBLIC;'
sudo -u postgres psql -d geonode -c 'GRANT ALL ON spatial_ref_sys TO PUBLIC;'
sudo -u postgres psql -d geonode -c 'GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO geonode;'
sudo -u postgres psql -d geonode -c 'GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO geonode;'
sudo -u postgres psql -d geonode_data -c 'CREATE EXTENSION postgis;'
sudo -u postgres psql -d geonode_data -c 'GRANT ALL ON geometry_columns TO PUBLIC;'
sudo -u postgres psql -d geonode_data -c 'GRANT ALL ON spatial_ref_sys TO PUBLIC;'
sudo -u postgres psql -d geonode_data -c 'GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO geonode;'
sudo -u postgres psql -d geonode_data -c 'GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO geonode;'
#Set configuration for postgres user to be trust, all others encrypted password
sudo nano /etc/postgresql/15/main/pg_hba.conf
sudo service postgresql restart
#Install Geoserver
#Geoserver install
#Tomcat 9 install
# Create tomcat user
sudo useradd -m -U -d /opt/tomcat -s /bin/bash tomcat
sudo usermod -a -G www-data tomcat
#Download tomcat - check version - 9 not 10
VERSION=9.0.85; wget https://archive.apache.org/dist/tomcat/tomcat-9/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz
# Extract to /opt/tomcat directory
sudo mkdir /opt/tomcat
sudo tar -xf apache-tomcat-${VERSION}.tar.gz -C /opt/tomcat/; rm apache-tomcat-${VERSION}.tar.gz
# Create symbolic link to allow for updated versions
sudo ln -s /opt/tomcat/apache-tomcat-${VERSION} /opt/tomcat/latest
# Create systemd file with link to java and start/stop operations
# Check the correct JAVA_HOME location
JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::")
echo $JAVA_HOME
$> /usr/lib/jvm/java-11-openjdk-amd64/
# Let's create the tomcat service
sudo nano /etc/systemd/system/tomcat9.service
#Paste content
[Unit]
Description=Tomcat 9 servlet container
After=network.target
RequiresMountsFor=/var/log/geoserver /opt/data/geoserver_data /opt/data/geoserver_cache
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom -Djava.awt.headless=true"
Environment="CATALINA_BASE=/opt/tomcat/latest"
Environment="CATALINA_HOME=/opt/tomcat/latest"
Environment="CATALINA_PID=/opt/tomcat/latest/temp/tomcat.pid"
# Security
ReadWritePaths=/opt/data/geoserver_data
ReadWritePaths=/var/log/geoserver
ReadWritePaths=/opt/data/geoserver_cache
ExecStart=/opt/tomcat/latest/bin/startup.sh
ExecStop=/opt/tomcat/latest/bin/shutdown.sh
[Install]
WantedBy=multi-user.target
## End content
## stop running tomcat for GeoServer provisioning
sudo systemctl daemon-reload
sudo systemctl stop tomcat9
## Prepare Java Environment
# Configure java options
sudo sed -i -e 's/xom-\*\.jar/xom-\*\.jar,bcprov\*\.jar/g' /opt/tomcat/latest/conf/catalina.properties
sudo touch /opt/tomcat/latest/bin/setenv.sh
export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::")
echo 'JAVA_HOME='$JAVA_HOME | sudo tee --append /opt/tomcat/latest/bin/setenv.sh
sudo sed -i -e "s/JAVA_OPTS=/#JAVA_OPTS=/g" /opt/tomcat/latest/bin/setenv.sh
echo 'GEOSERVER_DATA_DIR="/opt/data/geoserver_data"' | sudo tee --append /opt/tomcat/latest/bin/setenv.sh
echo 'GEOSERVER_LOG_LOCATION="/opt/data/geoserver_logs/geoserver.log"' | sudo tee --append /opt/tomcat/latest/bin/setenv.sh
echo 'GEOWEBCACHE_CACHE_DIR="/opt/data/geoserver_cache"' | sudo tee --append /opt/tomcat/latest/bin/setenv.sh
echo 'GEOFENCE_DIR="$GEOSERVER_DATA_DIR/geofence"' | sudo tee --append /opt/tomcat/latest/bin/setenv.sh
echo 'PRINT_BASE_URL="http://localhost/geoserver/pdf"' | sudo tee --append /opt/tomcat/latest/bin/setenv.sh
echo 'TIMEZONE="UTC"' | sudo tee --append /opt/tomcat/latest/bin/setenv.sh
echo 'JAVA_OPTS="-server -Djava.awt.headless=true -Xms512m -Xmx2048m -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -Dfile.encoding=UTF8 -Duser.timezone=$TIMEZONE -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DALLOW_ENV_PARAMETRIZATION=true -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL=$PRINT_BASE_URL -DGEOSERVER_DATA_DIR=$GEOSERVER_DATA_DIR -Dgeofence.dir=$GEOFENCE_DIR -DGEOSERVER_LOG_LOCATION=$GEOSERVER_LOG_LOCATION -DGEOWEBCACHE_CACHE_DIR=$GEOWEBCACHE_CACHE_DIR"' | sudo tee --append /opt/tomcat/latest/bin/setenv.sh
# Change ownership and make executable
sudo chown -R tomcat:www-data /opt/tomcat/
sudo sh -c 'chmod +x /opt/tomcat/latest/bin/*.sh'
# Create target folders
sudo mkdir -p /opt/data
sudo mkdir -p /opt/data/geoserver_data
sudo mkdir -p /var/log/geoserver
sudo mkdir -p /opt/data/geoserver_cache
sudo mkdir -p /opt/data/geoserver_logs
## set the directory permissions
sudo chmod -Rf 775 /opt/data
sudo chmod -Rf 775 /opt/data/geoserver_data
sudo chmod 2750 /var/log/geoserver
sudo chmod -Rf 775 /opt/data/geoserver_cache
sudo chmod -Rf 775 /opt/data/geoserver_logs
sudo touch /opt/data/geoserver_logs/geoserver.log
sudo touch /var/log/jvm.log
sudo chmod -Rf 777 /var/log/jvm.log
# Download and extract the default GEOSERVER_DATA_DIR
cd /opt/data/geoserver_data
GS_VERSION=2.23.3
sudo wget --no-check-certificate "https://artifacts.geonode.org/geoserver/$GS_VERSION/geonode-geoserver-ext-web-app-data.zip" -O data-$GS_VERSION.zip
sudo unzip data-$GS_VERSION.zip
sudo mv data/* .
## set geoserver directory ownership
sudo chown -Rf tomcat:www-data /opt/data/geoserver_data
sudo chown -R tomcat:adm /var/log/geoserver
sudo chown -Rf tomcat:www-data /opt/data/geoserver_cache
sudo chown -Rf tomcat:www-data /opt/data/geoserver_logs
## temporary placeholder for download war file
cd /opt && sudo mkdir -p geoserver && cd geoserver
## install geoserver war
sudo wget --no-check-certificate "https://artifacts.geonode.org/geoserver/$GS_VERSION/geoserver.war" -O geoserver-$GS_VERSION.war
sudo mv geoserver-$GS_VERSION.war /opt/tomcat/latest/webapps/geoserver.war
# Fix Geoserver default proxy base URL
sudo nano /opt/data/geoserver_data/global.xml
@@ -4,7 +4,7 @@
UTF-8
8
http://geoserver.org
- http://localhost:8080/geoserver
+ http://geonode.imperialbeachca.gov/geoserver
false
false
----- End
## start Tomcat9
sudo systemctl restart tomcat9
## Follow the startup logs
sudo tail -500f /var/log/tomcat9/catalina.out
sudo tail -500f /opt/data/geoserver_logs/geoserver.log
Get Geonode files for python3.10
sudo mkdir -p /opt/geonode; sudo usermod -a -G www-data $USER; sudo chown -Rf $USER:www-data /opt/geonode/; sudo chmod -Rf 775 /opt/geonode/
cd /opt/
sudo git clone https://github.com/GeoNode/geonode.git -b 4.2.x geonode
Create virtual environment
# Create Geonode Virtual Environment
which python3.10 # copy the path of python executable
# Create the GeoNode Virtual Environment (first time only)
export WORKON_HOME=~/.virtualenvs
source /usr/share/virtualenvwrapper/virtualenvwrapper.sh
mkvirtualenv --python=/usr/bin/python3.10 geonode #Use python 3.10 path from above
# To enter Virtual Environment in future
source /usr/share/virtualenvwrapper/virtualenvwrapper.sh
workon geonode
# Permanently save virtualenvwrapper environment
nano ~/.bashrc
# Write to the bottom of the file
export WORKON_HOME=~/.virtualenvs
source /usr/share/virtualenvwrapper/virtualenvwrapper.sh
# Geonode based on Python3.10
#Install Geonode file dependencies
cd geonode
pip install -r requirements.txt --upgrade
pip install -e . --upgrade
pip install pygdal=="`gdal-config --version`.*"
# Initialize Geonode
sudo chmod +x *.sh
sudo chmod -Rf 777 geonode/static_root/ geonode/uploaded/
./paver_local.sh sync
# Run Geonode
python manage.py runserver
############ NGINX NEW VERSION 1.25
# Backup config files
sudo cp -r /etc/nginx /etc/nginx-backup
# Use process stated here:
# https://ubuntuhandbook.org/index.php/2024/01/install-nginx-ubuntu-2204/
sudo apt install wget coreutils
sudo mkdir -p /etc/apt/keyrings
wget -qO - https://nginx.org/packages/keys/nginx_signing.key | sudo tee /etc/apt/keyrings/nginx_signing.key
sudo nano /etc/apt/sources.list.d/nginx.sources
# Contents
Types: deb
URIs: https://nginx.org/packages/mainline/ubuntu/
Suites: jammy
Components: nginx
Architectures: amd64
Signed-By: /etc/apt/keyrings/nginx_signing.key
# End Contents
sudo apt update
# Install UWSGI
sudo apt install -y uwsgi uwsgi-plugin-python3
# Geonode Environment Variables
# List from Vanilla Install docs
env = DJANGO_SETTINGS_MODULE=geonode.settings
env = GEONODE_INSTANCE_NAME=geonode
env = GEONODE_LB_HOST_IP=
env = GEONODE_LB_PORT=
# #################
# backend
# #################
env = POSTGRES_USER=postgres
env = POSTGRES_PASSWORD=postgres
env = GEONODE_DATABASE=geonode
env = GEONODE_DATABASE_PASSWORD=geonode
env = GEONODE_GEODATABASE=geonode_data
env = GEONODE_GEODATABASE_PASSWORD=geonode
env = GEONODE_DATABASE_SCHEMA=public
env = GEONODE_GEODATABASE_SCHEMA=public
env = DATABASE_HOST=localhost
env = DATABASE_PORT=5432
env = DATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode
env = GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode_data
env = GEONODE_DB_CONN_MAX_AGE=0
env = GEONODE_DB_CONN_TOUT=5
env = DEFAULT_BACKEND_DATASTORE=datastore
env = BROKER_URL=amqp://admin:admin@localhost:5672//
env = ASYNC_SIGNALS=False
env = SITEURL=http://localhost/
env = ALLOWED_HOSTS="['*']"
# Data Uploader
env = DEFAULT_BACKEND_UPLOADER=geonode.importer
env = TIME_ENABLED=True
env = MOSAIC_ENABLED=False
env = HAYSTACK_SEARCH=False
env = HAYSTACK_ENGINE_URL=http://elasticsearch:9200/
env = HAYSTACK_ENGINE_INDEX_NAME=haystack
env = HAYSTACK_SEARCH_RESULTS_PER_PAGE=200
# #################
# nginx
# HTTPD Server
# #################
env = GEONODE_LB_HOST_IP=localhost
env = GEONODE_LB_PORT=80
# IP or domain name and port where the server can be reached on HTTPS (leave HOST empty if you want to use HTTP only)
# port where the server can be reached on HTTPS
env = HTTP_HOST=localhost
env = HTTPS_HOST=
env = HTTP_PORT=8000
env = HTTPS_PORT=443
# #################
# geoserver
# #################
env = GEOSERVER_WEB_UI_LOCATION=http://localhost/geoserver/
env = GEOSERVER_PUBLIC_LOCATION=http://localhost/geoserver/
env = GEOSERVER_LOCATION=http://localhost:8080/geoserver/
env = GEOSERVER_ADMIN_USER=admin
env = GEOSERVER_ADMIN_PASSWORD=geoserver
env = OGC_REQUEST_TIMEOUT=5
env = OGC_REQUEST_MAX_RETRIES=1
env = OGC_REQUEST_BACKOFF_FACTOR=0.3
env = OGC_REQUEST_POOL_MAXSIZE=10
env = OGC_REQUEST_POOL_CONNECTIONS=10
# Java Options & Memory
env = ENABLE_JSONP=true
env = outFormat=text/javascript
env = GEOSERVER_JAVA_OPTS="-Djava.awt.headless=true -Xms2G -Xmx4G -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL=http://geoserver:8080/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine"
# #################
# Security
# #################
# Admin Settings
env = ADMIN_USERNAME=admin
env = ADMIN_PASSWORD=admin
env = ADMIN_EMAIL=admin@localhost
# EMAIL Notifications
env = EMAIL_ENABLE=False
env = DJANGO_EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
env = DJANGO_EMAIL_HOST=localhost
env = DJANGO_EMAIL_PORT=25
env = DJANGO_EMAIL_HOST_USER=
env = DJANGO_EMAIL_HOST_PASSWORD=
env = DJANGO_EMAIL_USE_TLS=False
env = DJANGO_EMAIL_USE_SSL=False
env = DEFAULT_FROM_EMAIL='GeoNode '
# Session/Access Control
env = LOCKDOWN_GEONODE=False
env = CORS_ORIGIN_ALLOW_ALL=True
env = X_FRAME_OPTIONS="SAMEORIGIN"
env = SESSION_EXPIRED_CONTROL_ENABLED=True
env = DEFAULT_ANONYMOUS_VIEW_PERMISSION=True
env = DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=True
# Users Registration
env = ACCOUNT_OPEN_SIGNUP=True
env = ACCOUNT_EMAIL_REQUIRED=True
env = ACCOUNT_APPROVAL_REQUIRED=False
env = ACCOUNT_CONFIRM_EMAIL_ON_GET=False
env = ACCOUNT_EMAIL_VERIFICATION=none
env = ACCOUNT_EMAIL_CONFIRMATION_EMAIL=False
env = ACCOUNT_EMAIL_CONFIRMATION_REQUIRED=False
env = ACCOUNT_AUTHENTICATION_METHOD=username_email
env = AUTO_ASSIGN_REGISTERED_MEMBERS_TO_REGISTERED_MEMBERS_GROUP_NAME=True
# OAuth2
env = OAUTH2_API_KEY=
env = OAUTH2_CLIENT_ID=Jrchz2oPY3akmzndmgUTYrs9gczlgoV20YPSvqaV
env = OAUTH2_CLIENT_SECRET=rCnp5txobUo83EpQEblM8fVj3QT5zb5qRfxNsuPzCqZaiRyIoxM4jdgMiZKFfePBHYXCLd7B8NlkfDBY9HKeIQPcy5Cp08KQNpRHQbjpLItDHv12GvkSeXp6OxaUETv3
# GeoNode APIs
env = API_LOCKDOWN=False
env = TASTYPIE_APIKEY=
# #################
# Production and
# Monitoring
# #################
env = DEBUG=False
env = SECRET_KEY='myv-y4#7j-d*p-__@j#*3z@!y24fz8%^z2v6atuy4bo9vqr1_a'
env = CACHE_BUSTING_STATIC_ENABLED=False
env = MEMCACHED_ENABLED=False
env = MEMCACHED_BACKEND=django.core.cache.backends.memcached.MemcachedCache
env = MEMCACHED_LOCATION=127.0.0.1:11211
env = MEMCACHED_LOCK_EXPIRE=3600
env = MEMCACHED_LOCK_TIMEOUT=10
env = MAX_DOCUMENT_SIZE=2
env = CLIENT_RESULTS_LIMIT=5
env = API_LIMIT_PER_PAGE=1000
# GIS Client
env = GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY=mapstore
env = MAPBOX_ACCESS_TOKEN=
env = BING_API_KEY=
env = GOOGLE_API_KEY=
# Monitoring
env = MONITORING_ENABLED=True
env = MONITORING_DATA_TTL=365
env = USER_ANALYTICS_ENABLED=True
env = USER_ANALYTICS_GZIP=True
env = CENTRALIZED_DASHBOARD_ENABLED=False
env = MONITORING_SERVICE_NAME=local-geonode
env = MONITORING_HOST_NAME=geonode
# Other Options/Contribs
env = MODIFY_TOPICCATEGORY=True
env = AVATAR_GRAVATAR_SSL=True
env = EXIF_ENABLED=True
env = CREATE_LAYER=True
env = FAVORITE_ENABLED=True
# End Environment Variables List
# Create Geonode UWSGI Config
sudo nano /etc/uwsgi/apps-available/geonode.ini
## Geonode config contents
[uwsgi]
uwsgi-socket = 0.0.0.0:8000
# http-socket = 0.0.0.0:8000
gid = www-data
plugins = python3
virtualenv = /home/ubuntu/.virtualenvs/geonode
for-readline = /opt/geonode/.env_local
env = %(_)
endfor =
chdir = /opt/geonode
module = geonode.wsgi:application
strict = false
master = true
enable-threads = true
vacuum = true ; Delete sockets during shutdown
single-interpreter = true
die-on-term = true ; Shutdown when receiving SIGTERM (default is respawn)
need-app = true
# logging
# path to where uwsgi logs will be saved
logto = /opt/data/logs/geonode.log
daemonize = /opt/data/logs/geonode.log
touch-reload = /opt/geonode/geonode/wsgi.py
buffer-size = 32768
harakiri = 60 ; forcefully kill workers after 60 seconds
py-callos-afterfork = true ; allow workers to trap signals
max-requests = 1000 ; Restart workers after this many requests
max-worker-lifetime = 3600 ; Restart workers after this many seconds
reload-on-rss = 2048 ; Restart workers after this much resident memory
worker-reload-mercy = 60 ; How long to wait before forcefully killing workers
cheaper-algo = busyness
processes = 128 ; Maximum number of workers allowed
cheaper = 8 ; Minimum number of workers allowed
cheaper-initial = 16 ; Workers created at startup
cheaper-overload = 1 ; Length of a cycle in seconds
cheaper-step = 16 ; How many workers to spawn at a time
cheaper-busyness-multiplier = 30 ; How many cycles to wait before killing workers
cheaper-busyness-min = 20 ; Below this threshold, kill workers (if stable for multiplier cycles)
cheaper-busyness-max = 70 ; Above this threshold, spawn new workers
cheaper-busyness-backlog-alert = 16 ; Spawn emergency workers if more than this many requests are waiting in the queue
cheaper-busyness-backlog-step = 2 ; How many emergency workers to create if there are too many requests in the queue
## End Content
# Enable the GeoNode UWSGI config
sudo ln -s /etc/uwsgi/apps-available/geonode.ini /etc/uwsgi/apps-enabled/geonode.ini
# Restart UWSGI Service
sudo pkill -9 -f uwsgi
# Create the UWSGI system service
# Create the executable
sudo vim /usr/bin/geonode-uwsgi-start.sh
#!/bin/bash
sudo uwsgi --ini /etc/uwsgi/apps-enabled/geonode.ini
sudo chmod +x /usr/bin/geonode-uwsgi-start.sh
# Create the systemctl Service
sudo vim /etc/systemd/system/geonode-uwsgi.service
# Contents
[Unit]
Description=GeoNode UWSGI Service
After=rc-local.service
[Service]
User=root
PIDFile=/run/geonode-uwsgi.pid
ExecStart=/usr/bin/geonode-uwsgi-start.sh
PrivateTmp=true
Type=simple
Restart=always
KillMode=process
TimeoutSec=900
[Install]
WantedBy=multi-user.target
# End Contents
# Enable the UWSGI service
sudo systemctl daemon-reload
sudo systemctl start geonode-uwsgi.service
sudo systemctl status geonode-uwsgi.service
sudo systemctl enable geonode-uwsgi.service
# Follow logs
sudo tail -500f /var/log/uwsgi/app/geonode.log