Compare commits
86 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
dc9b831534 | ||
![]() |
49bb26a063 | ||
![]() |
9958bdd205 | ||
![]() |
0507fbb9d1 | ||
![]() |
808baec53c | ||
![]() |
284cd4f52a | ||
![]() |
359afdcbe0 | ||
![]() |
e927c7a8ec | ||
![]() |
b6417cba97 | ||
![]() |
ae1c71fec0 | ||
![]() |
0fdf36661e | ||
![]() |
163a163b96 | ||
![]() |
7c99edddbd | ||
![]() |
9435841987 | ||
![]() |
9fdedc5dea | ||
![]() |
ccc3378774 | ||
![]() |
73c333e6e6 | ||
![]() |
519777a922 | ||
![]() |
4cc5a8450d | ||
![]() |
83066f5315 | ||
![]() |
1b8813314e | ||
![]() |
92107d4018 | ||
![]() |
1e7a74d6ef | ||
![]() |
c2ce54139c | ||
![]() |
5c5d06446a | ||
![]() |
72ddaffc4f | ||
![]() |
3e88913042 | ||
![]() |
dd78dccab2 | ||
![]() |
6f61db996c | ||
![]() |
735dc7b33e | ||
![]() |
7e779ab41b | ||
![]() |
709729df14 | ||
![]() |
8f9333a273 | ||
![]() |
15f55b870d | ||
![]() |
3bf6b70526 | ||
![]() |
e35eb46873 | ||
![]() |
81ee234540 | ||
![]() |
dec96d85e1 | ||
![]() |
9d0dbad846 | ||
![]() |
f3d0412525 | ||
![]() |
e5b0bb6012 | ||
![]() |
d6e94ce52e | ||
![]() |
a272396ef9 | ||
![]() |
b08b878e9a | ||
![]() |
38fc3295c2 | ||
![]() |
7b0de0cb7f | ||
![]() |
bd9bf431e7 | ||
![]() |
8f413a9aae | ||
![]() |
fa27ed6405 | ||
![]() |
2dd8f912b2 | ||
![]() |
e5ce8cdc01 | ||
![]() |
cf4041f47b | ||
8d5d443792 | |||
edcd01d4df | |||
a74a9664da | |||
91c79ab3de | |||
0f50faee8f | |||
e8fb624e19 | |||
951bdb325e | |||
7f2332e228 | |||
3e9606c184 | |||
26ef269e91 | |||
f4890f90b9 | |||
42bd16d5ee | |||
d5831486eb | |||
adfef954d1 | |||
7b8b636d37 | |||
1a4d2ff726 | |||
0311fcf3f0 | |||
4fa87c349c | |||
892c4c7ad7 | |||
56b06dee4f | |||
0d92d2a838 | |||
![]() |
881145c1cb | ||
![]() |
0eccff4144 | ||
![]() |
d73bb9a6c7 | ||
![]() |
f66425596a | ||
![]() |
f06d06f581 | ||
![]() |
1b6da9c607 | ||
![]() |
a22a9a02a6 | ||
![]() |
31ac793273 | ||
![]() |
30ad2ee1ab | ||
![]() |
eb4a1d4350 | ||
![]() |
77f2a7ef3d | ||
![]() |
f3ad99769f | ||
![]() |
baf2ee794b |
43 changed files with 2748 additions and 1012 deletions
552
.github/workflows/ncc_workflow.yml
vendored
Normal file
552
.github/workflows/ncc_workflow.yml
vendored
Normal file
|
@ -0,0 +1,552 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt update -yqq
|
||||||
|
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
||||||
|
|
||||||
|
- name: Install phive
|
||||||
|
run: |
|
||||||
|
wget -O phive.phar https://phar.io/releases/phive.phar
|
||||||
|
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
|
||||||
|
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
|
||||||
|
gpg --verify phive.phar.asc phive.phar
|
||||||
|
chmod +x phive.phar
|
||||||
|
mv phive.phar /usr/local/bin/phive
|
||||||
|
|
||||||
|
- name: Install phab
|
||||||
|
run: |
|
||||||
|
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
||||||
|
|
||||||
|
- name: Install latest version of NCC
|
||||||
|
run: |
|
||||||
|
git clone https://git.n64.cc/nosial/ncc.git
|
||||||
|
cd ncc
|
||||||
|
make redist
|
||||||
|
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
|
||||||
|
if [ -z "$NCC_DIR" ]; then
|
||||||
|
echo "NCC build directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
php "$NCC_DIR/INSTALL" --auto
|
||||||
|
cd .. && rm -rf ncc
|
||||||
|
|
||||||
|
- name: Build project
|
||||||
|
run: |
|
||||||
|
ncc build --config release --build-source --log-level debug
|
||||||
|
|
||||||
|
- name: Upload build artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release
|
||||||
|
path: build/release/net.nosial.loglib.ncc
|
||||||
|
release-compressed:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt update -yqq
|
||||||
|
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
||||||
|
|
||||||
|
- name: Install phive
|
||||||
|
run: |
|
||||||
|
wget -O phive.phar https://phar.io/releases/phive.phar
|
||||||
|
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
|
||||||
|
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
|
||||||
|
gpg --verify phive.phar.asc phive.phar
|
||||||
|
chmod +x phive.phar
|
||||||
|
mv phive.phar /usr/local/bin/phive
|
||||||
|
|
||||||
|
- name: Install phab
|
||||||
|
run: |
|
||||||
|
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
||||||
|
|
||||||
|
- name: Install latest version of NCC
|
||||||
|
run: |
|
||||||
|
git clone https://git.n64.cc/nosial/ncc.git
|
||||||
|
cd ncc
|
||||||
|
make redist
|
||||||
|
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
|
||||||
|
if [ -z "$NCC_DIR" ]; then
|
||||||
|
echo "NCC build directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
php "$NCC_DIR/INSTALL" --auto
|
||||||
|
cd .. && rm -rf ncc
|
||||||
|
|
||||||
|
- name: Build project
|
||||||
|
run: |
|
||||||
|
ncc build --config release-compressed --build-source --log-level debug
|
||||||
|
|
||||||
|
- name: Upload build artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-compressed
|
||||||
|
path: build/release/net.nosial.loglib.gz.ncc
|
||||||
|
debug-compressed:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt update -yqq
|
||||||
|
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
||||||
|
|
||||||
|
- name: Install phive
|
||||||
|
run: |
|
||||||
|
wget -O phive.phar https://phar.io/releases/phive.phar
|
||||||
|
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
|
||||||
|
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
|
||||||
|
gpg --verify phive.phar.asc phive.phar
|
||||||
|
chmod +x phive.phar
|
||||||
|
mv phive.phar /usr/local/bin/phive
|
||||||
|
|
||||||
|
- name: Install phab
|
||||||
|
run: |
|
||||||
|
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
||||||
|
|
||||||
|
- name: Install latest version of NCC
|
||||||
|
run: |
|
||||||
|
git clone https://git.n64.cc/nosial/ncc.git
|
||||||
|
cd ncc
|
||||||
|
make redist
|
||||||
|
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
|
||||||
|
if [ -z "$NCC_DIR" ]; then
|
||||||
|
echo "NCC build directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
php "$NCC_DIR/INSTALL" --auto
|
||||||
|
cd .. && rm -rf ncc
|
||||||
|
|
||||||
|
- name: Build project
|
||||||
|
run: |
|
||||||
|
ncc build --config debug-compressed --build-source --log-level debug
|
||||||
|
|
||||||
|
- name: Upload build artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: debug-compressed
|
||||||
|
path: build/debug/net.nosial.loglib.gz.ncc
|
||||||
|
release-executable:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt update -yqq
|
||||||
|
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
||||||
|
|
||||||
|
- name: Install phive
|
||||||
|
run: |
|
||||||
|
wget -O phive.phar https://phar.io/releases/phive.phar
|
||||||
|
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
|
||||||
|
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
|
||||||
|
gpg --verify phive.phar.asc phive.phar
|
||||||
|
chmod +x phive.phar
|
||||||
|
mv phive.phar /usr/local/bin/phive
|
||||||
|
|
||||||
|
- name: Install phab
|
||||||
|
run: |
|
||||||
|
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
||||||
|
|
||||||
|
- name: Install latest version of NCC
|
||||||
|
run: |
|
||||||
|
git clone https://git.n64.cc/nosial/ncc.git
|
||||||
|
cd ncc
|
||||||
|
make redist
|
||||||
|
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
|
||||||
|
if [ -z "$NCC_DIR" ]; then
|
||||||
|
echo "NCC build directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
php "$NCC_DIR/INSTALL" --auto
|
||||||
|
cd .. && rm -rf ncc
|
||||||
|
|
||||||
|
- name: Build project
|
||||||
|
run: |
|
||||||
|
ncc build --config release-executable --build-source --log-level debug
|
||||||
|
|
||||||
|
- name: Upload build artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-executable
|
||||||
|
path: build/release/release_executable_gz
|
||||||
|
release-compressed-executable:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt update -yqq
|
||||||
|
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
||||||
|
|
||||||
|
- name: Install phive
|
||||||
|
run: |
|
||||||
|
wget -O phive.phar https://phar.io/releases/phive.phar
|
||||||
|
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
|
||||||
|
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
|
||||||
|
gpg --verify phive.phar.asc phive.phar
|
||||||
|
chmod +x phive.phar
|
||||||
|
mv phive.phar /usr/local/bin/phive
|
||||||
|
|
||||||
|
- name: Install phab
|
||||||
|
run: |
|
||||||
|
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
||||||
|
|
||||||
|
- name: Install latest version of NCC
|
||||||
|
run: |
|
||||||
|
git clone https://git.n64.cc/nosial/ncc.git
|
||||||
|
cd ncc
|
||||||
|
make redist
|
||||||
|
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
|
||||||
|
if [ -z "$NCC_DIR" ]; then
|
||||||
|
echo "NCC build directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
php "$NCC_DIR/INSTALL" --auto
|
||||||
|
cd .. && rm -rf ncc
|
||||||
|
|
||||||
|
- name: Build project
|
||||||
|
run: |
|
||||||
|
ncc build --config release-compressed-executable --build-source --log-level debug
|
||||||
|
|
||||||
|
- name: Upload build artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-compressed-executable
|
||||||
|
path: build/release/release_compressed_executable
|
||||||
|
debug-compressed-executable:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt update -yqq
|
||||||
|
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
||||||
|
|
||||||
|
- name: Install phive
|
||||||
|
run: |
|
||||||
|
wget -O phive.phar https://phar.io/releases/phive.phar
|
||||||
|
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
|
||||||
|
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
|
||||||
|
gpg --verify phive.phar.asc phive.phar
|
||||||
|
chmod +x phive.phar
|
||||||
|
mv phive.phar /usr/local/bin/phive
|
||||||
|
|
||||||
|
- name: Install phab
|
||||||
|
run: |
|
||||||
|
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
||||||
|
|
||||||
|
- name: Install latest version of NCC
|
||||||
|
run: |
|
||||||
|
git clone https://git.n64.cc/nosial/ncc.git
|
||||||
|
cd ncc
|
||||||
|
make redist
|
||||||
|
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
|
||||||
|
if [ -z "$NCC_DIR" ]; then
|
||||||
|
echo "NCC build directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
php "$NCC_DIR/INSTALL" --auto
|
||||||
|
cd .. && rm -rf ncc
|
||||||
|
|
||||||
|
- name: Build project
|
||||||
|
run: |
|
||||||
|
ncc build --config debug-compressed-executable --build-source --log-level debug
|
||||||
|
|
||||||
|
- name: Upload build artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: debug-compressed-executable
|
||||||
|
path: build/debug/debug_compressed_executable
|
||||||
|
|
||||||
|
|
||||||
|
# Checking for phpunit.xml
|
||||||
|
check-phpunit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
phpunit-exists: ${{ steps.check.outputs.phpunit-exists }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Check for phpunit.xml
|
||||||
|
id: check
|
||||||
|
run: |
|
||||||
|
if [ -f phpunit.xml ]; then
|
||||||
|
echo "phpunit-exists=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "phpunit-exists=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
# Checking for phpdoc.dist.xml
|
||||||
|
check-phpdoc:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
phpdoc-exists: ${{ steps.check.outputs.phpdoc-exists }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Check for phpdoc.dist.xml
|
||||||
|
id: check
|
||||||
|
run: |
|
||||||
|
if [ -f phpdoc.dist.xml ]; then
|
||||||
|
echo "phpdoc-exists=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "phpdoc-exists=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
generate-phpdoc:
|
||||||
|
needs: [release, check-phpdoc]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
if: needs.check-phpdoc.outputs.phpdoc-exists == 'true'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt update -yqq
|
||||||
|
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
||||||
|
|
||||||
|
- name: Download PHPDocumentor
|
||||||
|
run: |
|
||||||
|
wget https://phpdoc.org/phpDocumentor.phar
|
||||||
|
chmod +x phpDocumentor.phar
|
||||||
|
|
||||||
|
- name: Generate PHPDoc
|
||||||
|
run: |
|
||||||
|
php phpDocumentor.phar -d src -t docs
|
||||||
|
|
||||||
|
- name: Archive PHPDoc
|
||||||
|
run: |
|
||||||
|
zip -r docs.zip docs
|
||||||
|
|
||||||
|
- name: Upload PHPDoc
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: documentation
|
||||||
|
path: docs.zip
|
||||||
|
|
||||||
|
test:
|
||||||
|
needs: [release, release-compressed, debug-compressed, release-executable, release-compressed-executable, debug-compressed-executable, check-phpunit]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
if: needs.check-phpunit.outputs.phpunit-exists == 'true'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release
|
||||||
|
path: release
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt update -yqq
|
||||||
|
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
||||||
|
curl -sSLf -o /usr/local/bin/install-php-extensions https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions
|
||||||
|
chmod +x /usr/local/bin/install-php-extensions
|
||||||
|
install-php-extensions zip
|
||||||
|
|
||||||
|
- name: Install phive
|
||||||
|
run: |
|
||||||
|
wget -O phive.phar https://phar.io/releases/phive.phar
|
||||||
|
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
|
||||||
|
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
|
||||||
|
gpg --verify phive.phar.asc phive.phar
|
||||||
|
chmod +x phive.phar
|
||||||
|
mv phive.phar /usr/local/bin/phive
|
||||||
|
|
||||||
|
- name: Install phab
|
||||||
|
run: |
|
||||||
|
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
||||||
|
|
||||||
|
- name: Install latest version of NCC
|
||||||
|
run: |
|
||||||
|
git clone https://git.n64.cc/nosial/ncc.git
|
||||||
|
cd ncc
|
||||||
|
make redist
|
||||||
|
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
|
||||||
|
if [ -z "$NCC_DIR" ]; then
|
||||||
|
echo "NCC build directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
php "$NCC_DIR/INSTALL" --auto
|
||||||
|
cd .. && rm -rf ncc
|
||||||
|
|
||||||
|
- name: Install NCC packages
|
||||||
|
run: |
|
||||||
|
ncc package install --package="release/net.nosial.loglib.ncc" --build-source --reinstall -y --log-level debug
|
||||||
|
|
||||||
|
- name: Run PHPUnit tests
|
||||||
|
run: |
|
||||||
|
wget https://phar.phpunit.de/phpunit-11.3.phar
|
||||||
|
php phpunit-11.3.phar --configuration phpunit.xml --log-junit reports/junit.xml --log-teamcity reports/teamcity --testdox-html reports/testdox.html --testdox-text reports/testdox.txt
|
||||||
|
|
||||||
|
- name: Upload test reports
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: reports
|
||||||
|
path: reports
|
||||||
|
|
||||||
|
|
||||||
|
release-documentation:
|
||||||
|
needs: generate-phpdoc
|
||||||
|
permissions: write-all
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download documentation artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: documentation
|
||||||
|
path: documentation
|
||||||
|
|
||||||
|
- name: Upload documentation artifact
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
documentation/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
|
release-artifacts:
|
||||||
|
needs: [release, release-compressed, debug-compressed, release-executable, release-compressed-executable, debug-compressed-executable]
|
||||||
|
permissions: write-all
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: php:8.3
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download release artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release
|
||||||
|
path: release
|
||||||
|
- name: Upload release artifact to release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
release/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Download release-compressed artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-compressed
|
||||||
|
path: release-compressed
|
||||||
|
- name: Upload release-compressed artifact to release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
release-compressed/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Download debug-compressed artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: debug-compressed
|
||||||
|
path: debug-compressed
|
||||||
|
- name: Upload debug-compressed artifact to release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
debug-compressed/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Download release-executable artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-executable
|
||||||
|
path: release-executable
|
||||||
|
- name: Upload release-executable artifact to release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
release-executable/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Download release-compressed-executable artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-compressed-executable
|
||||||
|
path: release-compressed-executable
|
||||||
|
- name: Upload release-compressed-executable artifact to release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
release-compressed-executable/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Download debug-compressed-executable artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: debug-compressed-executable
|
||||||
|
path: debug-compressed-executable
|
||||||
|
- name: Upload debug-compressed-executable artifact to release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
debug-compressed-executable/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1,3 @@
|
||||||
build/
|
build/
|
||||||
|
/.idea/phpunit.xml
|
||||||
|
/.phpunit.result.cache
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
image: php:8.1
|
image: repo.n64.cc:443/nosial/ncc:latest
|
||||||
|
|
||||||
before_script:
|
stages:
|
||||||
# Install some stuff that the image doesn't come with
|
- build
|
||||||
- apt update -yqq
|
- publish
|
||||||
- apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
|
|
||||||
|
|
||||||
# Install phive
|
variables:
|
||||||
- wget -O phive.phar https://phar.io/releases/phive.phar
|
PACKAGE_NAME: $CI_COMMIT_REF_NAME
|
||||||
- wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
|
|
||||||
- gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
|
|
||||||
- gpg --verify phive.phar.asc phive.phar
|
|
||||||
- chmod +x phive.phar
|
|
||||||
- mv phive.phar /usr/local/bin/phive
|
|
||||||
|
|
||||||
# Install phab
|
|
||||||
- phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
|
|
||||||
|
|
||||||
# Install the latest version of ncc (Nosial Code Compiler)
|
|
||||||
- git clone https://git.n64.cc/nosial/ncc.git
|
|
||||||
- cd ncc
|
|
||||||
- make redist
|
|
||||||
- php build/src/INSTALL --auto --install-composer
|
|
||||||
- cd .. && rm -rf ncc
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
stage: build
|
||||||
script:
|
script:
|
||||||
- ncc build --config release --log-level debug
|
- ncc build --config release --log-level debug -o "build/release/net.nosial.loglib.ncc"
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- build/
|
- "build/release/net.nosial.loglib.ncc"
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_BRANCH
|
|
||||||
|
|
||||||
release:
|
build_static:
|
||||||
stage: deploy
|
stage: build
|
||||||
script:
|
script:
|
||||||
- ncc build --config release --log-level debug
|
- ncc project install
|
||||||
|
- ncc build --config release_static --log-level debug -o "build/release/net.nosial.loglib_static.ncc"
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- build/
|
- "build/release/net.nosial.loglib_static.ncc"
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_TAG
|
publish:
|
||||||
|
stage: publish
|
||||||
|
before_script:
|
||||||
|
- 'if [ "$CI_COMMIT_REF_NAME" == "master" ]; then PACKAGE_NAME="latest"; fi'
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/release/net.nosial.loglib.ncc \
|
||||||
|
"https://$CI_SERVER_HOST/api/v4/projects/$CI_PROJECT_ID/packages/generic/${PACKAGE_NAME}/${CI_COMMIT_SHA}/net.nosial.loglib.ncc"
|
||||||
|
|
||||||
|
publish_static:
|
||||||
|
stage: publish
|
||||||
|
before_script:
|
||||||
|
- 'if [ "$CI_COMMIT_REF_NAME" == "master" ]; then PACKAGE_NAME="latest"; fi'
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/release/net.nosial.loglib_static.ncc \
|
||||||
|
"https://$CI_SERVER_HOST/api/v4/projects/$CI_PROJECT_ID/packages/generic/${PACKAGE_NAME}/${CI_COMMIT_SHA}/net.nosial.loglib_static.ncc"
|
4
.idea/inspectionProfiles/Project_Default.xml
generated
4
.idea/inspectionProfiles/Project_Default.xml
generated
|
@ -19,8 +19,12 @@
|
||||||
<option value="X-Args-3" />
|
<option value="X-Args-3" />
|
||||||
<option value="X-Args-4" />
|
<option value="X-Args-4" />
|
||||||
<option value="X-Args-5" />
|
<option value="X-Args-5" />
|
||||||
|
<option value="X-Temperature" />
|
||||||
|
<option value="X-Model" />
|
||||||
|
<option value="X-OPENAI-API-KEY" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PhpDocRedundantThrowsInspection" enabled="true" level="INFORMATION" enabled_by_default="true" />
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
20
.idea/php-inspections-ea-ultimate.xml
generated
Normal file
20
.idea/php-inspections-ea-ultimate.xml
generated
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="EAUltimateProjectSettings">
|
||||||
|
<categories>
|
||||||
|
<STRICTNESS_CATEGORY_SECURITY enabled="yes" />
|
||||||
|
<STRICTNESS_CATEGORY_PROBABLE_BUGS enabled="yes" />
|
||||||
|
<STRICTNESS_CATEGORY_PERFORMANCE enabled="yes" />
|
||||||
|
<STRICTNESS_CATEGORY_ARCHITECTURE enabled="yes" />
|
||||||
|
<STRICTNESS_CATEGORY_CONTROL_FLOW enabled="yes" />
|
||||||
|
<STRICTNESS_CATEGORY_LANGUAGE_LEVEL_MIGRATION enabled="yes" />
|
||||||
|
<STRICTNESS_CATEGORY_CODE_STYLE enabled="yes" />
|
||||||
|
<STRICTNESS_CATEGORY_UNUSED enabled="yes" />
|
||||||
|
<STRICTNESS_CATEGORY_PHPUNIT enabled="yes" />
|
||||||
|
</categories>
|
||||||
|
<settings>
|
||||||
|
<ANALYZE_ONLY_MODIFIED_FILES value="no" />
|
||||||
|
<PREFER_YODA_COMPARISON_STYLE value="no" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
|
</project>
|
2
.idea/php-test-framework.xml
generated
2
.idea/php-test-framework.xml
generated
|
@ -5,7 +5,7 @@
|
||||||
<tool tool_name="PHPUnit">
|
<tool tool_name="PHPUnit">
|
||||||
<cache>
|
<cache>
|
||||||
<versions>
|
<versions>
|
||||||
<info id="Local" version="PHPUnit version can't be detected. Default PHP interpreter is not local" />
|
<info id="Local/home/netkas/phar/phpunit.phar" version="11.3.5" />
|
||||||
</versions>
|
</versions>
|
||||||
</cache>
|
</cache>
|
||||||
</tool>
|
</tool>
|
||||||
|
|
5
.idea/php.xml
generated
5
.idea/php.xml
generated
|
@ -11,9 +11,8 @@
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpIncludePathManager">
|
<component name="PhpIncludePathManager">
|
||||||
<include_path>
|
<include_path>
|
||||||
|
<path value="/var/ncc/packages/net.nosial.optslib=1.1.2" />
|
||||||
<path value="/usr/share/php" />
|
<path value="/usr/share/php" />
|
||||||
<path value="/etc/ncc" />
|
|
||||||
<path value="/var/ncc/packages/net.nosial.optslib=1.0.0" />
|
|
||||||
</include_path>
|
</include_path>
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.2" />
|
<component name="PhpProjectSharedConfiguration" php_language_level="8.2" />
|
||||||
|
@ -125,7 +124,7 @@
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpUnit">
|
<component name="PhpUnit">
|
||||||
<phpunit_settings>
|
<phpunit_settings>
|
||||||
<PhpUnitSettings load_method="PHPUNIT_PHAR" custom_loader_path="$USER_HOME$/phpunit-9.5.phar" phpunit_phar_path="$USER_HOME$/phpunit-9.5.phar" />
|
<PhpUnitSettings load_method="PHPUNIT_PHAR" custom_loader_path="$USER_HOME$/phpunit-9.5.phar" phpunit_phar_path="$USER_HOME$/phar/phpunit.phar" />
|
||||||
</phpunit_settings>
|
</phpunit_settings>
|
||||||
</component>
|
</component>
|
||||||
<component name="PsalmOptionsConfiguration">
|
<component name="PsalmOptionsConfiguration">
|
||||||
|
|
10
.idea/runConfigurations/Build.xml
generated
Normal file
10
.idea/runConfigurations/Build.xml
generated
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Build" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile">
|
||||||
|
<makefile filename="$PROJECT_DIR$/Makefile" target="build" workingDirectory="" arguments="">
|
||||||
|
<envs />
|
||||||
|
</makefile>
|
||||||
|
<method v="2">
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Clean" run_configuration_type="MAKEFILE_TARGET_RUN_CONFIGURATION" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
8
.idea/runConfigurations/Clean.xml
generated
Normal file
8
.idea/runConfigurations/Clean.xml
generated
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Clean" type="MAKEFILE_TARGET_RUN_CONFIGURATION" factoryName="Makefile">
|
||||||
|
<makefile filename="$PROJECT_DIR$/Makefile" target="clean" workingDirectory="" arguments="">
|
||||||
|
<envs />
|
||||||
|
</makefile>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
102
CHANGELOG.md
102
CHANGELOG.md
|
@ -5,10 +5,110 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2.0.7] - 2025-01-13
|
||||||
|
|
||||||
|
This update introduces a minor fix
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed FileLogging issue by setting the write permission to 0666 for the log file if it doesn't exist.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [2.0.6] - 2025-01-10
|
||||||
|
|
||||||
|
This update introduces a minor change
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- File logging is disabled for web environments due to instability in file locking, until a better solution is found.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.0.5] - 2025-01-09
|
||||||
|
|
||||||
|
This update introduces a minor bug fix
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Refactor file locking to return status and handle failure.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.0.4] - 2024-12-04
|
||||||
|
|
||||||
|
This update introduces a minor bug fix
|
||||||
|
|
||||||
|
|
||||||
|
## [2.0.3] - 2024-11-05
|
||||||
|
|
||||||
|
This update introduces a minor bug fix
|
||||||
|
|
||||||
|
|
||||||
|
## [2.0.2] - 2024-10-30
|
||||||
|
|
||||||
|
This update introduces minor improvements
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Refactored exception handling in FileLogging where it will always attempt to print the exception no matter
|
||||||
|
the log level for as long as the log level isn't silent
|
||||||
|
- Implement enhanced error and exception handling
|
||||||
|
|
||||||
|
|
||||||
|
## [2.0.1] - 2024-10-29
|
||||||
|
|
||||||
|
This update introduces a critical bug fix where Console logging was enabled in web environments
|
||||||
|
|
||||||
|
|
||||||
|
## [2.0.0] - 2024-10-29
|
||||||
|
|
||||||
|
This update introduces some additional features & bug fixes
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Added File Logging support
|
||||||
|
- Added LogHandlerInterface & refactored Application settings to allow for use of custom logging handlers
|
||||||
|
- Added Logging type for logging type handling
|
||||||
|
- Added a Logger object for creating a logging instance for Applications
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- All abstract classes are now enum classes
|
||||||
|
- Refactored Console Logging to use the new LogHandlerInterface
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Set default log level to 'info' in Utilities. instead of using `null` due to deprecation error
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Removed Unused BRIGHT_COLORS constant from ConsoleColors
|
||||||
|
- Removed Unused Options object
|
||||||
|
- Removed Unused RuntimeOptions object
|
||||||
|
- Removed unused Console class
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.1] - 2024-10-13
|
||||||
|
|
||||||
|
Update build system
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.1.0] - 2023-10-12
|
||||||
|
|
||||||
|
Updated loglib to work with ncc 2.+.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Various code improvements and optimizations
|
||||||
|
- Removed unused code
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.2] - 2023-07-06
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Changed the Timestamp format to display micro time instead of a date format
|
||||||
|
* Timestamp Formats can now display in red or yellow to indicate performance impacts between log entries
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Fixed mistake in `\LogLib\Classes > Console > outException()` where the function attempts to print out a previous
|
||||||
|
exception by calling `getPrevious()` as an array instead of a function call.
|
||||||
|
|
||||||
|
|
||||||
## [1.0.1] - 2023-02-10
|
## [1.0.1] - 2023-02-10
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
* Added PSR compatible LoggerInterface implementation (\LogLib\Psr)
|
* Added PSR compatible LoggerInterface implementation (\LogLib\Psr)
|
||||||
* Added new option `--log-level` to set the log level (Can also be applied via the environment variable `LOG_LEVEL`)
|
* Added new option `--log-level` to set the log level (Can also be applied via the environment variable `LOG_LEVEL`)
|
||||||
|
|
||||||
|
|
24
LICENSE
24
LICENSE
|
@ -1,18 +1,14 @@
|
||||||
Copyright 2022-2023 Nosial All Rights Reserved.
|
Copyright 2022-2023 Nosial All Rights Reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
a copy of this software and associated documentation files (the "Software"),
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
to deal in the Software without restriction, including without limitation
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
and/or sell copies of the Software, and to permit persons to whom the Software
|
|
||||||
is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
||||||
copies or substantial portions of the Software.
|
the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||||
PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
||||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
35
Makefile
35
Makefile
|
@ -1,8 +1,33 @@
|
||||||
|
# Variables
|
||||||
|
DEFAULT_CONFIGURATION ?= release
|
||||||
|
LOG_LEVEL = debug
|
||||||
|
|
||||||
|
# Default Target
|
||||||
|
all: release release-compressed debug-compressed release-executable release-compressed-executable debug-compressed-executable
|
||||||
|
|
||||||
|
# Build Steps
|
||||||
release:
|
release:
|
||||||
ncc build --config="release"
|
ncc build --config=release --log-level $(LOG_LEVEL)
|
||||||
|
release-compressed:
|
||||||
|
ncc build --config=release-compressed --log-level $(LOG_LEVEL)
|
||||||
|
debug-compressed:
|
||||||
|
ncc build --config=debug-compressed --log-level $(LOG_LEVEL)
|
||||||
|
release-executable:
|
||||||
|
ncc build --config=release-executable --log-level $(LOG_LEVEL)
|
||||||
|
release-compressed-executable:
|
||||||
|
ncc build --config=release-compressed-executable --log-level $(LOG_LEVEL)
|
||||||
|
debug-compressed-executable:
|
||||||
|
ncc build --config=debug-compressed-executable --log-level $(LOG_LEVEL)
|
||||||
|
|
||||||
install:
|
|
||||||
ncc package install --package="build/release/net.nosial.loglib.ncc" --skip-dependencies --reinstall -y
|
|
||||||
|
|
||||||
uninstall:
|
install: release
|
||||||
ncc package uninstall -y --package="net.nosial.loglib"
|
ncc package install --package=build/release/net.nosial.loglib.ncc --skip-dependencies --build-source --reinstall -y --log-level $(LOG_LEVEL)
|
||||||
|
|
||||||
|
test: release
|
||||||
|
[ -f phpunit.xml ] || { echo "phpunit.xml not found"; exit 1; }
|
||||||
|
phpunit
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf build
|
||||||
|
|
||||||
|
.PHONY: all install test clean release release-compressed debug-compressed release-executable release-compressed-executable debug-compressed-executable
|
43
README.md
43
README.md
|
@ -1,7 +1,6 @@
|
||||||
# LogLib
|
# LogLib
|
||||||
|
|
||||||
A logging library for PHP/ncc, this was quickly thrown together
|
A logging library for PHP/ncc, this was quickly thrown together to provide a simple logging interface and to test out
|
||||||
to provide a simple logging interface and to test out
|
|
||||||
NCC's capabilities for PHP.
|
NCC's capabilities for PHP.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
@ -25,20 +24,24 @@ The library can be installed using ncc:
|
||||||
ncc install -p "nosial/libs.log=latest@n64"
|
ncc install -p "nosial/libs.log=latest@n64"
|
||||||
```
|
```
|
||||||
|
|
||||||
or by adding the following to your project.json file under
|
A static version of the library can be installed using ncc, the `--skip-dependencies` flag is option but prevents
|
||||||
the `build.dependencies` section:
|
additional dependencies from being installed.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ncc install -p "nosial/libs.log=latest@n64" --static --skip-dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
or by adding the following to your project.json file under the `build.dependencies` section:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "net.nosial.loglib",
|
"name": "net.nosial.loglib",
|
||||||
"version": "latest",
|
"version": "latest",
|
||||||
"source_type": "remote",
|
|
||||||
"source": "nosial/libs.log=latest@n64"
|
"source": "nosial/libs.log=latest@n64"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you don't have the n64 source configured you can add it
|
If you don't have the n64 source configured you can add it by running the following command:
|
||||||
by running the following command:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ncc source add --name n64 --type gitlab --host git.n64.cc
|
ncc source add --name n64 --type gitlab --host git.n64.cc
|
||||||
|
@ -61,8 +64,7 @@ make release
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
The usage of this library is very simple, there are
|
The usage of this library is very simple, there are multiple error levels that can be used to log messages
|
||||||
multiple error levels that can be used to log messages
|
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
|
@ -70,19 +72,17 @@ multiple error levels that can be used to log messages
|
||||||
require 'ncc';
|
require 'ncc';
|
||||||
import('net.nosial.loglib');
|
import('net.nosial.loglib');
|
||||||
|
|
||||||
\LogLib\Log::debug('This is a debug message');
|
\LogLib\Log::debug('com.example.lib', 'This is a debug message');
|
||||||
\LogLib\Log::verbose('This is a verbose message');
|
\LogLib\Log::verbose('com.example.lib', 'This is a verbose message');
|
||||||
\LogLib\Log::info('This is an info message');
|
\LogLib\Log::info('com.example.lib', 'This is an info message');
|
||||||
\LogLib\Log::warning('This is a warning message');
|
\LogLib\Log::warning('com.example.lib', 'This is a warning message');
|
||||||
\LogLib\Log::error('This is an error message');
|
\LogLib\Log::error('com.example.lib', 'This is an error message');
|
||||||
\LogLib\Log::fatal('This is a fatal message');
|
\LogLib\Log::fatal('com.example.lib', 'This is a fatal message');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To display the log messages, you can run your program
|
To display the log messages, you can run your program with the `--log-level` argument, this will display all messages
|
||||||
with the `--log-level` argument, this will display all
|
with a level equal to or higher than the one specified.
|
||||||
messages with a level equal to or higher than the one
|
|
||||||
specified.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
myprogram --log-level info
|
myprogram --log-level info
|
||||||
|
@ -100,9 +100,8 @@ The log level can be set to one of the following:
|
||||||
|
|
||||||
The default log level is `info`.
|
The default log level is `info`.
|
||||||
|
|
||||||
> Note: Log messages are only displayed if the program
|
> Note: Log messages are only displayed if the program is run from the command line, if you are running the program
|
||||||
is run from the command line, if you are running the
|
> from a web server, the log messages will be shown
|
||||||
program from a web server, the log messages will be shown
|
|
||||||
|
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
3
bootstrap.php
Normal file
3
bootstrap.php
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<?php
|
||||||
|
require 'ncc';
|
||||||
|
import('net.nosial.loglib');
|
15
phpdoc.dist.xml
Normal file
15
phpdoc.dist.xml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<phpdocumentor configVersion="3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://www.phpdoc.org" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/phpDocumentor/phpDocumentor/master/data/xsd/phpdoc.xsd">
|
||||||
|
<paths>
|
||||||
|
<output>build/docs</output>
|
||||||
|
<cache>build/cache</cache>
|
||||||
|
</paths>
|
||||||
|
<version number="latest">
|
||||||
|
<api>
|
||||||
|
<source dsn=".">
|
||||||
|
<path>src/LogLib</path>
|
||||||
|
</source>
|
||||||
|
<default-package-name>LogLib</default-package-name>
|
||||||
|
</api>
|
||||||
|
</version>
|
||||||
|
</phpdocumentor>
|
11
phpunit.xml
Normal file
11
phpunit.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<phpunit bootstrap="bootstrap.php">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="LogLib Test Suite">
|
||||||
|
<directory>tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<php>
|
||||||
|
<ini name="error_reporting" value="-1"/>
|
||||||
|
<server name="KERNEL_DIR" value="app/"/>
|
||||||
|
</php>
|
||||||
|
</phpunit>
|
52
project.json
52
project.json
|
@ -13,15 +13,14 @@
|
||||||
"host": "git.n64.cc",
|
"host": "git.n64.cc",
|
||||||
"ssl": true
|
"ssl": true
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"options": []
|
|
||||||
},
|
},
|
||||||
"assembly": {
|
"assembly": {
|
||||||
"name": "LogLib",
|
"name": "LogLib",
|
||||||
"package": "net.nosial.loglib",
|
"package": "net.nosial.loglib",
|
||||||
"company": "Nosial",
|
"company": "Nosial",
|
||||||
"copyright": "Copyright (c) 2022-2023 Nosial",
|
"copyright": "Copyright (c) 2022-2023 Nosial",
|
||||||
"version": "1.0.0",
|
"version": "2.0.7",
|
||||||
"uuid": "de1deca6-7b65-11ed-a8b0-a172264634d8"
|
"uuid": "de1deca6-7b65-11ed-a8b0-a172264634d8"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
|
@ -31,14 +30,57 @@
|
||||||
{
|
{
|
||||||
"name": "net.nosial.optslib",
|
"name": "net.nosial.optslib",
|
||||||
"version": "latest",
|
"version": "latest",
|
||||||
"source_type": "remote",
|
|
||||||
"source": "nosial/libs.opts=latest@n64"
|
"source": "nosial/libs.opts=latest@n64"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "release",
|
"name": "release",
|
||||||
"output_path": "build/release"
|
"build_type": "ncc",
|
||||||
|
"output": "build/release/%ASSEMBLY.PACKAGE%.ncc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release-compressed",
|
||||||
|
"build_type": "ncc",
|
||||||
|
"output": "build/release/%ASSEMBLY.PACKAGE%.gz.ncc",
|
||||||
|
"options": {
|
||||||
|
"compression": "high"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "debug-compressed",
|
||||||
|
"build_type": "ncc",
|
||||||
|
"output": "build/debug/%ASSEMBLY.PACKAGE%.gz.ncc",
|
||||||
|
"options": {
|
||||||
|
"compression": "high"
|
||||||
|
},
|
||||||
|
"define_constants": {
|
||||||
|
"DEBUG": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release-executable",
|
||||||
|
"build_type": "executable",
|
||||||
|
"output": "build/release/release_executable_gz",
|
||||||
|
"options": {
|
||||||
|
"ncc_configuration": "release"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release-compressed-executable",
|
||||||
|
"build_type": "executable",
|
||||||
|
"output": "build/release/release_compressed_executable",
|
||||||
|
"options": {
|
||||||
|
"ncc_configuration": "release-compressed"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "debug-compressed-executable",
|
||||||
|
"build_type": "executable",
|
||||||
|
"output": "build/debug/debug_compressed_executable",
|
||||||
|
"options": {
|
||||||
|
"ncc_configuration": "debug-compressed"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace LogLib\Abstracts;
|
|
||||||
|
|
||||||
abstract class CallType
|
|
||||||
{
|
|
||||||
const MethodCall = '->';
|
|
||||||
const StaticCall = '::';
|
|
||||||
const FunctionCall = ' ';
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace LogLib\Abstracts;
|
|
||||||
|
|
||||||
abstract class ConsoleColors
|
|
||||||
{
|
|
||||||
const Black = "0;30";
|
|
||||||
const DarkGray = "1;30";
|
|
||||||
const Blue = "0;34";
|
|
||||||
const LightBlue = "1;34";
|
|
||||||
const Green = "0;32";
|
|
||||||
const LightGreen = "1;32";
|
|
||||||
const Cyan = "0;36";
|
|
||||||
const LightCyan = "1;36";
|
|
||||||
const Red = "0;31";
|
|
||||||
const LightRed = "1;31";
|
|
||||||
const Purple = "0;35";
|
|
||||||
const LightPurple = "1;35";
|
|
||||||
const Brown = "0;33";
|
|
||||||
const Yellow = "1;33";
|
|
||||||
const LightGray = "0;37";
|
|
||||||
const White = "1;37";
|
|
||||||
const Reset = "0";
|
|
||||||
|
|
||||||
const All = [
|
|
||||||
self::Black,
|
|
||||||
self::DarkGray,
|
|
||||||
self::Blue,
|
|
||||||
self::LightBlue,
|
|
||||||
self::Green,
|
|
||||||
self::LightGreen,
|
|
||||||
self::Cyan,
|
|
||||||
self::LightCyan,
|
|
||||||
self::Red,
|
|
||||||
self::LightRed,
|
|
||||||
self::Purple,
|
|
||||||
self::LightPurple,
|
|
||||||
self::Brown,
|
|
||||||
self::Yellow,
|
|
||||||
self::LightGray,
|
|
||||||
self::White
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of random usable bright colors
|
|
||||||
*/
|
|
||||||
const BrightColors = [
|
|
||||||
self::LightBlue,
|
|
||||||
self::LightGreen,
|
|
||||||
self::LightCyan,
|
|
||||||
self::LightRed,
|
|
||||||
self::LightPurple,
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace LogLib\Abstracts;
|
|
||||||
|
|
||||||
abstract class LevelType
|
|
||||||
{
|
|
||||||
const Silent = 0;
|
|
||||||
const Fatal = 1;
|
|
||||||
const Error = 2;
|
|
||||||
const Warning = 3;
|
|
||||||
const Info = 4;
|
|
||||||
const Verbose = 5;
|
|
||||||
const Debug = 6;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All types.
|
|
||||||
*/
|
|
||||||
const All = [
|
|
||||||
self::Silent,
|
|
||||||
self::Fatal,
|
|
||||||
self::Error,
|
|
||||||
self::Warning,
|
|
||||||
self::Info,
|
|
||||||
self::Verbose,
|
|
||||||
self::Debug
|
|
||||||
];
|
|
||||||
}
|
|
87
src/LogLib/Classes/BacktraceParser.php
Normal file
87
src/LogLib/Classes/BacktraceParser.php
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib\Classes;
|
||||||
|
|
||||||
|
class BacktraceParser
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determines if the given backtrace originates from the exception handler.
|
||||||
|
*
|
||||||
|
* @param array $backtrace The backtrace array to inspect.
|
||||||
|
* @return bool Returns true if the backtrace originates from the exception handler within LogLib\Runtime class, false otherwise.
|
||||||
|
*/
|
||||||
|
public static function fromExceptionHandler(array $backtrace): bool
|
||||||
|
{
|
||||||
|
/** @var array $trace */
|
||||||
|
foreach($backtrace as $trace)
|
||||||
|
{
|
||||||
|
if(!isset($trace['function']) || $trace['function'] != 'exceptionHandler')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isset($trace['class']) || $trace['class'] != 'LogLib\Runtime')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the given backtrace originates from the error handler.
|
||||||
|
*
|
||||||
|
* @param array $backtrace The backtrace array to inspect.
|
||||||
|
* @return bool Returns true if the backtrace originates from the error handler within LogLib\Runtime class, false otherwise.
|
||||||
|
*/
|
||||||
|
public static function fromErrorHandler(array $backtrace): bool
|
||||||
|
{
|
||||||
|
/** @var array $trace */
|
||||||
|
foreach($backtrace as $trace)
|
||||||
|
{
|
||||||
|
if(!isset($trace['function']) || $trace['function'] != 'errorHandler')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isset($trace['class']) || $trace['class'] != 'LogLib\Runtime')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a given backtrace contains a call to the shutdownHandler method in the LogLib\Runtime class.
|
||||||
|
*
|
||||||
|
* @param array $backtrace The backtrace to be analyzed.
|
||||||
|
* @return bool True if the shutdownHandler method in the LogLib\Runtime class is found in the backtrace; otherwise, false.
|
||||||
|
*/
|
||||||
|
public static function fromShutdownHandler(array $backtrace): bool
|
||||||
|
{
|
||||||
|
/** @var array $trace */
|
||||||
|
foreach($backtrace as $trace)
|
||||||
|
{
|
||||||
|
if(!isset($trace['function']) || $trace['function'] != 'shutdownHandler')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isset($trace['class']) || $trace['class'] != 'LogLib\Runtime')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,167 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/** @noinspection PhpMissingFieldTypeInspection */
|
|
||||||
|
|
||||||
namespace LogLib\Classes;
|
|
||||||
|
|
||||||
use LogLib\Abstracts\ConsoleColors;
|
|
||||||
use LogLib\Abstracts\LevelType;
|
|
||||||
use LogLib\Log;
|
|
||||||
use LogLib\Objects\Event;
|
|
||||||
use LogLib\Objects\Options;
|
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
class Console
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $ApplicationColors = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats the application color for the console
|
|
||||||
*
|
|
||||||
* @param string $application
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function formatAppColor(string $application): string
|
|
||||||
{
|
|
||||||
if(!Log::getRuntimeOptions()->isDisplayAnsi())
|
|
||||||
return $application;
|
|
||||||
|
|
||||||
if(!isset(self::$ApplicationColors[$application]))
|
|
||||||
{
|
|
||||||
$colors = ConsoleColors::BrightColors;
|
|
||||||
$color = $colors[array_rand($colors)];
|
|
||||||
self::$ApplicationColors[$application] = $color;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::color($application, self::$ApplicationColors[$application]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a color formatted string for the console
|
|
||||||
*
|
|
||||||
* @param string $text
|
|
||||||
* @param string $color
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function color(string $text, string $color): string
|
|
||||||
{
|
|
||||||
if(!Log::getRuntimeOptions()->isDisplayAnsi())
|
|
||||||
return $text;
|
|
||||||
|
|
||||||
return "\033[" . $color . "m" . $text . "\033[0m";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Colorizes a event string for the console
|
|
||||||
*
|
|
||||||
* @param Event $event
|
|
||||||
* @param string $text
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function colorize(Event $event, string $text): string
|
|
||||||
{
|
|
||||||
if(!Log::getRuntimeOptions()->isDisplayAnsi())
|
|
||||||
return Utilities::levelToString($text);
|
|
||||||
|
|
||||||
$color = null;
|
|
||||||
switch($event->Level)
|
|
||||||
{
|
|
||||||
case LevelType::Debug:
|
|
||||||
$color = ConsoleColors::LightPurple;
|
|
||||||
break;
|
|
||||||
case LevelType::Verbose:
|
|
||||||
$color = ConsoleColors::LightCyan;
|
|
||||||
break;
|
|
||||||
case LevelType::Info:
|
|
||||||
$color = ConsoleColors::White;
|
|
||||||
break;
|
|
||||||
case LevelType::Warning:
|
|
||||||
$color = ConsoleColors::Yellow;
|
|
||||||
break;
|
|
||||||
case LevelType::Fatal:
|
|
||||||
$color = ConsoleColors::Red;
|
|
||||||
break;
|
|
||||||
case LevelType::Error:
|
|
||||||
$color = ConsoleColors::LightRed;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($color == null)
|
|
||||||
return Utilities::levelToString($text);
|
|
||||||
|
|
||||||
return self::color(Utilities::levelToString($text), $color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regular console output for the event object
|
|
||||||
*
|
|
||||||
* @param Options $options
|
|
||||||
* @param Event $event
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function out(Options $options, Event $event): void
|
|
||||||
{
|
|
||||||
if(!Utilities::runningInCli())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(Validate::checkLevelType(LevelType::Verbose, Log::getRuntimeOptions()->getLogLevel()))
|
|
||||||
{
|
|
||||||
$backtrace_output = Utilities::getTraceString($event, Log::getRuntimeOptions()->isDisplayAnsi());
|
|
||||||
|
|
||||||
print(sprintf(
|
|
||||||
"%s [%s] [%s] %s %s" . PHP_EOL,
|
|
||||||
$event->getTimestamp(),
|
|
||||||
self::formatAppColor($options->getApplicationName()),
|
|
||||||
self::colorize($event, $event->Level),
|
|
||||||
$backtrace_output, $event->Message
|
|
||||||
));
|
|
||||||
|
|
||||||
if($event->Exception !== null)
|
|
||||||
self::outException($event->Exception);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
print(sprintf(
|
|
||||||
"%s [%s] [%s] %s" . PHP_EOL,
|
|
||||||
$event->getTimestamp(),
|
|
||||||
self::formatAppColor($options->getApplicationName()),
|
|
||||||
self::colorize($event, $event->Level),
|
|
||||||
$event->Message
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints out the exception details
|
|
||||||
*
|
|
||||||
* @param Throwable $exception
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private static function outException(Throwable $exception): void
|
|
||||||
{
|
|
||||||
$trace_header = self::color($exception->getFile() . ':' . $exception->getLine(), ConsoleColors::Purple);
|
|
||||||
$trace_error = self::color('error: ', ConsoleColors::Red);
|
|
||||||
|
|
||||||
print($trace_header . ' ' . $trace_error . $exception->getMessage() . PHP_EOL);
|
|
||||||
print(sprintf('Error code: %s', $exception->getCode()) . PHP_EOL);
|
|
||||||
$trace = $exception->getTrace();
|
|
||||||
|
|
||||||
if(count($trace) > 1)
|
|
||||||
{
|
|
||||||
print('Stack Trace:' . PHP_EOL);
|
|
||||||
foreach($trace as $item)
|
|
||||||
{
|
|
||||||
print( ' - ' . self::color($item['file'], ConsoleColors::Red) . ':' . $item['line'] . PHP_EOL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($exception->getPrevious() !== null)
|
|
||||||
{
|
|
||||||
print('Previous Exception:' . PHP_EOL);
|
|
||||||
self::outException($exception['previous']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
122
src/LogLib/Classes/FileLock.php
Normal file
122
src/LogLib/Classes/FileLock.php
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
<?php
|
||||||
|
namespace LogLib\Classes;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FileLock
|
||||||
|
*
|
||||||
|
* This class provides functionalities to safely work with file locks and ensures
|
||||||
|
* that concurrent write operations do not overwrite each other.
|
||||||
|
* It offers methods to lock, unlock, and append data to a file.
|
||||||
|
*/
|
||||||
|
class FileLock
|
||||||
|
{
|
||||||
|
private $fileHandle;
|
||||||
|
private string $filePath;
|
||||||
|
private int $retryInterval; // in microseconds
|
||||||
|
private int $confirmationInterval; // in microseconds
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for FileLock.
|
||||||
|
*
|
||||||
|
* @param string $filePath Path to the file.
|
||||||
|
* @param int $retryInterval Time to wait between retries (in microseconds).
|
||||||
|
* @param int $confirmationInterval Time to wait before double confirmation (in microseconds).
|
||||||
|
*/
|
||||||
|
public function __construct(string $filePath, int $retryInterval=100000, int $confirmationInterval=50000)
|
||||||
|
{
|
||||||
|
$this->filePath = $filePath;
|
||||||
|
$this->retryInterval = $retryInterval;
|
||||||
|
$this->confirmationInterval = $confirmationInterval;
|
||||||
|
|
||||||
|
// Create the file if it doesn't exist
|
||||||
|
if (!file_exists($filePath))
|
||||||
|
{
|
||||||
|
// Create the file
|
||||||
|
touch($filePath);
|
||||||
|
|
||||||
|
// Set the file permissions to 0666
|
||||||
|
chmod($filePath, 0666);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks the file.
|
||||||
|
*
|
||||||
|
* @throws RuntimeException if unable to open or lock the file.
|
||||||
|
*/
|
||||||
|
private function lock(): bool
|
||||||
|
{
|
||||||
|
$this->fileHandle = @fopen($this->filePath, 'a');
|
||||||
|
if ($this->fileHandle === false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep trying to acquire the lock until it succeeds
|
||||||
|
while (!flock($this->fileHandle, LOCK_EX))
|
||||||
|
{
|
||||||
|
usleep($this->retryInterval); // Wait for the specified interval before trying again
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double confirmation
|
||||||
|
usleep($this->confirmationInterval); // Wait for the specified confirmation interval
|
||||||
|
if (!flock($this->fileHandle, LOCK_EX | LOCK_NB))
|
||||||
|
{
|
||||||
|
// If the lock cannot be re-acquired, release the current lock and retry
|
||||||
|
flock($this->fileHandle, LOCK_UN);
|
||||||
|
$this->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlocks the file after performing write operations.
|
||||||
|
*/
|
||||||
|
private function unlock(): void
|
||||||
|
{
|
||||||
|
if ($this->fileHandle !== null)
|
||||||
|
{
|
||||||
|
flock($this->fileHandle, LOCK_UN); // Release the lock
|
||||||
|
fclose($this->fileHandle); // Close the file handle
|
||||||
|
$this->fileHandle = null; // Reset the file handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends data to the file.
|
||||||
|
*
|
||||||
|
* @param string $data Data to append.
|
||||||
|
* @throws RuntimeException if unable to write to the file.
|
||||||
|
*/
|
||||||
|
public function append(string $data): void
|
||||||
|
{
|
||||||
|
if(!$this->lock())
|
||||||
|
{
|
||||||
|
// Do not proceed if the file cannot be locked
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->fileHandle !== false)
|
||||||
|
{
|
||||||
|
if (fwrite($this->fileHandle, $data) === false)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Unable to write to the file: " . $this->filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor to ensure the file handle is closed.
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if ($this->fileHandle)
|
||||||
|
{
|
||||||
|
fclose($this->fileHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
namespace LogLib\Classes;
|
namespace LogLib\Classes;
|
||||||
|
|
||||||
use LogLib\Abstracts\LevelType;
|
use LogLib\Enums\CallType;
|
||||||
use LogLib\Objects\Backtrace;
|
use LogLib\Enums\LogLevel;
|
||||||
use LogLib\Objects\Event;
|
use LogLib\Objects\Event;
|
||||||
use OptsLib\Parse;
|
use OptsLib\Parse;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
@ -11,59 +11,50 @@
|
||||||
class Utilities
|
class Utilities
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Returns the current backtrace
|
* Returns a backtrace of the calling code.
|
||||||
*
|
*
|
||||||
* @param bool $full
|
* @return array An array containing backtrace information.
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public static function getBacktrace(bool $full=false): array
|
public static function getBacktrace(): array
|
||||||
{
|
{
|
||||||
if(!function_exists('debug_backtrace'))
|
if(!function_exists('debug_backtrace'))
|
||||||
return [];
|
|
||||||
|
|
||||||
$backtrace = debug_backtrace();
|
|
||||||
$results = [];
|
|
||||||
|
|
||||||
foreach($backtrace as $trace)
|
|
||||||
{
|
{
|
||||||
if(isset($trace['class'] ) && str_contains($trace['class'], 'LogLib') && !$full)
|
return [];
|
||||||
continue;
|
|
||||||
|
|
||||||
$results[] = new Backtrace($trace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
return debug_backtrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current level type as a string
|
* Converts a log level to its corresponding string representation.
|
||||||
*
|
*
|
||||||
* @param int $level
|
* @param LogLevel $level The log level to convert.
|
||||||
* @return string
|
* @return string The string representation of the log level.
|
||||||
*/
|
*/
|
||||||
public static function levelToString(int $level): string
|
public static function levelToString(LogLevel $level): string
|
||||||
{
|
{
|
||||||
return match ($level)
|
return match ($level)
|
||||||
{
|
{
|
||||||
LevelType::Debug => 'DBG',
|
LogLevel::DEBUG => 'DBG',
|
||||||
LevelType::Verbose => 'VRB',
|
LogLevel::VERBOSE => 'VRB',
|
||||||
LevelType::Info => 'INF',
|
LogLevel::INFO => 'INF',
|
||||||
LevelType::Warning => 'WRN',
|
LogLevel::WARNING => 'WRN',
|
||||||
LevelType::Fatal => 'CRT',
|
LogLevel::FATAL => 'CRT',
|
||||||
LevelType::Error => 'ERR',
|
LogLevel::ERROR => 'ERR',
|
||||||
default => 'UNK',
|
default => 'UNK',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple method to determine if the current environment is a CLI environment
|
* Determines whether the application is currently running in the command line interface (CLI) mode.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool true if running in CLI mode, false otherwise.
|
||||||
*/
|
*/
|
||||||
public static function runningInCli(): bool
|
public static function runningInCli(): bool
|
||||||
{
|
{
|
||||||
if(function_exists('php_sapi_name'))
|
if(function_exists('php_sapi_name'))
|
||||||
{
|
{
|
||||||
|
/** @noinspection ConstantCanBeUsedInspection */
|
||||||
return strtolower(php_sapi_name()) === 'cli';
|
return strtolower(php_sapi_name()) === 'cli';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,68 +67,72 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to determine the current log level from the command line arguments
|
* Returns the log level based on the configuration.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return LogLevel The log level. This value represents the severity or importance of the log messages.
|
||||||
|
* The returned value will be one of the constants defined in the LevelType class:
|
||||||
|
* - DEBUG (6)
|
||||||
|
* - VERBOSE (5)
|
||||||
|
* - INFO (4)
|
||||||
|
* - WARNING (3)
|
||||||
|
* - ERROR (2)
|
||||||
|
* - FATAL (1)
|
||||||
|
* - SILENT (0)
|
||||||
|
* If no log level is configured or the configured level is not recognized, the INFO level (4) will be returned by default.
|
||||||
*/
|
*/
|
||||||
public static function getLogLevel(): int
|
private static function parseLogLevel(string $logLevel): LogLevel
|
||||||
{
|
{
|
||||||
$args = Parse::getArguments();
|
switch(strtolower($logLevel))
|
||||||
|
|
||||||
$selected_level = ($args['log'] ?? $args['log-level'] ?? (getenv('LOG_LEVEL') ?: null) ?? null);
|
|
||||||
|
|
||||||
if($selected_level === null)
|
|
||||||
return LevelType::Info;
|
|
||||||
|
|
||||||
switch(strtolower($selected_level))
|
|
||||||
{
|
{
|
||||||
case LevelType::Debug:
|
case LogLevel::DEBUG:
|
||||||
case 'debug':
|
case 'debug':
|
||||||
case '6':
|
case '6':
|
||||||
case 'dbg':
|
case 'dbg':
|
||||||
return LevelType::Debug;
|
return LogLevel::DEBUG;
|
||||||
|
|
||||||
case LevelType::Verbose:
|
case LogLevel::VERBOSE:
|
||||||
case 'verbose':
|
case 'verbose':
|
||||||
case '5':
|
case '5':
|
||||||
case 'vrb':
|
case 'vrb':
|
||||||
return LevelType::Verbose;
|
return LogLevel::VERBOSE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case LevelType::Info:
|
case LogLevel::INFO:
|
||||||
case 'info':
|
case 'info':
|
||||||
case '4':
|
case '4':
|
||||||
case 'inf':
|
case 'inf':
|
||||||
return LevelType::Info;
|
return LogLevel::INFO;
|
||||||
|
|
||||||
case LevelType::Warning:
|
case LogLevel::WARNING:
|
||||||
case 'warning':
|
case 'warning':
|
||||||
case '3':
|
case '3':
|
||||||
case 'wrn':
|
case 'wrn':
|
||||||
return LevelType::Warning;
|
return LogLevel::WARNING;
|
||||||
|
|
||||||
case LevelType::Error:
|
case LogLevel::ERROR:
|
||||||
case 'error':
|
case 'error':
|
||||||
case '2':
|
case '2':
|
||||||
case 'err':
|
case 'err':
|
||||||
return LevelType::Error;
|
return LogLevel::ERROR;
|
||||||
|
|
||||||
case LevelType::Fatal:
|
case LogLevel::FATAL:
|
||||||
case 'fatal':
|
case 'fatal':
|
||||||
case '1':
|
case '1':
|
||||||
case 'crt':
|
case 'crt':
|
||||||
return LevelType::Fatal;
|
return LogLevel::FATAL;
|
||||||
|
|
||||||
case LevelType::Silent:
|
case LogLevel::SILENT:
|
||||||
case 'silent':
|
case 'silent':
|
||||||
case '0':
|
case '0':
|
||||||
case 'sil':
|
case 'sil':
|
||||||
return LevelType::Silent;
|
return LogLevel::SILENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* Checks if ANSI escape sequences should be displayed in the output.
|
||||||
|
*
|
||||||
|
* @return bool Returns true if ANSI escape sequences should be displayed, false otherwise.
|
||||||
*/
|
*/
|
||||||
public static function getDisplayAnsi(): bool
|
public static function getDisplayAnsi(): bool
|
||||||
{
|
{
|
||||||
|
@ -145,74 +140,140 @@
|
||||||
$display_ansi = ($args['display-ansi'] ?? $args['ansi'] ?? null);
|
$display_ansi = ($args['display-ansi'] ?? $args['ansi'] ?? null);
|
||||||
|
|
||||||
if($display_ansi === null)
|
if($display_ansi === null)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Strict boolean response
|
// Strict boolean response
|
||||||
return strtolower($display_ansi) === 'true' || $display_ansi === '1';
|
return strtolower($display_ansi) === 'true' || $display_ansi === '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current active log file name, the current value can
|
* Returns a string representation of the backtrace for the given event.
|
||||||
* change depending on the date/time, if it has changed; close the
|
|
||||||
* old file and open a new one.
|
|
||||||
*
|
*
|
||||||
* @return string
|
* @param Event $event The event object for which to generate the backtrace string.
|
||||||
|
* @return string|null A string representation of the backtrace for the event, or null if the event has no backtrace.
|
||||||
|
* The output format is: ClassName::methodName() or functionName() depending on the type of call.
|
||||||
|
* If $ansi is true, the output will be colored using ANSI escape codes.
|
||||||
|
* If the event has no backtrace, the constant CallType::LAMBDA_CALL will be returned.
|
||||||
*/
|
*/
|
||||||
public static function getLogFilename(): string
|
public static function getTraceString(Event $event, bool $ansi = true): ?string
|
||||||
{
|
{
|
||||||
return date('Y-m-d') . '.log';
|
if ($event->getBacktrace() === null || count($event->getBacktrace()) === 0)
|
||||||
|
{
|
||||||
|
return CallType::LAMBDA_CALL->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
$backtrace = $event->getBacktrace()[count($event->getBacktrace()) - 1];
|
||||||
* Returns a random string of characters
|
// Ignore \LogLib namespace
|
||||||
*
|
if (isset($backtrace['class']) && str_starts_with($backtrace['class'], 'LogLib'))
|
||||||
* @param int $length
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function randomString(int $length = 32): string
|
|
||||||
{
|
{
|
||||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
if (isset($backtrace['file']))
|
||||||
$charactersLength = strlen($characters);
|
|
||||||
$randomString = '';
|
|
||||||
for ($i = 0; $i < $length; $i++)
|
|
||||||
{
|
{
|
||||||
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
if ($ansi)
|
||||||
|
{
|
||||||
|
return "\033[1;37m" . basename($backtrace['file']) . "\033[0m";
|
||||||
}
|
}
|
||||||
return $randomString;
|
return basename($backtrace['file']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return self::determineCallType($event->getBacktrace())->value; // Return a placeholder value
|
||||||
* @param Event $event
|
}
|
||||||
* @param bool $ansi
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public static function getTraceString(Event $event, bool $ansi=false): ?string
|
|
||||||
{
|
|
||||||
if($event->getBacktrace() == null)
|
|
||||||
return 'λ';
|
|
||||||
|
|
||||||
$backtrace = $event->getBacktrace()[0];
|
if ($backtrace['function'] === '{closure}')
|
||||||
$function = $backtrace->getFunction();
|
{
|
||||||
$class = $backtrace->getClass();
|
if (isset($backtrace['file']))
|
||||||
|
{
|
||||||
|
if ($ansi)
|
||||||
|
{
|
||||||
|
return "\033[1;37m" . basename($backtrace['file']) . "\033[0m" . CallType::STATIC_CALL->value . CallType::LAMBDA_CALL->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return basename($backtrace['file']) . CallType::STATIC_CALL->value . CallType::LAMBDA_CALL->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::determineCallType($event->getBacktrace())->value . CallType::STATIC_CALL->value . CallType::LAMBDA_CALL->value; // Adjusted to handle missing 'file'
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($backtrace['function'] === 'eval')
|
||||||
|
{
|
||||||
|
if (isset($backtrace['file']))
|
||||||
|
{
|
||||||
|
if ($ansi)
|
||||||
|
{
|
||||||
|
return "\033[1;37m" . basename($backtrace['file']) . "\033[0m" . CallType::STATIC_CALL->value . CallType::EVAL_CALL->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return basename($backtrace['file']) . CallType::STATIC_CALL->value . CallType::EVAL_CALL->value;
|
||||||
|
}
|
||||||
|
return self::determineCallType($event->getBacktrace())->value . CallType::STATIC_CALL->value . CallType::EVAL_CALL->value; // Adjusted to handle missing 'file'
|
||||||
|
}
|
||||||
|
|
||||||
if ($ansi)
|
if ($ansi)
|
||||||
{
|
{
|
||||||
$function = "\033[1;37m$function\033[0m";
|
$function = sprintf("\033[1;37m%s\033[0m", $backtrace['function']);
|
||||||
$class = "\033[1;37m$class\033[0m";
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$function = $backtrace['function'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if($class == null)
|
$class = null;
|
||||||
return "{$function}()";
|
|
||||||
|
|
||||||
$type = ($backtrace->getType() == '->' ? '->' : '::');
|
if (isset($backtrace["class"]))
|
||||||
return "{$class}{$type}{$function}()";
|
{
|
||||||
|
if ($ansi)
|
||||||
|
{
|
||||||
|
$class = sprintf("\033[1;37m%s\033[0m", $backtrace['class']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$class = $backtrace['class'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($class === null)
|
||||||
|
{
|
||||||
|
return $function . CallType::FUNCTION_CALL->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = ($backtrace['type'] === CallType::METHOD_CALL ? CallType::METHOD_CALL : CallType::STATIC_CALL);
|
||||||
|
return "{$class}{$type->value}{$function}" . CallType::FUNCTION_CALL->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array representation of a throwable exception
|
* Determines the type of call based on the provided backtrace.
|
||||||
*
|
*
|
||||||
* @param Throwable $e
|
* @param array $backtrace The backtrace information of the calling code.
|
||||||
* @return array
|
* @return CallType The type of call detected.
|
||||||
|
*/
|
||||||
|
private static function determineCallType(array $backtrace): CallType
|
||||||
|
{
|
||||||
|
if(BacktraceParser::fromErrorHandler($backtrace))
|
||||||
|
{
|
||||||
|
return CallType::ERROR_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(BacktraceParser::fromExceptionHandler($backtrace))
|
||||||
|
{
|
||||||
|
return CallType::EXCEPTION_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(BacktraceParser::fromShutdownHandler($backtrace))
|
||||||
|
{
|
||||||
|
return CallType::SHUTDOWN_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallType::UNKNOWN_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an exception object to an array representation.
|
||||||
|
*
|
||||||
|
* @param Throwable $e The exception object to convert.
|
||||||
|
* @return array An array containing the details of the exception.
|
||||||
|
* The array includes the exception message, code, file, line, and a formatted trace.
|
||||||
|
* The trace is formatted as a string containing the file, line, class, type, and function for each call in the traceback.
|
||||||
*/
|
*/
|
||||||
public static function exceptionToArray(Throwable $e): array
|
public static function exceptionToArray(Throwable $e): array
|
||||||
{
|
{
|
||||||
|
@ -233,4 +294,135 @@
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the directory path for logging purposes.
|
||||||
|
*
|
||||||
|
* @return string The path to the log directory, or a temporary directory if not set.
|
||||||
|
*/
|
||||||
|
public static function getLogDirectory(): string
|
||||||
|
{
|
||||||
|
$args = Parse::getArguments();
|
||||||
|
$LOGGING_DIRECTORY = ($args['logging-directory'] ?? getenv('LOGGING_DIRECTORY') ?? null);
|
||||||
|
|
||||||
|
if($LOGGING_DIRECTORY === null)
|
||||||
|
{
|
||||||
|
return sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'logs';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $LOGGING_DIRECTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if console logging is enabled based on command-line arguments,
|
||||||
|
* execution environment, or environment variables.
|
||||||
|
*
|
||||||
|
* @return bool True if console logging is enabled, false otherwise.
|
||||||
|
*/
|
||||||
|
public static function getConsoleLoggingEnabled(): bool
|
||||||
|
{
|
||||||
|
if(isset(Parse::getArguments()['log-level']))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(self::runningInCli())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(getenv('LOGGING_CONSOLE') === 'true' || getenv('LOGGING_CONSOLE') === '1')
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the current logging level for console output.
|
||||||
|
*
|
||||||
|
* @return LogLevel The determined logging level.
|
||||||
|
*/
|
||||||
|
public static function getConsoleLoggingLevel(): LogLevel
|
||||||
|
{
|
||||||
|
return self::parseLogLevel(($args['log'] ?? $args['log-level'] ?? (getenv('LOG_LEVEL') ?: 'info') ?? 'info'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if file logging is enabled based on various conditions.
|
||||||
|
*
|
||||||
|
* @return bool True if file logging is enabled, false otherwise.
|
||||||
|
*/
|
||||||
|
public static function getFileLoggingEnabled(): bool
|
||||||
|
{
|
||||||
|
if(isset(Parse::getArguments()['logging-directory']))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(getenv('LOGGING_DIRECTORY') !== null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_writable(self::getLogDirectory()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the logging level for file outputs based on environment variables or command line arguments.
|
||||||
|
*
|
||||||
|
* @return LogLevel The logging level to be used for file logging.
|
||||||
|
*/
|
||||||
|
public static function getFileLoggingLevel(): LogLevel
|
||||||
|
{
|
||||||
|
if(getenv('LOGGING_FILE_LEVEL') !== null)
|
||||||
|
{
|
||||||
|
return self::parseLogLevel(getenv('LOGGING_FILE_LEVEL'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset(Parse::getArguments()['logging-file-level']))
|
||||||
|
{
|
||||||
|
return self::parseLogLevel(Parse::getArguments()['logging-file-level']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LogLevel::WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the directory path for file logging.
|
||||||
|
*
|
||||||
|
* @return string The logging directory path.
|
||||||
|
*/
|
||||||
|
public static function getFileLoggingDirectory(): string
|
||||||
|
{
|
||||||
|
$args = Parse::getArguments();
|
||||||
|
$LOGGING_DIRECTORY = ($args['logging-directory'] ?? getenv('LOGGING_DIRECTORY') ?? null);
|
||||||
|
|
||||||
|
if($LOGGING_DIRECTORY === null || $LOGGING_DIRECTORY === false || strlen($LOGGING_DIRECTORY) === 0)
|
||||||
|
{
|
||||||
|
return sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'logs';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $LOGGING_DIRECTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitizes a file name by replacing spaces with hyphens and removing illegal characters.
|
||||||
|
*
|
||||||
|
* @param string $name The file name to sanitize.
|
||||||
|
* @return string The sanitized file name.
|
||||||
|
*/
|
||||||
|
public static function sanitizeFileName(string $name): string
|
||||||
|
{
|
||||||
|
// Replace spaces with hyphens
|
||||||
|
$name = str_replace(' ', '-', $name);
|
||||||
|
|
||||||
|
// Remove illegal characters and replace escapable characters with underscores
|
||||||
|
return preg_replace('/[\/:*?"<>|.]/', '_', $name);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -2,108 +2,78 @@
|
||||||
|
|
||||||
namespace LogLib\Classes;
|
namespace LogLib\Classes;
|
||||||
|
|
||||||
use LogLib\Abstracts\LevelType;
|
use LogLib\Enums\LogLevel;
|
||||||
|
|
||||||
class Validate
|
class Validate
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Validates that the level is valid
|
* Checks if the given input level is valid for the current level.
|
||||||
*
|
*
|
||||||
* @param string $level
|
* @param LogLevel $input The input level to check.
|
||||||
* @return bool
|
* @param LogLevel $current_level The current level to compare against.
|
||||||
|
* @return bool Returns true if the input level is valid for the current level, false otherwise.
|
||||||
*/
|
*/
|
||||||
public static function LevelType(string $level): bool
|
public static function checkLevelType(LogLevel $input, LogLevel $current_level): bool
|
||||||
{
|
{
|
||||||
return in_array($level, LevelType::All);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the input level matches the current level
|
|
||||||
*
|
|
||||||
* @param string $input
|
|
||||||
* @param string $current_level
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function checkLevelType(string $input, string $current_level): bool
|
|
||||||
{
|
|
||||||
if($input == null)
|
|
||||||
return false;
|
|
||||||
if($current_level == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$input = strtolower($input);
|
|
||||||
if(!Validate::LevelType($input))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$current_level = strtolower($current_level);
|
|
||||||
if(!Validate::LevelType($current_level))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch($current_level)
|
switch($current_level)
|
||||||
{
|
{
|
||||||
case LevelType::Debug:
|
case LogLevel::DEBUG:
|
||||||
$levels = [
|
$levels = [
|
||||||
LevelType::Debug,
|
LogLevel::DEBUG,
|
||||||
LevelType::Verbose,
|
LogLevel::VERBOSE,
|
||||||
LevelType::Info,
|
LogLevel::INFO,
|
||||||
LevelType::Warning,
|
LogLevel::WARNING,
|
||||||
LevelType::Fatal,
|
LogLevel::FATAL,
|
||||||
LevelType::Error
|
LogLevel::ERROR
|
||||||
];
|
];
|
||||||
if(in_array($input, $levels))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case LevelType::Verbose:
|
return in_array($input, $levels, true);
|
||||||
|
|
||||||
|
case LogLevel::VERBOSE:
|
||||||
$levels = [
|
$levels = [
|
||||||
LevelType::Verbose,
|
LogLevel::VERBOSE,
|
||||||
LevelType::Info,
|
LogLevel::INFO,
|
||||||
LevelType::Warning,
|
LogLevel::WARNING,
|
||||||
LevelType::Fatal,
|
LogLevel::FATAL,
|
||||||
LevelType::Error
|
LogLevel::ERROR
|
||||||
];
|
];
|
||||||
if(in_array($input, $levels))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case LevelType::Info:
|
return in_array($input, $levels, true);
|
||||||
|
|
||||||
|
case LogLevel::INFO:
|
||||||
$levels = [
|
$levels = [
|
||||||
LevelType::Info,
|
LogLevel::INFO,
|
||||||
LevelType::Warning,
|
LogLevel::WARNING,
|
||||||
LevelType::Fatal,
|
LogLevel::FATAL,
|
||||||
LevelType::Error
|
LogLevel::ERROR
|
||||||
];
|
];
|
||||||
if(in_array($input, $levels))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case LevelType::Warning:
|
return in_array($input, $levels, true);
|
||||||
|
|
||||||
|
case LogLevel::WARNING:
|
||||||
$levels = [
|
$levels = [
|
||||||
LevelType::Warning,
|
LogLevel::WARNING,
|
||||||
LevelType::Fatal,
|
LogLevel::FATAL,
|
||||||
LevelType::Error
|
LogLevel::ERROR
|
||||||
];
|
];
|
||||||
if(in_array($input, $levels))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case LevelType::Error:
|
return in_array($input, $levels, true);
|
||||||
|
|
||||||
|
case LogLevel::ERROR:
|
||||||
$levels = [
|
$levels = [
|
||||||
LevelType::Fatal,
|
LogLevel::FATAL,
|
||||||
LevelType::Error
|
LogLevel::ERROR
|
||||||
];
|
];
|
||||||
if(in_array($input, $levels))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case LevelType::Fatal:
|
return in_array($input, $levels, true);
|
||||||
if($input == LevelType::Fatal)
|
|
||||||
return true;
|
case LogLevel::FATAL:
|
||||||
return false;
|
return $input == LogLevel::FATAL;
|
||||||
|
|
||||||
|
case LogLevel::SILENT:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
case LevelType::Silent:
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
69
src/LogLib/Enums/CallType.php
Normal file
69
src/LogLib/Enums/CallType.php
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib\Enums;
|
||||||
|
|
||||||
|
enum CallType : string
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Represents a method call.
|
||||||
|
*
|
||||||
|
* @var string METHOD_CALL
|
||||||
|
*/
|
||||||
|
case METHOD_CALL = '->';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a static method call.
|
||||||
|
*
|
||||||
|
* @var string STATIC_CALL
|
||||||
|
*/
|
||||||
|
case STATIC_CALL = '::';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a function call.
|
||||||
|
*
|
||||||
|
* @var string FUNCTION_CALL
|
||||||
|
*/
|
||||||
|
case FUNCTION_CALL = '()';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a lambda function call.
|
||||||
|
*
|
||||||
|
* @var string LAMBDA_CALL
|
||||||
|
*/
|
||||||
|
case LAMBDA_CALL = 'λ';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an eval() call.
|
||||||
|
*
|
||||||
|
* @var string EVAL_CALL
|
||||||
|
*/
|
||||||
|
case EVAL_CALL = 'eval()';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an unknown file.
|
||||||
|
*
|
||||||
|
* @var string UNKNOWN_FILE
|
||||||
|
*/
|
||||||
|
case UNKNOWN_FILE = '?';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a runtime error handler.
|
||||||
|
*
|
||||||
|
* @var string ERROR_HANDLER
|
||||||
|
*/
|
||||||
|
case ERROR_HANDLER = 'RUNTIME_ERROR';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a shutdown handler event.
|
||||||
|
*
|
||||||
|
* @var string SHUTDOWN_HANDLER
|
||||||
|
*/
|
||||||
|
case SHUTDOWN_HANDLER = 'SHUTDOWN_ERROR';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an exception handler for runtime exceptions.
|
||||||
|
*
|
||||||
|
* @var string EXCEPTION_HANDLER
|
||||||
|
*/
|
||||||
|
case EXCEPTION_HANDLER = 'RUNTIME_EXCEPTION';
|
||||||
|
}
|
58
src/LogLib/Enums/ConsoleColors.php
Normal file
58
src/LogLib/Enums/ConsoleColors.php
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib\Enums;
|
||||||
|
|
||||||
|
enum ConsoleColors : string
|
||||||
|
{
|
||||||
|
case BLUE = "0;34";
|
||||||
|
|
||||||
|
case LIGHT_BLUE = "1;34";
|
||||||
|
|
||||||
|
case GREEN = "0;32";
|
||||||
|
|
||||||
|
case LIGHT_GREEN = "1;32";
|
||||||
|
|
||||||
|
case CYAN = "0;36";
|
||||||
|
|
||||||
|
case LIGHT_CYAN = "1;36";
|
||||||
|
|
||||||
|
case RED = "0;31";
|
||||||
|
|
||||||
|
case LIGHT_RED = "1;31";
|
||||||
|
|
||||||
|
case PURPLE = "0;35";
|
||||||
|
|
||||||
|
case LIGHT_PURPLE = "1;35";
|
||||||
|
|
||||||
|
case BROWN = "0;33";
|
||||||
|
|
||||||
|
case YELLOW = "1;33";
|
||||||
|
|
||||||
|
case LIGHT_GRAY = "0;37";
|
||||||
|
|
||||||
|
case WHITE = "1;37";
|
||||||
|
|
||||||
|
case RESET = "0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an array of all possible supported color values.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public const ALL = [
|
||||||
|
self::BLUE,
|
||||||
|
self::LIGHT_BLUE,
|
||||||
|
self::GREEN,
|
||||||
|
self::LIGHT_GREEN,
|
||||||
|
self::CYAN,
|
||||||
|
self::LIGHT_CYAN,
|
||||||
|
self::RED,
|
||||||
|
self::LIGHT_RED,
|
||||||
|
self::PURPLE,
|
||||||
|
self::LIGHT_PURPLE,
|
||||||
|
self::BROWN,
|
||||||
|
self::YELLOW,
|
||||||
|
self::LIGHT_GRAY,
|
||||||
|
self::WHITE
|
||||||
|
];
|
||||||
|
}
|
54
src/LogLib/Enums/LogLevel.php
Normal file
54
src/LogLib/Enums/LogLevel.php
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib\Enums;
|
||||||
|
|
||||||
|
enum LogLevel : int
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Silent type.
|
||||||
|
*/
|
||||||
|
case SILENT = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fatal type.
|
||||||
|
*/
|
||||||
|
case FATAL = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error type.
|
||||||
|
*/
|
||||||
|
case ERROR = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
case WARNING = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information type.
|
||||||
|
*/
|
||||||
|
case INFO = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verbose type.
|
||||||
|
*/
|
||||||
|
case VERBOSE = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug type.
|
||||||
|
*/
|
||||||
|
case DEBUG = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All types.
|
||||||
|
*/
|
||||||
|
public const ALL = [
|
||||||
|
self::SILENT,
|
||||||
|
self::FATAL,
|
||||||
|
self::ERROR,
|
||||||
|
self::WARNING,
|
||||||
|
self::INFO,
|
||||||
|
self::VERBOSE,
|
||||||
|
self::DEBUG
|
||||||
|
];
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace LogLib\Exceptions;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
class ConfigurationException extends Exception
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param string $message
|
|
||||||
* @param int $code
|
|
||||||
* @param Throwable|null $previous
|
|
||||||
*/
|
|
||||||
public function __construct(string $message = "", int $code = 0, ?Throwable $previous = null)
|
|
||||||
{
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
$this->message = $message;
|
|
||||||
$this->code = $code;
|
|
||||||
}
|
|
||||||
}
|
|
223
src/LogLib/Handlers/ConsoleLogging.php
Normal file
223
src/LogLib/Handlers/ConsoleLogging.php
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib\Handlers;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LogLib\Classes\Utilities;
|
||||||
|
use LogLib\Classes\Validate;
|
||||||
|
use LogLib\Enums\ConsoleColors;
|
||||||
|
use LogLib\Enums\LogLevel;
|
||||||
|
use LogLib\Interfaces\LogHandlerInterface;
|
||||||
|
use LogLib\Objects\Application;
|
||||||
|
use LogLib\Objects\Event;
|
||||||
|
use RuntimeException;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class ConsoleLogging implements LogHandlerInterface
|
||||||
|
{
|
||||||
|
private static array $application_colors = [];
|
||||||
|
private static float|int|null $last_tick_time = null;
|
||||||
|
private static ?int $largest_tick_length = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public static function handle(Application $application, Event $event): void
|
||||||
|
{
|
||||||
|
if(!Utilities::runningInCli())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the event level is enabled for console logging
|
||||||
|
if(!Validate::checkLevelType($event->getLevel(), $application->getConsoleLoggingLevel()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Validate::checkLevelType(LogLevel::DEBUG, $application->getConsoleLoggingLevel()))
|
||||||
|
{
|
||||||
|
$backtrace_output = Utilities::getTraceString($event);
|
||||||
|
|
||||||
|
print(sprintf("[%s] [%s] [%s] %s %s" . PHP_EOL,
|
||||||
|
self::getTimestamp(), self::formatAppColor($application->getApplicationName()), self::colorize($event),
|
||||||
|
$backtrace_output, $event->getMessage()
|
||||||
|
));
|
||||||
|
|
||||||
|
if($event->getException() !== null)
|
||||||
|
{
|
||||||
|
self::outException($event->getException());
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Validate::checkLevelType(LogLevel::VERBOSE, $application->getConsoleLoggingLevel()))
|
||||||
|
{
|
||||||
|
$backtrace_output = Utilities::getTraceString($event);
|
||||||
|
|
||||||
|
print(sprintf("[%s] [%s] %s %s" . PHP_EOL,
|
||||||
|
self::formatAppColor($application->getApplicationName()),
|
||||||
|
self::colorize($event),
|
||||||
|
$backtrace_output, $event->getMessage()
|
||||||
|
));
|
||||||
|
|
||||||
|
if($event->getException() !== null)
|
||||||
|
{
|
||||||
|
self::outException($event->getException());
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print(sprintf("[%s] [%s] %s" . PHP_EOL,
|
||||||
|
self::formatAppColor($application->getApplicationName()),
|
||||||
|
self::colorize($event),
|
||||||
|
$event->getMessage()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the application name with a color for the console
|
||||||
|
*
|
||||||
|
* @param string $application_name The application name
|
||||||
|
* @return string The formatted application name
|
||||||
|
*/
|
||||||
|
private static function formatAppColor(string $application_name): string
|
||||||
|
{
|
||||||
|
if(!isset(self::$application_colors[$application_name]))
|
||||||
|
{
|
||||||
|
$colors = ConsoleColors::ALL;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$color = $colors[random_int(0, count($colors) - 1)];
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(sprintf('Unable to generate random color for application "%s"', $application_name), $e->getCode(), $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$application_colors[$application_name] = $color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::color($application_name, self::$application_colors[$application_name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a specified color to the given text, using ANSI escape sequences.
|
||||||
|
*
|
||||||
|
* @param string $text The text to apply the color to.
|
||||||
|
* @param ConsoleColors $color The ANSI color code to apply to the text.
|
||||||
|
* @return string The text with the specified color applied.
|
||||||
|
*/
|
||||||
|
private static function color(string $text, ConsoleColors $color): string
|
||||||
|
{
|
||||||
|
return "\033[" . $color->value . "m" . $text . "\033[0m";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Colorizes the log message based on the event level using ANSI escape sequences.
|
||||||
|
*
|
||||||
|
* @param Event $event The log event to colorize.
|
||||||
|
* @return string The colorized log message.
|
||||||
|
*/
|
||||||
|
private static function colorize(Event $event): string
|
||||||
|
{
|
||||||
|
$color = match($event->getLevel())
|
||||||
|
{
|
||||||
|
LogLevel::DEBUG => ConsoleColors::LIGHT_PURPLE,
|
||||||
|
LogLevel::VERBOSE => ConsoleColors::LIGHT_CYAN,
|
||||||
|
LogLevel::INFO => ConsoleColors::WHITE,
|
||||||
|
LogLevel::WARNING => ConsoleColors::YELLOW,
|
||||||
|
LogLevel::FATAL => ConsoleColors::RED,
|
||||||
|
LogLevel::ERROR => ConsoleColors::LIGHT_RED,
|
||||||
|
default => null,
|
||||||
|
};
|
||||||
|
|
||||||
|
if($color === null)
|
||||||
|
{
|
||||||
|
return Utilities::levelToString($event->getLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::color(Utilities::levelToString($event->getLevel()), $color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the current timestamp as a formatted string.
|
||||||
|
*
|
||||||
|
* @return string The current timestamp.
|
||||||
|
*/
|
||||||
|
private static function getTimestamp(): string
|
||||||
|
{
|
||||||
|
$tick_time = (string)microtime(true);
|
||||||
|
|
||||||
|
if(!is_null(self::$largest_tick_length) && strlen($tick_time) > (int)self::$largest_tick_length)
|
||||||
|
{
|
||||||
|
self::$largest_tick_length = strlen($tick_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen($tick_time) < self::$largest_tick_length)
|
||||||
|
{
|
||||||
|
$tick_time = str_pad($tick_time, (strlen($tick_time) + (self::$largest_tick_length - strlen($tick_time))));
|
||||||
|
}
|
||||||
|
|
||||||
|
$fmt_tick = $tick_time;
|
||||||
|
if(self::$last_tick_time !== null)
|
||||||
|
{
|
||||||
|
$timeDiff = microtime(true) - self::$last_tick_time;
|
||||||
|
|
||||||
|
if ($timeDiff > 1.0)
|
||||||
|
{
|
||||||
|
$fmt_tick = self::color($tick_time, ConsoleColors::LIGHT_RED);
|
||||||
|
}
|
||||||
|
elseif ($timeDiff > 0.5)
|
||||||
|
{
|
||||||
|
$fmt_tick = self::color($tick_time, ConsoleColors::YELLOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$last_tick_time = $tick_time;
|
||||||
|
return $fmt_tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints information about the given exception, including the error message, error code,
|
||||||
|
* and stack trace.
|
||||||
|
*
|
||||||
|
* @param Throwable|null $exception The exception to print information about.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function outException(?Throwable $exception=null): void
|
||||||
|
{
|
||||||
|
if($exception === null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$trace_header = self::color($exception->getFile() . ':' . $exception->getLine(), ConsoleColors::PURPLE);
|
||||||
|
$trace_error = self::color('error: ', ConsoleColors::RED);
|
||||||
|
|
||||||
|
print($trace_header . ' ' . $trace_error . $exception->getMessage() . PHP_EOL);
|
||||||
|
print(sprintf('Error code: %s', $exception->getCode()) . PHP_EOL);
|
||||||
|
$trace = $exception->getTrace();
|
||||||
|
|
||||||
|
if(count($trace) > 1)
|
||||||
|
{
|
||||||
|
print('Stack Trace:' . PHP_EOL);
|
||||||
|
foreach($trace as $item)
|
||||||
|
{
|
||||||
|
if(isset($item['file']) && isset($item['line']))
|
||||||
|
{
|
||||||
|
print( ' - ' . self::color($item['file'], ConsoleColors::RED) . ':' . $item['line'] . PHP_EOL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($exception->getPrevious() !== null)
|
||||||
|
{
|
||||||
|
print('Previous Exception:' . PHP_EOL);
|
||||||
|
self::outException($exception->getPrevious());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
151
src/LogLib/Handlers/FileLogging.php
Normal file
151
src/LogLib/Handlers/FileLogging.php
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib\Handlers;
|
||||||
|
|
||||||
|
use LogLib\Classes\FileLock;
|
||||||
|
use LogLib\Classes\Utilities;
|
||||||
|
use LogLib\Classes\Validate;
|
||||||
|
use LogLib\Enums\LogLevel;
|
||||||
|
use LogLib\Interfaces\LogHandlerInterface;
|
||||||
|
use LogLib\Objects\Application;
|
||||||
|
use LogLib\Objects\Event;
|
||||||
|
use RuntimeException;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class FileLogging implements LogHandlerInterface
|
||||||
|
{
|
||||||
|
private static array $application_logs = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public static function handle(Application $application, Event $event): void
|
||||||
|
{
|
||||||
|
if(!Validate::checkLevelType($event->getLevel(), $application->getFileLoggingLevel()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Validate::checkLevelType(LogLevel::DEBUG, $application->getConsoleLoggingLevel()))
|
||||||
|
{
|
||||||
|
$backtrace_output = Utilities::getTraceString($event, false);
|
||||||
|
$output = sprintf("[%s] [%s] [%s] %s %s" . PHP_EOL,
|
||||||
|
self::getTimestamp(), $application->getApplicationName(), $event->getLevel()->name, $backtrace_output, $event->getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if(Validate::checkLevelType(LogLevel::VERBOSE, $application->getConsoleLoggingLevel()))
|
||||||
|
{
|
||||||
|
$backtrace_output = Utilities::getTraceString($event, false);
|
||||||
|
$output = sprintf("[%s] [%s] [%s] %s %s" . PHP_EOL, self::getTimestamp(), $application->getApplicationName(), $event->getLevel()->name, $backtrace_output, $event->getMessage());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$output = sprintf("[%s] [%s] [%s] %s" . PHP_EOL, self::getTimestamp(), $application->getApplicationName(), $event->getLevel()->name, $event->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if($event->getException() !== null)
|
||||||
|
{
|
||||||
|
$output .= self::outException($event->getException());
|
||||||
|
}
|
||||||
|
|
||||||
|
self::getLogger($application)->append($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the logger instance associated with the given application.
|
||||||
|
* If the logger does not exist, it initializes a new one and stores it.
|
||||||
|
*
|
||||||
|
* @param Application $application The application for which the logger is to be retrieved.
|
||||||
|
* @return FileLock The logger instance associated with the specified application.
|
||||||
|
*/
|
||||||
|
private static function getLogger(Application $application): FileLock
|
||||||
|
{
|
||||||
|
if(!isset(self::$application_logs[$application->getApplicationName()]))
|
||||||
|
{
|
||||||
|
self::$application_logs[$application->getApplicationName()] = new FileLock(self::getLogFile($application));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$application_logs[$application->getApplicationName()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the log file path for the specified application.
|
||||||
|
*
|
||||||
|
* @param Application $application The application instance for which the log file is to be retrieved.
|
||||||
|
* @return string The full path of the log file.
|
||||||
|
*/
|
||||||
|
private static function getLogFile(Application $application): string
|
||||||
|
{
|
||||||
|
$logging_directory = $application->getFileLoggingDirectory();
|
||||||
|
|
||||||
|
if(!file_exists($logging_directory))
|
||||||
|
{
|
||||||
|
if(!mkdir($logging_directory))
|
||||||
|
{
|
||||||
|
throw new RuntimeException(sprintf("Cannot write to %s due to insufficient permissions", $logging_directory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$logging_file = $logging_directory . DIRECTORY_SEPARATOR . Utilities::sanitizeFileName($application->getApplicationName()) . '-' . date('Y-m-d') . '.log';
|
||||||
|
|
||||||
|
if(!file_exists($logging_file) && !@touch($logging_file))
|
||||||
|
{
|
||||||
|
throw new RuntimeException(sprintf("Cannot write to %s due to insufficient permissions", $logging_file));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $logging_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the current timestamp formatted as "yd/m/y H:i".
|
||||||
|
*
|
||||||
|
* @return string The formatted current timestamp.
|
||||||
|
*/
|
||||||
|
private static function getTimestamp(): string
|
||||||
|
{
|
||||||
|
return date('yd/m/y H:i');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a detailed string representation of a given Throwable object, including its message, code,
|
||||||
|
* file, line of occurrence, stack trace, and any previous exceptions.
|
||||||
|
*
|
||||||
|
* @param Throwable|null $exception The throwable object to process. If null, an empty string is returned.
|
||||||
|
* @return string A detailed string representation of the throwable object.
|
||||||
|
*/
|
||||||
|
private static function outException(?Throwable $exception=null): string
|
||||||
|
{
|
||||||
|
if($exception === null)
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = '';
|
||||||
|
$trace_header = $exception->getFile() . ':' . $exception->getLine();
|
||||||
|
$trace_error = 'error: ';
|
||||||
|
|
||||||
|
$output .= $trace_header . ' ' . $trace_error . $exception->getMessage() . PHP_EOL;
|
||||||
|
$output .= sprintf('Error code: %s', $exception->getCode() . PHP_EOL);
|
||||||
|
$trace = $exception->getTrace();
|
||||||
|
|
||||||
|
if(count($trace) > 1)
|
||||||
|
{
|
||||||
|
$output .= 'Stack Trace:' . PHP_EOL;
|
||||||
|
foreach($trace as $item)
|
||||||
|
{
|
||||||
|
if(isset($item['file']) && isset($item['line']))
|
||||||
|
{
|
||||||
|
$output .= ' - ' . $item['file'] . ':' . $item['line'] . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($exception->getPrevious() !== null)
|
||||||
|
{
|
||||||
|
$output .= 'Previous Exception:' . PHP_EOL;
|
||||||
|
$output .= self::outException($exception->getPrevious());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
20
src/LogLib/Interfaces/LogHandlerInterface.php
Normal file
20
src/LogLib/Interfaces/LogHandlerInterface.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib\Interfaces;
|
||||||
|
|
||||||
|
use LogLib\Exceptions\LoggingException;
|
||||||
|
use LogLib\Objects\Application;
|
||||||
|
use LogLib\Objects\Event;
|
||||||
|
|
||||||
|
interface LogHandlerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Outputs the event details based on the given options.
|
||||||
|
*
|
||||||
|
* @param Application $application The options used to configure the output
|
||||||
|
* @param Event $event The event to be output
|
||||||
|
* @return void
|
||||||
|
* @throws LoggingException If an error occurs while handling the event
|
||||||
|
*/
|
||||||
|
public static function handle(Application $application, Event $event): void;
|
||||||
|
}
|
|
@ -4,40 +4,48 @@
|
||||||
|
|
||||||
namespace LogLib;
|
namespace LogLib;
|
||||||
|
|
||||||
|
use ErrorException;
|
||||||
|
use Exception;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use LogLib\Abstracts\LevelType;
|
|
||||||
use LogLib\Classes\Console;
|
|
||||||
use LogLib\Classes\Utilities;
|
use LogLib\Classes\Utilities;
|
||||||
use LogLib\Classes\Validate;
|
use LogLib\Enums\LogLevel;
|
||||||
|
use LogLib\Objects\Application;
|
||||||
use LogLib\Objects\Event;
|
use LogLib\Objects\Event;
|
||||||
use LogLib\Objects\Options;
|
|
||||||
use LogLib\Objects\RuntimeOptions;
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class Log
|
class Log
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Options[]
|
* @var Application[]|null
|
||||||
*/
|
*/
|
||||||
private static $Applications;
|
private static $applications;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var RuntimeOptions
|
|
||||||
*/
|
|
||||||
private static $RuntimeOptions;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a new application logger
|
* Registers a new application logger
|
||||||
*
|
*
|
||||||
* @param Options $options The options for the application
|
* @param Application $application The options for the application
|
||||||
|
* @param bool $overwrite
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function register(Options $options): bool
|
public static function register(Application $application, bool $overwrite=false): bool
|
||||||
{
|
{
|
||||||
if(self::isRegistered($options->getApplicationName()))
|
if(self::isRegistered($application->getApplicationName()))
|
||||||
return false;
|
{
|
||||||
|
if($overwrite)
|
||||||
|
{
|
||||||
|
self::$applications[$application->getApplicationName()] = $application;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
self::$Applications[$options->getApplicationName()] = $options;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(self::$applications === null)
|
||||||
|
{
|
||||||
|
self::$applications = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$applications[$application->getApplicationName()] = $application;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +57,15 @@
|
||||||
*/
|
*/
|
||||||
public static function unregister(string $application): void
|
public static function unregister(string $application): void
|
||||||
{
|
{
|
||||||
if(isset(self::$Applications[$application]))
|
if(self::$applications === null)
|
||||||
unset(self::$Applications[$application]);
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset(self::$applications[$application]))
|
||||||
|
{
|
||||||
|
unset(self::$applications[$application]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,64 +76,65 @@
|
||||||
*/
|
*/
|
||||||
private static function isRegistered(string $application): bool
|
private static function isRegistered(string $application): bool
|
||||||
{
|
{
|
||||||
return isset(self::$Applications[$application]);
|
return isset(self::$applications[$application]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $application
|
* Retrieves the application options. If the application is not registered, it optionally creates and registers a new one.
|
||||||
* @return Options
|
*
|
||||||
|
* @param string $application The name of the application.
|
||||||
|
* @param bool $create (Optional) Whether to create the application if it is not registered. Default is true.
|
||||||
|
* @return Application The options for the specified application.
|
||||||
*/
|
*/
|
||||||
public static function getApplication(string $application): Options
|
public static function getApplication(string $application, bool $create=true): Application
|
||||||
{
|
{
|
||||||
if(!self::isRegistered($application))
|
if(!self::isRegistered($application))
|
||||||
|
{
|
||||||
|
if(!$create)
|
||||||
|
{
|
||||||
throw new InvalidArgumentException("The application '$application' is not registered");
|
throw new InvalidArgumentException("The application '$application' is not registered");
|
||||||
|
}
|
||||||
|
|
||||||
return self::$Applications[$application];
|
self::register(new Application($application));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$applications[$application];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $application_name The name of the application
|
* Logs a message with a specified application name, level, optional message, and optional throwable.
|
||||||
* @return Options The options for the application
|
*
|
||||||
*/
|
* @param string|null $application_name The name of the application
|
||||||
public static function getOptions(string $application_name): Options
|
* @param LogLevel $level The level type of the log (default is LevelType::INFO)
|
||||||
{
|
* @param string|null $message The message of the log event
|
||||||
if(!self::isRegistered($application_name))
|
|
||||||
{
|
|
||||||
self::register(new Options($application_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$Applications[$application_name];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $application_name The name of the application
|
|
||||||
* @param string $level The level of the event
|
|
||||||
* @param string|null $message The message of the event
|
|
||||||
* @param Throwable|null $throwable The exception that was thrown, if any
|
* @param Throwable|null $throwable The exception that was thrown, if any
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private static function log(string $application_name, string $level=LevelType::Info, ?string $message=null, ?Throwable $throwable=null): void
|
private static function log(?string $application_name, LogLevel $level=LogLevel::INFO, ?string $message=null, ?Throwable $throwable=null): void
|
||||||
{
|
{
|
||||||
$application = self::getOptions($application_name);
|
$application = self::getApplication($application_name);
|
||||||
|
|
||||||
if(!Validate::checkLevelType($level, self::getRuntimeOptions()->getLogLevel()))
|
if($message === null)
|
||||||
return;
|
{
|
||||||
|
|
||||||
if($message == null)
|
|
||||||
throw new InvalidArgumentException('Message cannot be null');
|
throw new InvalidArgumentException('Message cannot be null');
|
||||||
if($level == null || !Validate::levelType($level))
|
}
|
||||||
throw new InvalidArgumentException('Invalid logging level');
|
|
||||||
|
|
||||||
$event = new Event();
|
$event = new Event($message, $level, $throwable);
|
||||||
$event->Level = $level;
|
|
||||||
$event->Message = $message;
|
|
||||||
$event->Exception = $throwable;
|
|
||||||
|
|
||||||
if($event->getBacktrace() == null)
|
if($event->getBacktrace() === null)
|
||||||
|
{
|
||||||
$event->setBacktrace(Utilities::getBacktrace());
|
$event->setBacktrace(Utilities::getBacktrace());
|
||||||
|
}
|
||||||
|
|
||||||
if(self::getRuntimeOptions()->isConsoleOutput())
|
if($application->isConsoleLoggingEnabled())
|
||||||
Console::out($application, $event);
|
{
|
||||||
|
$application->getConsoleLoggingHandler()::handle($application, $event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($application->isFileLoggingEnabled())
|
||||||
|
{
|
||||||
|
$application->getFileLoggingHandler()::handle($application, $event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,7 +144,7 @@
|
||||||
*/
|
*/
|
||||||
public static function info(string $application_name, string $message): void
|
public static function info(string $application_name, string $message): void
|
||||||
{
|
{
|
||||||
self::log($application_name, LevelType::Info, $message);
|
self::log($application_name, LogLevel::INFO, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,7 +154,7 @@
|
||||||
*/
|
*/
|
||||||
public static function verbose(string $application_name, string $message): void
|
public static function verbose(string $application_name, string $message): void
|
||||||
{
|
{
|
||||||
self::log($application_name, LevelType::Verbose, $message);
|
self::log($application_name, LogLevel::VERBOSE, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,74 +164,65 @@
|
||||||
*/
|
*/
|
||||||
public static function debug(string $application_name, string $message): void
|
public static function debug(string $application_name, string $message): void
|
||||||
{
|
{
|
||||||
self::log($application_name, LevelType::Debug, $message);
|
self::log($application_name, LogLevel::DEBUG, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $application_name The name of the application
|
* Logs a warning message.
|
||||||
* @param string $message The message of the event
|
*
|
||||||
* @param Throwable|null $throwable The exception that was thrown, if any
|
* @param string $application_name The name of the application.
|
||||||
|
* @param string $message The warning message to log.
|
||||||
|
* @param Throwable|null $throwable (Optional) The throwable object associated with the warning.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function warning(string $application_name, string $message, ?Throwable $throwable=null): void
|
public static function warning(string $application_name, string $message, ?Throwable $throwable=null): void
|
||||||
{
|
{
|
||||||
self::log($application_name, LevelType::Warning, $message, $throwable);
|
self::log($application_name, LogLevel::WARNING, $message, $throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $application_name The name of the application
|
* Logs an error message.
|
||||||
* @param string $message The message of the event
|
*
|
||||||
* @param Throwable|null $throwable The exception that was thrown, if any
|
* @param string $application_name The name of the application.
|
||||||
|
* @param string $message The error message.
|
||||||
|
* @param Throwable|null $throwable The optional throwable object associated with the error.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function error(string $application_name, string $message, ?Throwable $throwable=null): void
|
public static function error(string $application_name, string $message, ?Throwable $throwable=null): void
|
||||||
{
|
{
|
||||||
self::log($application_name, LevelType::Error, $message, $throwable);
|
self::log($application_name, LogLevel::ERROR, $message, $throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $application_name The name of the application
|
* Logs a fatal message.
|
||||||
* @param string $message The message of the event
|
*
|
||||||
* @param Throwable|null $throwable The exception that was thrown, if any
|
* @param string $application_name The name of the application.
|
||||||
|
* @param string $message The fatal message to log.
|
||||||
|
* @param Throwable|null $throwable (Optional) The throwable object associated with the fatal message.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function fatal(string $application_name, string $message, ?Throwable $throwable=null): void
|
public static function fatal(string $application_name, string $message, ?Throwable $throwable=null): void
|
||||||
{
|
{
|
||||||
self::log($application_name, LevelType::Fatal, $message, $throwable);
|
self::log($application_name, LogLevel::FATAL, $message, $throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers LogLib as a exception handler
|
* Registers an exception handler that logs any uncaught exceptions as errors.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function registerExceptionHandler(): void
|
public static function registerExceptionHandler(): void
|
||||||
{
|
{
|
||||||
set_exception_handler(function(Throwable $throwable) {
|
Runtime::registerExceptionHandler();
|
||||||
self::error('Runtime', $throwable->getMessage(), $throwable);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters all applications
|
* Unregisters the currently registered exception handler.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function unregisterExceptionHandler(): void
|
public static function unregisterExceptionHandler(): void
|
||||||
{
|
{
|
||||||
set_exception_handler(null);
|
Runtime::unregisterExceptionHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return RuntimeOptions
|
|
||||||
*/
|
|
||||||
public static function getRuntimeOptions(): RuntimeOptions
|
|
||||||
{
|
|
||||||
if(self::$RuntimeOptions == null)
|
|
||||||
{
|
|
||||||
self::$RuntimeOptions = new RuntimeOptions();
|
|
||||||
}
|
|
||||||
return self::$RuntimeOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
86
src/LogLib/Logger.php
Normal file
86
src/LogLib/Logger.php
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib;
|
||||||
|
|
||||||
|
use LogLib\Objects\Application;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class Logger extends Application
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function __construct(string $applicationName)
|
||||||
|
{
|
||||||
|
parent::__construct($applicationName);
|
||||||
|
Log::register($this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an informational message.
|
||||||
|
*
|
||||||
|
* @param string $message The message to log.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function info(string $message): void
|
||||||
|
{
|
||||||
|
Log::info($this->getApplicationName(), $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a verbose message with the application name.
|
||||||
|
*
|
||||||
|
* @param string $message The message to be logged.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function verbose(string $message): void
|
||||||
|
{
|
||||||
|
Log::verbose($this->getApplicationName(), $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a debug message.
|
||||||
|
*
|
||||||
|
* @param string $message The debug message to log.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function debug(string $message): void
|
||||||
|
{
|
||||||
|
Log::debug($this->getApplicationName(), $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a warning message with the application name.
|
||||||
|
*
|
||||||
|
* @param string $message The warning message to log.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function warning(string $message): void
|
||||||
|
{
|
||||||
|
Log::warning($this->getApplicationName(), $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an error message with an optional throwable instance.
|
||||||
|
*
|
||||||
|
* @param string $message The error message to be logged.
|
||||||
|
* @param Throwable|null $throwable An optional throwable instance to be logged along with the error message.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function error(string $message, ?Throwable $throwable=null): void
|
||||||
|
{
|
||||||
|
Log::error($this->getApplicationName(), $message, $throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a fatal error message along with an optional throwable.
|
||||||
|
*
|
||||||
|
* @param string $message The fatal error message to log.
|
||||||
|
* @param Throwable|null $throwable Optional throwable associated with the fatal error.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function fatal(string $message, ?Throwable $throwable=null): void
|
||||||
|
{
|
||||||
|
Log::fatal($this->getApplicationName(), $message, $throwable);
|
||||||
|
}
|
||||||
|
}
|
248
src/LogLib/Objects/Application.php
Normal file
248
src/LogLib/Objects/Application.php
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib\Objects;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use LogLib\Classes\Utilities;
|
||||||
|
use LogLib\Enums\LogLevel;
|
||||||
|
use LogLib\Handlers\ConsoleLogging;
|
||||||
|
use LogLib\Handlers\FileLogging;
|
||||||
|
use LogLib\Interfaces\LogHandlerInterface;
|
||||||
|
|
||||||
|
class Application
|
||||||
|
{
|
||||||
|
private string $applicationName;
|
||||||
|
private bool $handleExceptions;
|
||||||
|
private bool $consoleLoggingEnabled;
|
||||||
|
private string $consoleLoggingHandler;
|
||||||
|
private LogLevel $consoleLoggingLevel;
|
||||||
|
private bool $fileLoggingEnabled;
|
||||||
|
private string $fileLoggingHandler;
|
||||||
|
private LogLevel $fileLoggingLevel;
|
||||||
|
private string $fileLoggingDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for initializing the application logging and exception handling.
|
||||||
|
*
|
||||||
|
* @param string $applicationName The name of the application.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(string $applicationName)
|
||||||
|
{
|
||||||
|
$this->applicationName = $applicationName;
|
||||||
|
$this->handleExceptions = true;
|
||||||
|
$this->consoleLoggingEnabled = Utilities::getConsoleLoggingEnabled();
|
||||||
|
$this->consoleLoggingHandler = ConsoleLogging::class;
|
||||||
|
$this->consoleLoggingLevel = Utilities::getConsoleLoggingLevel();
|
||||||
|
$this->fileLoggingEnabled = Utilities::getFileLoggingEnabled();
|
||||||
|
$this->fileLoggingHandler = FileLogging::class;
|
||||||
|
$this->fileLoggingLevel = Utilities::getFileLoggingLevel();
|
||||||
|
$this->fileLoggingDirectory = Utilities::getFileLoggingDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getApplicationName(): string
|
||||||
|
{
|
||||||
|
return $this->applicationName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if exceptions are being handled.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isHandleExceptions(): bool
|
||||||
|
{
|
||||||
|
return $this->handleExceptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the flag to handle exceptions.
|
||||||
|
*
|
||||||
|
* @param bool $handleExceptions Flag indicating whether to handle exceptions.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setHandleExceptions(bool $handleExceptions): void
|
||||||
|
{
|
||||||
|
$this->handleExceptions = $handleExceptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if console logging is enabled.
|
||||||
|
*
|
||||||
|
* @return bool True if console logging is enabled, false otherwise.
|
||||||
|
*/
|
||||||
|
public function isConsoleLoggingEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->consoleLoggingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param bool $consoleLoggingEnabled Indicates whether console logging is enabled.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setConsoleLoggingEnabled(bool $consoleLoggingEnabled): void
|
||||||
|
{
|
||||||
|
$this->consoleLoggingEnabled = $consoleLoggingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current console logging handler.
|
||||||
|
*
|
||||||
|
* @return LogHandlerInterface|string The console logging handler currently set.
|
||||||
|
*/
|
||||||
|
public function getConsoleLoggingHandler(): LogHandlerInterface|string
|
||||||
|
{
|
||||||
|
return new $this->consoleLoggingHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the console logging handler.
|
||||||
|
*
|
||||||
|
* @param LogHandlerInterface|string $consoleLoggingHandler The console logging handler to set.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setConsoleLoggingHandler(LogHandlerInterface|string $consoleLoggingHandler): void
|
||||||
|
{
|
||||||
|
if($consoleLoggingHandler instanceof LogHandlerInterface)
|
||||||
|
{
|
||||||
|
$this->consoleLoggingHandler = get_class($consoleLoggingHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!class_exists($consoleLoggingHandler))
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException("The class $consoleLoggingHandler does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!in_array(LogHandlerInterface::class, class_implements($consoleLoggingHandler)))
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException("The class $consoleLoggingHandler does not implement LogHandlerInterface.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->consoleLoggingHandler = $consoleLoggingHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current console logging level.
|
||||||
|
*
|
||||||
|
* @return LogLevel The current logging level for the console.
|
||||||
|
*/
|
||||||
|
public function getConsoleLoggingLevel(): LogLevel
|
||||||
|
{
|
||||||
|
return $this->consoleLoggingLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the logging level for console output.
|
||||||
|
*
|
||||||
|
* @param LogLevel $consoleLoggingLevel The logging level to set for console output.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setConsoleLoggingLevel(LogLevel $consoleLoggingLevel): void
|
||||||
|
{
|
||||||
|
$this->consoleLoggingLevel = $consoleLoggingLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if file logging is enabled.
|
||||||
|
*
|
||||||
|
* @return bool Returns true if file logging is enabled, false otherwise.
|
||||||
|
*/
|
||||||
|
public function isFileLoggingEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->fileLoggingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables file logging.
|
||||||
|
*
|
||||||
|
* @param bool $fileLoggingEnabled True to enable file logging, false to disable.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setFileLoggingEnabled(bool $fileLoggingEnabled): void
|
||||||
|
{
|
||||||
|
$this->fileLoggingEnabled = $fileLoggingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return LogHandlerInterface|string
|
||||||
|
*/
|
||||||
|
public function getFileLoggingHandler(): LogHandlerInterface|string
|
||||||
|
{
|
||||||
|
return $this->fileLoggingHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the file logging handler.
|
||||||
|
*
|
||||||
|
* @param string $fileLoggingHandler The file logging handler to be set.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setFileLoggingHandler(string $fileLoggingHandler): void
|
||||||
|
{
|
||||||
|
if($fileLoggingHandler instanceof LogHandlerInterface)
|
||||||
|
{
|
||||||
|
$this->consoleLoggingHandler = get_class($fileLoggingHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!class_exists($fileLoggingHandler))
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException("The class $fileLoggingHandler does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!in_array(LogHandlerInterface::class, class_implements($fileLoggingHandler)))
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException("The class $fileLoggingHandler does not implement LogHandlerInterface.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->consoleLoggingHandler = $fileLoggingHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the logging level for file outputs.
|
||||||
|
*
|
||||||
|
* @return LogLevel The current file logging level.
|
||||||
|
*/
|
||||||
|
public function getFileLoggingLevel(): LogLevel
|
||||||
|
{
|
||||||
|
return $this->fileLoggingLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the logging level for file-based logging.
|
||||||
|
*
|
||||||
|
* @param LogLevel $fileLoggingLevel The logging level to set for file logging.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setFileLoggingLevel(LogLevel $fileLoggingLevel): void
|
||||||
|
{
|
||||||
|
$this->fileLoggingLevel = $fileLoggingLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the directory path for file logging.
|
||||||
|
*
|
||||||
|
* @return string The directory path where log files are stored.
|
||||||
|
*/
|
||||||
|
public function getFileLoggingDirectory(): string
|
||||||
|
{
|
||||||
|
return $this->fileLoggingDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the directory for file logging.
|
||||||
|
*
|
||||||
|
* @param string $fileLoggingDirectory The path to the directory where log files will be stored.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setFileLoggingDirectory(string $fileLoggingDirectory): void
|
||||||
|
{
|
||||||
|
$this->fileLoggingDirectory = $fileLoggingDirectory;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,174 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/** @noinspection PhpMissingFieldTypeInspection */
|
|
||||||
|
|
||||||
namespace LogLib\Objects;
|
|
||||||
|
|
||||||
class Backtrace
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The function name of the backtrace
|
|
||||||
*
|
|
||||||
* @var string|null
|
|
||||||
* @property_name function
|
|
||||||
*/
|
|
||||||
private $Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The line number of the backtrace
|
|
||||||
*
|
|
||||||
* @var int|null
|
|
||||||
* @property_name line
|
|
||||||
*/
|
|
||||||
private $Line;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The file name of the backtrace
|
|
||||||
*
|
|
||||||
* @var string|null
|
|
||||||
* @property_name file
|
|
||||||
*/
|
|
||||||
private $File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class name, if any, of the backtrace
|
|
||||||
*
|
|
||||||
* @var string|null
|
|
||||||
* @property_name class
|
|
||||||
*/
|
|
||||||
private $Class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current call type. If a method call, "->" is returned.
|
|
||||||
* If a static method call, "::" is returned. If a function call,
|
|
||||||
* nothing is returned.
|
|
||||||
*
|
|
||||||
* @see CallType
|
|
||||||
* @var string|null
|
|
||||||
* @property_name type
|
|
||||||
*/
|
|
||||||
private $Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If inside a function, this lists the functions arguments. If inside
|
|
||||||
* an included file, this lists the included file name(s).
|
|
||||||
*
|
|
||||||
* @var array|null
|
|
||||||
* @property_name args
|
|
||||||
*/
|
|
||||||
private $Args;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public Constructor
|
|
||||||
*
|
|
||||||
* @param array|null $backtrace
|
|
||||||
*/
|
|
||||||
public function __construct(?array $backtrace=null)
|
|
||||||
{
|
|
||||||
if($backtrace === null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
$this->Function = $backtrace['function'] ?? null;
|
|
||||||
$this->Line = $backtrace['line'] ?? null;
|
|
||||||
$this->File = $backtrace['file'] ?? null;
|
|
||||||
$this->Class = $backtrace['class'] ?? null;
|
|
||||||
$this->Type = $backtrace['type'] ?? null;
|
|
||||||
$this->Args = $backtrace['args'] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getFunction(): ?string
|
|
||||||
{
|
|
||||||
return $this->Function;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|null $Function
|
|
||||||
*/
|
|
||||||
public function setFunction(?string $Function): void
|
|
||||||
{
|
|
||||||
$this->Function = $Function;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int|null
|
|
||||||
*/
|
|
||||||
public function getLine(): ?int
|
|
||||||
{
|
|
||||||
return $this->Line;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int|null $Line
|
|
||||||
*/
|
|
||||||
public function setLine(?int $Line): void
|
|
||||||
{
|
|
||||||
$this->Line = $Line;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getFile(): ?string
|
|
||||||
{
|
|
||||||
return $this->File;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|null $File
|
|
||||||
*/
|
|
||||||
public function setFile(?string $File): void
|
|
||||||
{
|
|
||||||
$this->File = $File;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getClass(): ?string
|
|
||||||
{
|
|
||||||
return $this->Class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|null $Class
|
|
||||||
*/
|
|
||||||
public function setClass(?string $Class): void
|
|
||||||
{
|
|
||||||
$this->Class = $Class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getType(): ?string
|
|
||||||
{
|
|
||||||
return $this->Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|null $Type
|
|
||||||
*/
|
|
||||||
public function setType(?string $Type): void
|
|
||||||
{
|
|
||||||
$this->Type = $Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array|null
|
|
||||||
*/
|
|
||||||
public function getArgs(): ?array
|
|
||||||
{
|
|
||||||
return $this->Args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array|null $Args
|
|
||||||
*/
|
|
||||||
public function setArgs(?array $Args): void
|
|
||||||
{
|
|
||||||
$this->Args = $Args;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,54 +4,77 @@
|
||||||
|
|
||||||
namespace LogLib\Objects;
|
namespace LogLib\Objects;
|
||||||
|
|
||||||
use LogLib\Abstracts\LevelType;
|
|
||||||
use LogLib\Classes\Utilities;
|
use LogLib\Classes\Utilities;
|
||||||
|
use LogLib\Enums\LogLevel;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class Event
|
class Event
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The level of the event
|
* @var LogLevel
|
||||||
*
|
|
||||||
* @see LevelType
|
|
||||||
* @var string
|
|
||||||
* @property_name level
|
|
||||||
*/
|
*/
|
||||||
public $Level;
|
private $level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Unix Timestamp of when the event was created
|
* @var array|null
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
private $Timestamp;
|
private $backtrace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of backtraces, if any, that were created when the event was created
|
|
||||||
*
|
|
||||||
* @var Backtrace[]|null
|
|
||||||
*/
|
|
||||||
private $Backtrace;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The exception that was thrown, if any
|
|
||||||
*
|
|
||||||
* @var Throwable|null
|
* @var Throwable|null
|
||||||
*/
|
*/
|
||||||
public $Exception;
|
private $exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The message of the event
|
|
||||||
*
|
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $Message;
|
private $message;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public Constructor
|
* Event constructor.
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
* @param LogLevel $level
|
||||||
|
* @param Throwable|null $exception
|
||||||
|
* @param array|null $backtrace
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(string $message, LogLevel $level, ?Throwable $exception=null, ?array $backtrace=null)
|
||||||
{
|
{
|
||||||
$this->Timestamp = date('c');
|
$this->message = $message;
|
||||||
|
$this->level = $level;
|
||||||
|
$this->exception = $exception;
|
||||||
|
$this->backtrace = $backtrace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the level of the event
|
||||||
|
*
|
||||||
|
* @return LogLevel
|
||||||
|
* @see LogLevel
|
||||||
|
*/
|
||||||
|
public function getLevel(): LogLevel
|
||||||
|
{
|
||||||
|
return $this->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the message of the event
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMessage(): string
|
||||||
|
{
|
||||||
|
return $this->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional. Returns the exception to the event
|
||||||
|
*
|
||||||
|
* @return Throwable|null
|
||||||
|
*/
|
||||||
|
public function getException(): ?Throwable
|
||||||
|
{
|
||||||
|
return $this->exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,31 +85,26 @@
|
||||||
*/
|
*/
|
||||||
public function setException(Throwable $e): void
|
public function setException(Throwable $e): void
|
||||||
{
|
{
|
||||||
$this->Exception = Utilities::exceptionToArray($e);
|
$this->exception = Utilities::exceptionToArray($e);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getTimestamp(): string
|
|
||||||
{
|
|
||||||
return $this->Timestamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the backtrace of the event
|
||||||
|
*
|
||||||
* @return array|null
|
* @return array|null
|
||||||
*/
|
*/
|
||||||
public function getBacktrace(): ?array
|
public function getBacktrace(): ?array
|
||||||
{
|
{
|
||||||
return $this->Backtrace;
|
return $this->backtrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array|null $Backtrace
|
* Sets the backtrace of the event
|
||||||
|
*
|
||||||
|
* @param array|null $backtrace
|
||||||
*/
|
*/
|
||||||
public function setBacktrace(?array $Backtrace): void
|
public function setBacktrace(?array $backtrace): void
|
||||||
{
|
{
|
||||||
$this->Backtrace = $Backtrace;
|
$this->backtrace = $backtrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,36 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/** @noinspection PhpMissingFieldTypeInspection */
|
|
||||||
|
|
||||||
namespace LogLib\Objects;
|
|
||||||
|
|
||||||
|
|
||||||
class Options
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The name of the application
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
* @property_name application_name
|
|
||||||
*/
|
|
||||||
private $ApplicationName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options constructor.
|
|
||||||
*/
|
|
||||||
public function __construct(string $application_name)
|
|
||||||
{
|
|
||||||
$this->ApplicationName = $application_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the Application
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getApplicationName(): string
|
|
||||||
{
|
|
||||||
return $this->ApplicationName;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/** @noinspection PhpMissingFieldTypeInspection */
|
|
||||||
|
|
||||||
namespace LogLib\Objects;
|
|
||||||
|
|
||||||
use InvalidArgumentException;
|
|
||||||
use LogLib\Abstracts\LevelType;
|
|
||||||
use LogLib\Classes\Utilities;
|
|
||||||
|
|
||||||
class RuntimeOptions
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Indicates if the console output is enabled
|
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
* @property_name console_output
|
|
||||||
*/
|
|
||||||
private $ConsoleOutput;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates if ANSI colors should be used in the console output
|
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
* @property_name display_ansi
|
|
||||||
*/
|
|
||||||
private $DisplayAnsi;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates if LogLib should handle uncaught exceptions
|
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
* @property_name handle_exceptions
|
|
||||||
*/
|
|
||||||
private $HandleExceptions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current log level
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
* @see LevelType
|
|
||||||
*/
|
|
||||||
private $LogLevel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public Constructor
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->ConsoleOutput = Utilities::runningInCli();
|
|
||||||
$this->DisplayAnsi = Utilities::getDisplayAnsi();
|
|
||||||
$this->HandleExceptions = true;
|
|
||||||
$this->LogLevel = Utilities::getLogLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isConsoleOutput(): bool
|
|
||||||
{
|
|
||||||
return $this->ConsoleOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param bool $ConsoleOutput
|
|
||||||
*/
|
|
||||||
public function setConsoleOutput(bool $ConsoleOutput): void
|
|
||||||
{
|
|
||||||
$this->ConsoleOutput = $ConsoleOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isDisplayAnsi(): bool
|
|
||||||
{
|
|
||||||
return $this->DisplayAnsi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param bool $DisplayAnsi
|
|
||||||
*/
|
|
||||||
public function setDisplayAnsi(bool $DisplayAnsi): void
|
|
||||||
{
|
|
||||||
$this->DisplayAnsi = $DisplayAnsi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isHandleExceptions(): bool
|
|
||||||
{
|
|
||||||
return $this->HandleExceptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param bool $HandleExceptions
|
|
||||||
*/
|
|
||||||
public function setHandleExceptions(bool $HandleExceptions): void
|
|
||||||
{
|
|
||||||
$this->HandleExceptions = $HandleExceptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getLogLevel(): int
|
|
||||||
{
|
|
||||||
return $this->LogLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $LogLevel
|
|
||||||
*/
|
|
||||||
public function setLogLevel(int $LogLevel): void
|
|
||||||
{
|
|
||||||
$this->LogLevel = $LogLevel;
|
|
||||||
}
|
|
||||||
}
|
|
124
src/LogLib/Runtime.php
Normal file
124
src/LogLib/Runtime.php
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib;
|
||||||
|
|
||||||
|
use ErrorException;
|
||||||
|
use Exception;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class Runtime
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Registers an exception handler that logs any uncaught exceptions as errors.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function registerExceptionHandler(): void
|
||||||
|
{
|
||||||
|
set_exception_handler([__CLASS__, 'exceptionHandler']);
|
||||||
|
set_error_handler([__CLASS__, 'errorHandler']);
|
||||||
|
register_shutdown_function([__CLASS__, 'shutdownHandler']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles uncaught exceptions by logging them with a fatal error level.
|
||||||
|
*
|
||||||
|
* @param Throwable $throwable The exception or error that was thrown.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function exceptionHandler(Throwable $throwable): void
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log::Fatal('Runtime', $throwable->getMessage(), $throwable);
|
||||||
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles PHP errors by converting them to exceptions and logging appropriately.
|
||||||
|
*
|
||||||
|
* @param int $errno The level of the error raised.
|
||||||
|
* @param string $errstr The error message.
|
||||||
|
* @param string $errfile The filename that the error was raised in.
|
||||||
|
* @param int $errline The line number the error was raised at.
|
||||||
|
* @return bool True to prevent PHP's internal error handler from being invoked.
|
||||||
|
*/
|
||||||
|
public static function errorHandler(int $errno, string $errstr, string $errfile = '', int $errline = 0): bool
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Convert error to exception for consistent handling
|
||||||
|
$exception = new ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||||
|
|
||||||
|
// Handle different error types
|
||||||
|
switch ($errno)
|
||||||
|
{
|
||||||
|
case E_ERROR:
|
||||||
|
case E_PARSE:
|
||||||
|
case E_CORE_ERROR:
|
||||||
|
case E_COMPILE_ERROR:
|
||||||
|
case E_USER_ERROR:
|
||||||
|
Log::error('Runtime', $errstr, $exception);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case E_USER_DEPRECATED:
|
||||||
|
case E_DEPRECATED:
|
||||||
|
case E_USER_NOTICE:
|
||||||
|
case E_NOTICE:
|
||||||
|
case E_USER_WARNING:
|
||||||
|
case E_WARNING:
|
||||||
|
default:
|
||||||
|
Log::warning('Runtime', $errstr, $exception);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true to prevent PHP's internal error handler
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles script shutdown by checking for any fatal errors and logging them.
|
||||||
|
*
|
||||||
|
* This method is designed to be registered with the `register_shutdown_function`,
|
||||||
|
* and it inspects the last error that occurred using `error_get_last`. If a fatal
|
||||||
|
* error is detected, it logs the error details.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function shutdownHandler(): void
|
||||||
|
{
|
||||||
|
$error = error_get_last();
|
||||||
|
|
||||||
|
if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR]))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$exception = new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']);
|
||||||
|
Log::error('Fatal Error', $error['message'], $exception);
|
||||||
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters the currently registered exception handler.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function unregisterExceptionHandler(): void
|
||||||
|
{
|
||||||
|
set_exception_handler(null);
|
||||||
|
}
|
||||||
|
}
|
74
tests/LogLib/LogTest.php
Normal file
74
tests/LogLib/LogTest.php
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace LogLib;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class LogTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function testDebug()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInfo()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetRuntimeOptions()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetOptions()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetApplication()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnregisterExceptionHandler()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUnregister()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWarning()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testError()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFatal()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterExceptionHandler()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testVerbose()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegister()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use LogLib\Abstracts\LevelType;
|
|
||||||
use LogLib\Log;
|
use LogLib\Log;
|
||||||
use LogLib\Objects\Options;
|
use LogLib\Objects\Options;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use LogLib\Abstracts\LevelType;
|
|
||||||
use LogLib\Log;
|
use LogLib\Log;
|
||||||
use LogLib\Objects\Options;
|
use LogLib\Objects\Options;
|
||||||
|
|
||||||
|
@ -16,3 +15,60 @@
|
||||||
Log::warning('net.nosial.optslib', 'This is a warning message');
|
Log::warning('net.nosial.optslib', 'This is a warning message');
|
||||||
Log::error('net.nosial.optslib', 'This is an error message');
|
Log::error('net.nosial.optslib', 'This is an error message');
|
||||||
Log::fatal('net.nosial.optslib', 'This is a fatal message');
|
Log::fatal('net.nosial.optslib', 'This is a fatal message');
|
||||||
|
|
||||||
|
|
||||||
|
class test
|
||||||
|
{
|
||||||
|
public function testLogging(): void
|
||||||
|
{
|
||||||
|
Log::debug('net.nosial.optslib', 'This is a debug message');
|
||||||
|
Log::verbose('net.nosial.optslib', 'This is a verbose message');
|
||||||
|
Log::info('net.nosial.optslib', 'This is an info message');
|
||||||
|
Log::warning('net.nosial.optslib', 'This is a warning message');
|
||||||
|
Log::error('net.nosial.optslib', 'This is an error message');
|
||||||
|
Log::fatal('net.nosial.optslib', 'This is a fatal message');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$test = new test();
|
||||||
|
$test->testLogging();
|
||||||
|
|
||||||
|
eval('\LogLib\Log::debug(\'net.nosial.optslib\', \'This is a debug message\');');
|
||||||
|
eval('\LogLib\Log::verbose(\'net.nosial.optslib\', \'This is a verbose message\');');
|
||||||
|
|
||||||
|
$callable = static function()
|
||||||
|
{
|
||||||
|
Log::info('net.nosial.optslib', 'This is an info message');
|
||||||
|
Log::warning('net.nosial.optslib', 'This is a warning message');
|
||||||
|
Log::error('net.nosial.optslib', 'This is an error message');
|
||||||
|
Log::fatal('net.nosial.optslib', 'This is a fatal message');
|
||||||
|
};
|
||||||
|
|
||||||
|
$callable();
|
||||||
|
|
||||||
|
|
||||||
|
class test2
|
||||||
|
{
|
||||||
|
public function testEval(): void
|
||||||
|
{
|
||||||
|
eval('\LogLib\Log::debug(\'net.nosial.optslib\', \'This is a debug message\');');
|
||||||
|
eval('\LogLib\Log::verbose(\'net.nosial.optslib\', \'This is a verbose message\');');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCallable(): void
|
||||||
|
{
|
||||||
|
$b = static function()
|
||||||
|
{
|
||||||
|
Log::info('net.nosial.optslib', 'This is an info message');
|
||||||
|
Log::warning('net.nosial.optslib', 'This is a warning message');
|
||||||
|
Log::error('net.nosial.optslib', 'This is an error message');
|
||||||
|
Log::fatal('net.nosial.optslib', 'This is a fatal message');
|
||||||
|
};
|
||||||
|
|
||||||
|
$b();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$test2 = new test2();
|
||||||
|
$test2->testEval();
|
||||||
|
$test2->testCallable();
|
Loading…
Add table
Reference in a new issue