Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement log rotation #91

Merged
merged 29 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f6bfd5a
misc fixes in libroll
norswap Jan 11, 2024
d3b22e4
move libroll to own package
norswap Jan 11, 2024
87f5db7
split out exceptions, command line run logic, and streams from librol…
norswap Jan 11, 2024
ee17f94
add close logic to Tee
norswap Jan 11, 2024
1ef4b39
add FileStream
norswap Jan 11, 2024
bf0f1b3
fix "failed to promptly kill subprocess"
norswap Jan 11, 2024
11bad3a
migrate global state out of libroll and into own top-level module
norswap Jan 11, 2024
608a1c2
lint
norswap Jan 11, 2024
5cde884
avoid running exit hooks twice
norswap Jan 12, 2024
989d2ab
add early exit monitoring for services
norswap Jan 12, 2024
93764eb
implement log rotation
norswap Jan 13, 2024
cf7c89f
add new "file" forward mode and clarify WriteableStream
norswap Jan 15, 2024
0652e7b
add paymaster and bundler to rotating log files
norswap Jan 15, 2024
2a2dfc1
migrate forward="fd" to forward="file"
norswap Jan 15, 2024
e0ac67d
simplify clean logic and make sure it deletes archived log files
norswap Jan 15, 2024
f086ca7
use log file paths from config where it wasn't already the case
norswap Jan 15, 2024
5516815
correct contract name
norswap Jan 15, 2024
c272317
fix flaky deployment for real for real
norswap Jan 15, 2024
af62ef7
you may be able to go fast!
norswap Jan 15, 2024
705f367
fix unpleasant indentations
norswap Jan 15, 2024
0d3d988
fix doc cross-reference specifiers
norswap Jan 15, 2024
aeb8cc4
avoid circular dependency
norswap Jan 15, 2024
8440826
fix references
norswap Jan 15, 2024
f2d88fa
remove warning when not applicable
norswap Jan 15, 2024
3dca4f6
no build artifacts to clean for blockscout
norswap Jan 15, 2024
b01272a
convert FileStream to always reopen the files, which is necessary to …
norswap Jan 15, 2024
9f3f7a6
enable user-defined logrotate policy override
norswap Jan 15, 2024
c9c9790
remove unused imports & format
norswap Jan 15, 2024
76bd8d0
add logging policy documentation
norswap Jan 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,23 @@ The current version of simple-op-stack-rollup deploys software pinned to the fol
- `sudo apt install python3-pip` on Debian-based systems
- `brew install python` on macOS with Homebrew

The following dependencies will be checked by `roll.py`:
You also need the following installed, `rollop` will warn you if these are missing:

- Some common command line utilities: `make`, `curl`, `tar`, `awk` and `grep`.
- [`logrotate`](https://github.com/logrotate/logrotate)
- `sudo apt install logrotate` on Debian-based systems
- `brew install logrotate` on macOS with Homebrew
- Git
- Docker (if you wish to run the Blockscout block explorer)

`roll.py` will check the following dependencies and install them for you if needed (the script will
always for your permission before installing anything outside the current directory):
`rollop` will check the following dependencies and install them for you if needed (the script will
always ask for your permission before installing anything outside the current directory):

- Python libraries
- [Tomli](https://pypi.org/project/tomli/)
- [PyYAML](https://pypi.org/project/PyYAML/) (for block explorer support)
- These will be installed globally by default
- install them locally instead (in a venv within the roll-op directory), you can run `source
devenv.sh` before running `rollop`.
- These will be installed globally by default. To install them locally instead (in a venv within
the roll-op directory), you can run `source devenv.sh` before running `rollbop`.
- Node.js 20.9.0
- pnpm (`pnpm install -g pnpm`)
- Yarn (for account abstraction support)
Expand Down Expand Up @@ -141,6 +143,15 @@ cast send \
0x3fAB184622Dc19b6109349B94811493BF2a45362
```

## Documentation

See the [doc index](/docs/README.md).

- [OP Stack Primer](/docs/opstack.md)
- [Port Configuration](/docs/port-config.md)
- [Vocabulary](/docs/vocabulary.md)
- [Logging Policy](/docs/logging.md)


## Contributing (for developers building simple-op-stack rollup)

Expand Down
47 changes: 24 additions & 23 deletions account_abstraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,20 @@ def start_bundler(config: Config):
"ERC4337_BUNDLER_ETH_CLIENT_URL": config.l2_engine_rpc_url,
"ERC4337_BUNDLER_PRIVATE_KEY": bundler_key}

log_file_path = f"{config.logs_dir}/stackup_bundler.log"
log_file = open(log_file_path, "w")
print(f"Starting the stackup bundler. Logging to {log_file_path}.")
log_file = config.stackup_bundler_log_file
print(f"Starting the stackup bundler. Logging to {log_file}.")

def on_exit():
print(f"AA bundler exited. Check {log_file} for details.\n"
"You can re-run with `./rollop aa` in another terminal\n"
"(!! Make sure to specify the same config file and flags!)")

PROCESS_MGR.start(
"start bundler",
"stackup-bundler start --mode private",
env=env,
forward="fd",
stdout=log_file)
file=log_file,
on_exit=on_exit)


# --------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -180,17 +184,21 @@ def start_paymaster(config: Config):
env=env)

# start paymaster signer service
log_file_path = f"{config.logs_dir}/paymaster_signer.log"
log_file = open(log_file_path, "w")
print(f"Starting paymaster signer service. Logging to {log_file_path}")
log_file = config.paymaster_log_file
print(f"Starting paymaster signer service. Logging to {log_file}")

def on_exit():
print(f"AA paymaster exited. Check {log_file} for details.\n"
"You can re-run with `./rollop aa` in another terminal\n"
"(!! Make sure to specify the same config file and flags!)")

PROCESS_MGR.start(
"start paymaster signer service",
"pnpm run start",
cwd="paymaster",
env=env,
forward="fd",
stdout=log_file)
file=log_file,
on_exit=on_exit)


####################################################################################################
Expand All @@ -199,23 +207,16 @@ def clean(config: Config):
"""
Deletes the account abstraction deployment outputs and build logs.
"""
paths = [
lib.remove_paths(config, [
os.path.join(config.logs_dir, "build_aa_contracts.log"),
os.path.join(config.logs_dir, "stackup_bundler.log"),
os.path.join(config.logs_dir, "install_bundler.log"),
os.path.join(config.logs_dir, "build_paymaster.log"),
os.path.join(config.logs_dir, config.deploy_aa_log_file_name),
os.path.join(config.logs_dir, "paymaster_signer.log")
]

for path in paths:
if os.path.exists(path):
lib.debug(f"Removing {path}")
os.remove(path)

path = "account-abstraction/deployments/opstack"
lib.debug(f"Removing {path}")
shutil.rmtree(path, ignore_errors=True)
config.stackup_bundler_log_file,
config.paymaster_log_file,
# dirs
"account-abstraction/deployments/opstack",
])


####################################################################################################
26 changes: 8 additions & 18 deletions block_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
This module defines functions related to spinning a block explorer.
"""
import os
import shutil
import subprocess

import deps
from config import Config
Expand Down Expand Up @@ -52,9 +50,8 @@ def launch_blockscout(config: Config):
deps.check_docker()
setup_blockscout_repo()

log_file_name = f"{config.logs_dir}/launch_blockscout.log"
log_file = open(log_file_name, "w")
print(f"Launching the blockscout block explorer. Logging to {log_file_name}\n"
log_file = config.blockscout_log_file
print(f"Launching the blockscout block explorer. Logging to {log_file}\n"
"Explorer available at http://localhost:80 in a little bit.")

http_url = config.l2_engine_rpc_http_url.replace("127.0.0.1", "host.docker.internal")
Expand Down Expand Up @@ -109,7 +106,8 @@ def edit_docker_compose_config(dc_config: dict):
"spin up block explorer",
"docker compose -f geth.yml up",
cwd="blockscout/docker-compose",
forward="fd", stdout=log_file, stderr=subprocess.STDOUT, env=env)
file=log_file,
env=env)


####################################################################################################
Expand Down Expand Up @@ -151,22 +149,14 @@ def clean(config: Config):
"""
Deletes the block explorer databases, logs, and containers.
"""

dir_paths = [
lib.remove_paths(config, [
config.blockscout_log_file,
# dirs
"blockscout/docker-compose/services/blockscout-db-data",
"blockscout/docker-compose/services/logs",
"blockscout/docker-compose/services/redis-data",
"blockscout/docker-compose/services/stats-db-data",
]

for path in dir_paths:
lib.debug(f"Removing {path}")
shutil.rmtree(path, ignore_errors=True)

path = os.path.join(config.logs_dir, "launch_blockscout.log")
if os.path.exists(path):
lib.debug(f"Removing {path}")
os.remove(path)
])

lib.run("remove blockscout containers",
f"docker compose --project-name {_COMPOSE_PROJECT_NAME} rm --stop --force")
Expand Down
6 changes: 3 additions & 3 deletions config/account_abstraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ def __init__(self):
# ==============================================================================================

# Also needed to run the bundler and paymster:
# :py:attribute:`aa_deployer_key` in :py:class:`config.AccountAbstractionConfig`
# :py:attribute:`bundler_key` in :py:class:`config.AccountAbstractionConfig`
# :py:attribute:`paymaster_key` in :py:class:`config.AccountAbstractionConfig`
# :py:attr:`aa_deployer_key` in :py:class:`config.AccountAbstractionConfig`
# :py:attr:`bundler_key` in :py:class:`config.AccountAbstractionConfig`
# :py:attr:`paymaster_key` in :py:class:`config.AccountAbstractionConfig`

# ==============================================================================================
10 changes: 5 additions & 5 deletions config/accounts_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def __init__(self):

self.admin_key = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
"""
Private key corresponding to :py:attribute:`admin_account`, see its documentation for
Private key corresponding to :py:attr:`admin_account`, see its documentation for
more details.
By default, uses the 0th "test junk" account key.
Do not prefix the key with 0x.
Expand All @@ -74,14 +74,14 @@ def __init__(self):
self.batcher_mnemonic = "test test test test test test test test test test test junk"
"""
Mnemonic to use to derive the batcher key (Anvil "test junk" account mnemonic by default).
Ignored if :py:attribute:`batcher_key` is set.
Ignored if :py:attr:`batcher_key` is set.
"""

self.batcher_hd_path = "m/44'/60'/0'/0/2"
"""
HD derivation path to use to derive the batcher key.
Uses the 2nd (0-based!) "test junk" mnemonnic key by default.
Ignored if :py:attribute:`proposer_key` is set.
Ignored if :py:attr:`proposer_key` is set.
"""

# ------------------------------------------------------------------------------------------
Expand All @@ -102,14 +102,14 @@ def __init__(self):
self.proposer_mnemonic = "test test test test test test test test test test test junk"
"""
Mnemonic to use to derive the proposer key (Anvil "test junk" account mnemonic by default).
Ignored if :py:attribute:`proposer_key` is set.
Ignored if :py:attr:`proposer_key` is set.
"""

self.proposer_hd_path = "m/44'/60'/0'/0/1"
"""
HD derivation path to use to derive the proposer key.
Uses the 1th (0-based!) "test junk" mnemonnic key by default.
Ignored if :py:attribute:`proposer_key` is set.
Ignored if :py:attr:`proposer_key` is set.
"""

# ------------------------------------------------------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .l2_proposer import L2ProposerConfig
from .network import NetworkConfig
from .paths import PathsConfig
from .logs import LogsConfig


class Config(
Expand All @@ -24,7 +25,8 @@ class Config(
L2ProposerConfig,
L2BatcherConfig,
ExplorerConfig,
AccountAbstractionConfig
AccountAbstractionConfig,
LogsConfig,
):

# ==========================================================================================
Expand Down
14 changes: 7 additions & 7 deletions config/devnet_l1.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ def __init__(self):
"""
When using the "devnet" command, whether to run a local L1 chain (True by default).
If false, it means deploying on an existing L1 blockchain, specified by
:py:attribute:`l1_rpc`.
:py:attr:`l1_rpc`.

Note that you can/should stil set :py:attribute:`l1_rpc` when this is True, if you want to
Note that you can/should stil set :py:attr:`l1_rpc` when this is True, if you want to
deploy the the devnet L1 on another IP or port.
"""

# Any attribute defined in this section are only meaningful (used) if
# :py:attribute:`deploy_devnet_l1` is True!
# :py:attr:`deploy_devnet_l1` is True!

self.l1_contracts_in_genesis = True
"""
Expand Down Expand Up @@ -78,20 +78,20 @@ def __init__(self):
self.l1_metrics_listen_port = 7060
"""
Port to the L1 node metrics server should bind to (7060 by default).
Ignored if :py:attribute:`node_metrics` is False.
Ignored if :py:attr:`l1_metrics` is False.
"""

self.l1_metrics_listen_addr = "0.0.0.0"
"""
Address the L1 node metrics server should bind to ("0.0.0.0" by default).
Ignored if :py:attribute:`node_metrics` is False.
Ignored if :py:attr:`l1_metrics` is False.
"""

# ==============================================================================================

# See also:
# :py:attribute:`l1_chain_id` in :py:class:`config.network.NetworkConfig`
# :py:attribute:`l1_data_dir` in :py:class:`config.paths.PathConfig`
# :py:attr:`l1_chain_id` in :py:class:`config.network.NetworkConfig`
# :py:attr:`l1_data_dir` in :py:class:`config.paths.PathConfig`

# ==============================================================================================

Expand Down
4 changes: 2 additions & 2 deletions config/examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import os

import state
from config import Config
import libroll as lib


####################################################################################################
Expand Down Expand Up @@ -127,7 +127,7 @@ def use_production_config(config: Config):
config.l2_proposer_poll_interval = 12
config.l2_proposer_num_confirmations = 10
# Must be true if using the devnet L1 or any L1 that doesn't mark blocks as finalized!
config.l2_proposer_allow_non_finalized = lib.args.command == "devnet"
config.l2_proposer_allow_non_finalized = state.args.command == "devnet"

# === Batcher ===

Expand Down
2 changes: 1 addition & 1 deletion config/explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init__(self):

self.chain_short_name = "roll-op"
"""
Short version of :py:attribute:`chain_name`, used in the block explorer.
Short version of :py:attr:`chain_name`, used in the block explorer.
Defaults to "roll-op".
"""

Expand Down
4 changes: 2 additions & 2 deletions config/governance.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ def __init__(self):

self.governance_token_symbol = "STONK"
"""
If :py:attribute:`enable_governance` is True, the symbol of the governance token to deploy.
If :py:attr:`enable_governance` is True, the symbol of the governance token to deploy.
"""

self.governance_token_name = "Simple Token Op-chain Network Koin"
"""
If :py:attribute:`enable_governance` is True, the name of the governance token to deploy.
If :py:attr:`enable_governance` is True, the name of the governance token to deploy.
"""

# ==============================================================================================
10 changes: 5 additions & 5 deletions config/l2_batcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,20 @@ def __init__(self):
self.batcher_metrics_listen_port = 7301
"""
Port to the batcher metrics server should bind to (7301 by default).
Ignored if :py:attribute:`batcher_metrics` is False.
Ignored if :py:attr:`batcher_metrics` is False.
"""

self.batcher_metrics_listen_addr = "0.0.0.0"
"""
Address the batcher metrics server should bind to ("0.0.0.0" by default).
Ignored if :py:attribute:`batcher_metrics` is False.
Ignored if :py:attr:`batcher_metrics` is False.
"""

# ==============================================================================================

# Also needed to configure the L2 batcher:
# :py:attribute:`l1_rpc_url` in :py:class:`config.NetworkConfig`
# :py:attribute:`l2_engine_rpc_url` in :py:class:`config.NetworkConfig`
# :py:attribute:`l2_node_rpc_url` in :py:class:`config.NetworkConfig`
# :py:attr:`l1_rpc_url` in :py:class:`config.NetworkConfig`
# :py:attr:`l2_engine_rpc_url` in :py:class:`config.NetworkConfig`
# :py:attr:`l2_node_rpc_url` in :py:class:`config.NetworkConfig`

# ==============================================================================================
Loading