Compare commits
58 Commits
fd98d6d117
...
dc25a9cf68
Author | SHA1 | Date |
---|---|---|
Andrew Dolgov | dc25a9cf68 | |
Andrew Dolgov | a9d8fd8bdc | |
Andrew Dolgov | d43d6f7dff | |
Andrew Dolgov | a28d9582e8 | |
Andrew Dolgov | 718af52a1b | |
Chih-Hsuan Yen | d26309b1e5 | |
Andrew Dolgov | 3468317bd3 | |
defkev | af3e9eb4a0 | |
defkev | 5bfd18d3e6 | |
Andrew Dolgov | a4543de3ac | |
wn_ | b1187f0db6 | |
Andrew Dolgov | 11946f0148 | |
Andrew Dolgov | 3de09b44f2 | |
Andrew Dolgov | 0578bf8025 | |
Andrew Dolgov | 1e90feef0e | |
Andrew Dolgov | c314bd8742 | |
Andrew Dolgov | 103fdd5e60 | |
Andrew Dolgov | 7a54154d45 | |
Andrew Dolgov | 27bd226f2b | |
Andrew Dolgov | 15c9dbe270 | |
Andrew Dolgov | 2420feb91f | |
Andrew Dolgov | 8ccea1712e | |
Andrew Dolgov | f3f2e7d043 | |
Andrew Dolgov | 6920c44587 | |
Andrew Dolgov | 566d164053 | |
Andrew Dolgov | 06aabdf60b | |
Andrew Dolgov | 4e17fac8b7 | |
Andrew Dolgov | 7dc83961bd | |
Andrew Dolgov | b0fc248c05 | |
Andrew Dolgov | 6ec01203a1 | |
Andrew Dolgov | 44137342a6 | |
Andrew Dolgov | fd5e0f98c4 | |
Andrew Dolgov | e18295a364 | |
Andrew Dolgov | d68c736e47 | |
Andrew Dolgov | 6418157ccf | |
Andrew Dolgov | d7c070b22b | |
Andrew Dolgov | c1b3c99667 | |
Andrew Dolgov | 8f3646a9c9 | |
Andrew Dolgov | a37eab2610 | |
Andrew Dolgov | 431b8778ed | |
Andrew Dolgov | c4edc93182 | |
Andrew Dolgov | 028bb846d9 | |
Andrew Dolgov | 31ef788e02 | |
fox | ae27d51197 | |
Jan Pieter Kunst | a60c833ee4 | |
Andrew Dolgov | 0fcc2d1d66 | |
Andrew Dolgov | 152545b3c9 | |
Andrew Dolgov | 881f8805bd | |
Andrew Dolgov | 53bd56894d | |
Andrew Dolgov | af5c64045b | |
Andrew Dolgov | 0fcc715069 | |
Andrew Dolgov | fd684dae29 | |
Andrew Dolgov | 58450486a0 | |
Andrew Dolgov | 4a60652be9 | |
Andrew Dolgov | 521ac622e4 | |
Andrew Dolgov | f0e0f7d5f5 | |
fox | c2d8ba5973 | |
wn_ | 807f914338 |
|
@ -1,24 +1,36 @@
|
|||
FROM registry.fakecake.org/docker.io/alpine:3.17
|
||||
FROM registry.fakecake.org/docker.io/alpine:3.18
|
||||
EXPOSE 9000/tcp
|
||||
|
||||
ENV SCRIPT_ROOT=/opt/tt-rss
|
||||
ENV SRC_DIR=/src/tt-rss/
|
||||
|
||||
RUN apk add --no-cache dcron php81 php81-fpm php81-phar \
|
||||
php81-pdo php81-gd php81-pgsql php81-pdo_pgsql php81-xmlwriter \
|
||||
php81-mbstring php81-intl php81-xml php81-curl php81-simplexml \
|
||||
php81-session php81-tokenizer php81-dom php81-fileinfo php81-ctype \
|
||||
php81-json php81-iconv php81-pcntl php81-posix php81-zip php81-exif \
|
||||
php81-openssl git postgresql-client sudo php81-pecl-xdebug rsync tzdata && \
|
||||
sed -i 's/\(memory_limit =\) 128M/\1 256M/' /etc/php81/php.ini && \
|
||||
RUN apk add --no-cache dcron php82 php82-fpm php82-phar php82-sockets php82-pecl-apcu \
|
||||
php82-pdo php82-gd php82-pgsql php82-pdo_pgsql php82-xmlwriter php82-opcache \
|
||||
php82-mbstring php82-intl php82-xml php82-curl php82-simplexml \
|
||||
php82-session php82-tokenizer php82-dom php82-fileinfo php82-ctype \
|
||||
php82-json php82-iconv php82-pcntl php82-posix php82-zip php82-exif \
|
||||
php82-openssl git postgresql-client sudo php82-pecl-xdebug rsync tzdata && \
|
||||
sed -i 's/\(memory_limit =\) 128M/\1 256M/' /etc/php82/php.ini && \
|
||||
sed -i -e 's/^listen = 127.0.0.1:9000/listen = 9000/' \
|
||||
-e 's/;\(clear_env\) = .*/\1 = no/i' \
|
||||
-e 's/^\(user\|group\) = .*/\1 = app/i' \
|
||||
-e 's/;\(php_admin_value\[error_log\]\) = .*/\1 = \/tmp\/error.log/' \
|
||||
-e 's/;\(php_admin_flag\[log_errors\]\) = .*/\1 = on/' \
|
||||
/etc/php81/php-fpm.d/www.conf && \
|
||||
/etc/php82/php-fpm.d/www.conf && \
|
||||
mkdir -p /var/www ${SCRIPT_ROOT}/config.d
|
||||
|
||||
ARG CI_COMMIT_BRANCH
|
||||
ENV CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH}
|
||||
|
||||
ARG CI_COMMIT_SHORT_SHA
|
||||
ENV CI_COMMIT_SHORT_SHA=${CI_COMMIT_SHORT_SHA}
|
||||
|
||||
ARG CI_COMMIT_TIMESTAMP
|
||||
ENV CI_COMMIT_TIMESTAMP=${CI_COMMIT_TIMESTAMP}
|
||||
|
||||
ARG CI_COMMIT_SHA
|
||||
ENV CI_COMMIT_SHA=${CI_COMMIT_SHA}
|
||||
|
||||
ADD --chmod=0755 startup.sh ${SCRIPT_ROOT}
|
||||
ADD --chmod=0755 updater.sh ${SCRIPT_ROOT}
|
||||
ADD --chmod=0755 dcron.sh ${SCRIPT_ROOT}
|
||||
|
@ -29,13 +41,7 @@ ADD config.docker.php ${SCRIPT_ROOT}
|
|||
|
||||
COPY --from=app-src . ${SRC_DIR}
|
||||
|
||||
ARG ORIGIN_REPO_MAIN=https://git.tt-rss.org/fox/tt-rss.git
|
||||
ARG ORIGIN_REPO_XACCEL=https://git.tt-rss.org/fox/ttrss-nginx-xaccel.git
|
||||
ARG ORIGIN_COMMIT=
|
||||
|
||||
ENV ORIGIN_REPO_MAIN=${ORIGIN_REPO_MAIN}
|
||||
ENV ORIGIN_REPO_XACCEL=${ORIGIN_REPO_XACCEL}
|
||||
ENV ORIGIN_COMMIT=${ORIGIN_COMMIT}
|
||||
|
||||
RUN git clone --depth=1 ${ORIGIN_REPO_XACCEL} ${SRC_DIR}/plugins.local/nginx_xaccel
|
||||
|
||||
|
@ -75,7 +81,7 @@ ENV TTRSS_DB_HOST="db"
|
|||
ENV TTRSS_DB_PORT="5432"
|
||||
|
||||
ENV TTRSS_MYSQL_CHARSET="UTF8"
|
||||
ENV TTRSS_PHP_EXECUTABLE="/usr/bin/php81"
|
||||
ENV TTRSS_PHP_EXECUTABLE="/usr/bin/php82"
|
||||
ENV TTRSS_PLUGINS="auth_internal, note, nginx_xaccel"
|
||||
|
||||
CMD ${SCRIPT_ROOT}/startup.sh
|
||||
|
|
|
@ -61,7 +61,7 @@ sudo -u app cp ${SCRIPT_ROOT}/config.docker.php $DST_DIR/config.php
|
|||
chmod 644 $DST_DIR/config.php
|
||||
|
||||
chown -R $OWNER_UID:$OWNER_GID $DST_DIR \
|
||||
/var/log/php81
|
||||
/var/log/php82
|
||||
|
||||
if [ -z "$TTRSS_NO_STARTUP_PLUGIN_UPDATES" ]; then
|
||||
echo updating all local plugins...
|
||||
|
@ -100,7 +100,7 @@ if [ ! -z "${TTRSS_XDEBUG_ENABLED}" ]; then
|
|||
fi
|
||||
echo enabling xdebug with the following parameters:
|
||||
env | grep TTRSS_XDEBUG
|
||||
cat > /etc/php81/conf.d/50_xdebug.ini <<EOF
|
||||
cat > /etc/php82/conf.d/50_xdebug.ini <<EOF
|
||||
zend_extension=xdebug.so
|
||||
xdebug.mode=develop,trace,debug
|
||||
xdebug.start_with_request = yes
|
||||
|
@ -110,17 +110,17 @@ EOF
|
|||
fi
|
||||
|
||||
sed -i.bak "s/^\(memory_limit\) = \(.*\)/\1 = ${PHP_WORKER_MEMORY_LIMIT}/" \
|
||||
/etc/php81/php.ini
|
||||
/etc/php82/php.ini
|
||||
|
||||
sed -i.bak "s/^\(pm.max_children\) = \(.*\)/\1 = ${PHP_WORKER_MAX_CHILDREN}/" \
|
||||
/etc/php81/php-fpm.d/www.conf
|
||||
/etc/php82/php-fpm.d/www.conf
|
||||
|
||||
sudo -Eu app php81 $DST_DIR/update.php --update-schema=force-yes
|
||||
sudo -Eu app php82 $DST_DIR/update.php --update-schema=force-yes
|
||||
|
||||
if [ ! -z "$ADMIN_USER_PASS" ]; then
|
||||
sudo -Eu app php81 $DST_DIR/update.php --user-set-password "admin:$ADMIN_USER_PASS"
|
||||
sudo -Eu app php82 $DST_DIR/update.php --user-set-password "admin:$ADMIN_USER_PASS"
|
||||
else
|
||||
if sudo -Eu app php81 $DST_DIR/update.php --user-check-password "admin:password"; then
|
||||
if sudo -Eu app php82 $DST_DIR/update.php --user-check-password "admin:password"; then
|
||||
RANDOM_PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 16 ; echo '')
|
||||
|
||||
echo "*****************************************************************************"
|
||||
|
@ -128,17 +128,17 @@ else
|
|||
echo "* If you want to set it manually, use ADMIN_USER_PASS environment variable. *"
|
||||
echo "*****************************************************************************"
|
||||
|
||||
sudo -Eu app php81 $DST_DIR/update.php --user-set-password "admin:$RANDOM_PASS"
|
||||
sudo -Eu app php82 $DST_DIR/update.php --user-set-password "admin:$RANDOM_PASS"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -z "$ADMIN_USER_ACCESS_LEVEL" ]; then
|
||||
sudo -Eu app php81 $DST_DIR/update.php --user-set-access-level "admin:$ADMIN_USER_ACCESS_LEVEL"
|
||||
sudo -Eu app php82 $DST_DIR/update.php --user-set-access-level "admin:$ADMIN_USER_ACCESS_LEVEL"
|
||||
fi
|
||||
|
||||
if [ ! -z "$AUTO_CREATE_USER" ]; then
|
||||
sudo -Eu app /bin/sh -c "php81 $DST_DIR/update.php --user-exists $AUTO_CREATE_USER ||
|
||||
php81 $DST_DIR/update.php --force-yes --user-add \"$AUTO_CREATE_USER:$AUTO_CREATE_USER_PASS:$AUTO_CREATE_USER_ACCESS_LEVEL\""
|
||||
sudo -Eu app /bin/sh -c "php82 $DST_DIR/update.php --user-exists $AUTO_CREATE_USER ||
|
||||
php82 $DST_DIR/update.php --force-yes --user-add \"$AUTO_CREATE_USER:$AUTO_CREATE_USER_PASS:$AUTO_CREATE_USER_ACCESS_LEVEL\""
|
||||
fi
|
||||
|
||||
rm -f /tmp/error.log && mkfifo /tmp/error.log && chown app:app /tmp/error.log
|
||||
|
@ -150,4 +150,4 @@ unset AUTO_CREATE_USER_PASS
|
|||
|
||||
touch $DST_DIR/.app_is_ready
|
||||
|
||||
exec /usr/sbin/php-fpm81 --nodaemonize --force-stderr
|
||||
exec /usr/sbin/php-fpm82 --nodaemonize --force-stderr
|
||||
|
|
|
@ -21,7 +21,7 @@ while ! pg_isready -h $TTRSS_DB_HOST -U $TTRSS_DB_USER; do
|
|||
done
|
||||
|
||||
sed -i.bak "s/^\(memory_limit\) = \(.*\)/\1 = ${PHP_WORKER_MEMORY_LIMIT}/" \
|
||||
/etc/php81/php.ini
|
||||
/etc/php82/php.ini
|
||||
|
||||
DST_DIR=/var/www/html/tt-rss
|
||||
|
||||
|
@ -30,4 +30,4 @@ while [ ! -s $DST_DIR/config.php -a -e $DST_DIR/.app_is_ready ]; do
|
|||
sleep 3
|
||||
done
|
||||
|
||||
sudo -E -u app /usr/bin/php81 /var/www/html/tt-rss/update_daemon2.php
|
||||
sudo -E -u app /usr/bin/php82 /var/www/html/tt-rss/update_daemon2.php
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
workflow_dispatch: {}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
|
||||
jobs:
|
||||
phpdoc:
|
||||
runs-on: alpine-3.16
|
||||
steps:
|
||||
- uses: https://gitea.com/actions/checkout@v3
|
||||
|
||||
- name: phpdoc
|
||||
run: php81 /phpDocumentor.phar -d classes -d include -t phpdoc --visibility=public
|
||||
|
||||
- name: prepare ssh
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.APK_DEPLOY_SSH_KEY }}" | tr -d \\r > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
|
||||
- name: upload results
|
||||
run: rsync -av -e 'ssh -o StrictHostKeyChecking=no' phpdoc/ ${{ secrets.APK_DEPLOY_USER }}@${{ secrets.APK_DEPLOY_HOST }}:phpdoc/
|
||||
|
||||
build:
|
||||
runs-on: alpine-3.16
|
||||
steps:
|
||||
- uses: https://gitea.com/actions/checkout@v3
|
||||
|
||||
- name: eslint
|
||||
run: npx eslint js plugins
|
||||
|
||||
- run: rm -rf node_modules
|
||||
|
||||
- name: phpunit
|
||||
run: php81 ./vendor/bin/phpunit
|
||||
|
||||
- name: calculate cache key hash
|
||||
uses: actions/go-hashfiles@v0.0.1
|
||||
id: cache-hash
|
||||
with:
|
||||
patterns: |
|
||||
classes/*.php
|
||||
include/*.php
|
||||
plugins/**/*.php
|
||||
|
||||
- name: phpstan
|
||||
run: php81 -d memory_limit=-1 ./vendor/bin/phpstan --memory-limit=2G
|
||||
|
||||
- name: setup qemu
|
||||
uses: https://github.com/docker/setup-qemu-action@v2
|
||||
|
||||
- name: setup buildx
|
||||
uses: https://github.com/docker/setup-buildx-action@v2
|
||||
|
||||
- name: login to registry
|
||||
uses: https://github.com/docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ secrets.REGISTRY_HOST }}
|
||||
username: ${{ secrets.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: login to docker hub
|
||||
uses: https://github.com/docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
password: ${{ secrets.DOCKER_HUB_TOKEN }}
|
||||
|
||||
- name: get docker meta for web-nginx
|
||||
id: meta_web_nginx
|
||||
uses: https://github.com/docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
${{ secrets.REGISTRY_HOST }}/cthulhoo/ttrss-web-nginx
|
||||
cthulhoo/ttrss-web-nginx
|
||||
tags: |
|
||||
type=sha,prefix={{ date 'YY.MM-' tz='UTC'}}
|
||||
type=raw,value=latest,enable={{ is_default_branch }}
|
||||
|
||||
- name: build web-nginx image
|
||||
uses: https://github.com/docker/build-push-action@v4
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
context: .docker/web-nginx
|
||||
tags: ${{ steps.meta_web_nginx.outputs.tags }}
|
||||
labels: ${{ steps.meta_web_nginx.outputs.labels }}
|
||||
provenance: false
|
||||
cache-from: type=registry,ref=${{ secrets.REGISTRY_HOST }}/cthulhoo/ttrss-web-nginx:latest
|
||||
cache-to: type=inline
|
||||
|
||||
- name: get docker meta for app
|
||||
id: meta_app
|
||||
uses: https://github.com/docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
${{ secrets.REGISTRY_HOST }}/cthulhoo/ttrss-fpm-pgsql-static
|
||||
cthulhoo/ttrss-fpm-pgsql-static
|
||||
tags: |
|
||||
type=sha,prefix={{ date 'YY.MM-' tz='UTC'}}
|
||||
type=raw,value=latest,enable={{ is_default_branch }}
|
||||
|
||||
- name: build app image
|
||||
uses: https://github.com/docker/build-push-action@v4
|
||||
with:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
context: .docker/app
|
||||
build-contexts:
|
||||
app-src=.
|
||||
tags: ${{ steps.meta_app.outputs.tags }}
|
||||
labels: ${{ steps.meta_app.outputs.labels }}
|
||||
provenance: false
|
||||
cache-from: type=registry,ref=${{ secrets.REGISTRY_HOST }}/cthulhoo/ttrss-fpm-pgsql-static:latest
|
||||
cache-to: type=inline
|
|
@ -1,33 +0,0 @@
|
|||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
|
||||
name: lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- "master"
|
||||
workflow_dispatch: {}
|
||||
pull_request: {}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: alpine-3.16
|
||||
steps:
|
||||
- name: checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: npm install
|
||||
run: npm install
|
||||
|
||||
- name: eslint
|
||||
run: npx eslint js plugins
|
||||
|
||||
- name: phpunit
|
||||
run: php81 ./vendor/bin/phpunit
|
||||
|
||||
- name: phpstan
|
||||
run: php81 -d memory_limit=-1 ./vendor/bin/phpstan --memory-limit=2G
|
136
.gitlab-ci.yml
136
.gitlab-ci.yml
|
@ -2,145 +2,55 @@ stages:
|
|||
- lint
|
||||
- build
|
||||
|
||||
.build-master:
|
||||
image:
|
||||
name: ${CI_DOCKER_IMAGE}
|
||||
stage: build
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "web"
|
||||
changes:
|
||||
- '**/*.php'
|
||||
- '**/*.js'
|
||||
- '.docker/**/*'
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
when: manual
|
||||
before_script:
|
||||
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
|
||||
- docker login -u ${DOCKER_HUB_USER} -p ${DOCKER_HUB_TOKEN}
|
||||
variables:
|
||||
ESLINT_PATHS: js plugins
|
||||
|
||||
- docker run --privileged --rm registry.fakecake.org/docker.io/tonistiigi/binfmt --install all
|
||||
- docker buildx create --name mp-builder --driver docker-container --bootstrap --use
|
||||
|
||||
script:
|
||||
- BUILD_TIMESTAMP=$(date -d $(echo ${CI_COMMIT_TIMESTAMP} | cut -b 1-10) +%y.%m)
|
||||
|
||||
- docker buildx build
|
||||
--push
|
||||
--platform linux/amd64,linux/arm64,linux/arm/v7
|
||||
--tag ${CI_REGISTRY}/cthulhoo/${CI_JOB_NAME}:${BUILD_TIMESTAMP}-${CI_COMMIT_SHORT_SHA}
|
||||
--tag ${CI_REGISTRY}/cthulhoo/${CI_JOB_NAME}:latest
|
||||
--tag cthulhoo/${CI_JOB_NAME}:${BUILD_TIMESTAMP}-${CI_COMMIT_SHORT_SHA}
|
||||
--tag cthulhoo/${CI_JOB_NAME}:latest
|
||||
--build-context app-src=.
|
||||
--cache-from type=registry,ref=${CI_REGISTRY}/cthulhoo/${CI_JOB_NAME}:latest
|
||||
--cache-to type=inline
|
||||
${BUILD_CONTEXT}
|
||||
|
||||
# note: CI_REGISTRY, etc. variables are privileged
|
||||
#
|
||||
# .build-branch:
|
||||
# image:
|
||||
# name: ${CI_DOCKER_IMAGE}
|
||||
# stage: build
|
||||
# rules:
|
||||
# - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "web"
|
||||
# changes:
|
||||
# - '**/*.php'
|
||||
# - '**/*.js'
|
||||
# - '.docker/**/*'
|
||||
# - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
||||
# when: manual
|
||||
# before_script:
|
||||
# - docker buildx create --name mp-builder --driver docker-container --bootstrap --use
|
||||
# - CONTAINER_NAME=$(echo ${CI_JOB_NAME} | sed 's/branch://')
|
||||
# script:
|
||||
# - docker buildx build
|
||||
# --push
|
||||
# --platform linux/amd64
|
||||
# --tag ${CI_REGISTRY}/cthulhoo/$CONTAINER_NAME:${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}
|
||||
# --tag ${CI_REGISTRY}/cthulhoo/$CONTAINER_NAME:${CI_COMMIT_BRANCH}
|
||||
# --build-context app-src=.
|
||||
# --cache-from type=registry,ref=${CI_REGISTRY}/cthulhoo/$CONTAINER_NAME:${CI_COMMIT_BRANCH}
|
||||
# --cache-to type=inline
|
||||
# ${BUILD_CONTEXT}
|
||||
include:
|
||||
- project: 'ci/ci-templates'
|
||||
ref: master
|
||||
file: .ci-build-docker.yml
|
||||
- project: 'ci/ci-templates'
|
||||
ref: master
|
||||
file: .ci-lint-common.yml
|
||||
|
||||
phpunit:
|
||||
image:
|
||||
name: ${CI_DOCKER_IMAGE}
|
||||
stage: lint
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE != "web"
|
||||
changes:
|
||||
- '**/*.php'
|
||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- php81 ./vendor/bin/phpunit
|
||||
extends: .phpunit
|
||||
|
||||
eslint:
|
||||
image:
|
||||
name: ${CI_DOCKER_IMAGE}
|
||||
stage: lint
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE != "web"
|
||||
changes:
|
||||
- '**/*.js'
|
||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- npm install
|
||||
- npx eslint js plugins
|
||||
extends: .eslint
|
||||
|
||||
phpstan:
|
||||
image:
|
||||
name: ${CI_DOCKER_IMAGE}
|
||||
needs:
|
||||
- phpunit
|
||||
stage: lint
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE != "web"
|
||||
changes:
|
||||
- '**/*.php'
|
||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- php81 -d memory_limit=-1 ./vendor/bin/phpstan --memory-limit=2G
|
||||
extends: .phpstan
|
||||
|
||||
ttrss-web-nginx:
|
||||
extends: .build-master
|
||||
variables:
|
||||
BUILD_CONTEXT: ${CI_PROJECT_DIR}/.docker/web-nginx
|
||||
|
||||
ttrss-web-nginx:branch:
|
||||
extends: .build-branch
|
||||
variables:
|
||||
BUILD_CONTEXT: ${CI_PROJECT_DIR}/.docker/web-nginx
|
||||
|
||||
ttrss-fpm-pgsql-static:
|
||||
extends: .build-master
|
||||
variables:
|
||||
BUILD_CONTEXT: ${CI_PROJECT_DIR}/.docker/app
|
||||
|
||||
# branch:ttrss-web-nginx:
|
||||
# extends: .build-branch
|
||||
# variables:
|
||||
# BUILD_CONTEXT: ${CI_PROJECT_DIR}/.docker/web-nginx
|
||||
|
||||
# branch:ttrss-fpm-pgsql-static:
|
||||
# extends: .build-branch
|
||||
# variables:
|
||||
# BUILD_CONTEXT: ${CI_PROJECT_DIR}/.docker/app
|
||||
ttrss-fpm-pgsql-static:branch:
|
||||
extends: .build-branch
|
||||
variables:
|
||||
BUILD_CONTEXT: ${CI_PROJECT_DIR}/.docker/app
|
||||
|
||||
phpdoc:
|
||||
image:
|
||||
name: ${CI_DOCKER_IMAGE}
|
||||
stage: build
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "web"
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "web" && $PHPDOC_DEPLOY_SSH_KEY != null
|
||||
changes:
|
||||
- '**/*.php'
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $PHPDOC_DEPLOY_SSH_KEY != null
|
||||
when: manual
|
||||
script:
|
||||
- php81 /phpDocumentor.phar -d classes -d include -t phpdoc --visibility=public
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
## Contributing code the right way
|
||||
|
||||
TLDR: it works like Github.
|
||||
TLDR: it works *almost* like Github.
|
||||
|
||||
Due to spam, new Gitlab users are set to [external](https://docs.gitlab.com/ee/user/admin_area/external_users.html). In order to do anything, you'll need to ask for your account to be promoted. Sorry for the inconvenience.
|
||||
|
||||
1. Register on the [development website](https://dev.tt-rss.org);
|
||||
2. Fork the repository you're interested in;
|
||||
3. Do the needful;
|
||||
4. Verify that your changes pass through PHPStan (see below);
|
||||
4. File a PR against master branch;
|
||||
2. Post on the forums asking for your account to be promoted;
|
||||
3. Fork the repository you're interested in;
|
||||
4. Do the needful;
|
||||
5. Verify that your changes pass through PHPStan (see below);
|
||||
6. File a PR against master branch;
|
||||
|
||||
If you have any other questions, see this [forum thread](https://discourse.tt-rss.org/t/how-to-contribute-code-via-pull-requests-on-git-tt-rss-org/1850).
|
||||
|
||||
|
|
46
backend.php
46
backend.php
|
@ -30,11 +30,16 @@
|
|||
$op = (string)clean($op);
|
||||
$method = (string)clean($method);
|
||||
|
||||
$scope = Tracer::start(__FILE__, ['tags' => json_encode($_REQUEST)]);
|
||||
|
||||
startup_gettext();
|
||||
|
||||
$script_started = microtime(true);
|
||||
|
||||
if (!init_plugins()) return;
|
||||
if (!init_plugins()) {
|
||||
$scope->close();
|
||||
return;
|
||||
}
|
||||
|
||||
header("Content-Type: text/json; charset=utf-8");
|
||||
|
||||
|
@ -46,6 +51,9 @@
|
|||
if (!\Sessions\validate_session()) {
|
||||
header("Content-Type: text/json");
|
||||
print Errors::to_json(Errors::E_UNAUTHORIZED);
|
||||
|
||||
$scope->getSpan()->setTag('error', Errors::E_UNAUTHORIZED);
|
||||
$scope->close();
|
||||
return;
|
||||
}
|
||||
UserHelper::load_user_plugins($_SESSION["uid"]);
|
||||
|
@ -53,6 +61,9 @@
|
|||
|
||||
if (Config::is_migration_needed()) {
|
||||
print Errors::to_json(Errors::E_SCHEMA_MISMATCH);
|
||||
|
||||
$scope->getSpan()->setTag('error', Errors::E_SCHEMA_MISMATCH);
|
||||
$scope->close();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -114,10 +125,14 @@
|
|||
user_error("Refusing to invoke method $method of handler $op which starts with underscore.", E_USER_WARNING);
|
||||
header("Content-Type: text/json");
|
||||
print Errors::to_json(Errors::E_UNAUTHORIZED);
|
||||
|
||||
$scope->getSpan()->setTag('error', Errors::E_UNAUTHORIZED);
|
||||
$scope->close();
|
||||
return;
|
||||
}
|
||||
|
||||
if ($override) {
|
||||
/** @var Plugin|IHandler|ICatchall $handler */
|
||||
$handler = $override;
|
||||
} else {
|
||||
$reflection = new ReflectionClass($op);
|
||||
|
@ -125,10 +140,18 @@
|
|||
}
|
||||
|
||||
if (implements_interface($handler, 'IHandler')) {
|
||||
$h_scope = Tracer::start("construct/$op");
|
||||
$handler->__construct($_REQUEST);
|
||||
$h_scope->close();
|
||||
|
||||
if (validate_csrf($csrf_token) || $handler->csrf_ignore($method)) {
|
||||
if ($handler->before($method)) {
|
||||
|
||||
$b_scope = Tracer::start("before/$method");
|
||||
$before = $handler->before($method);
|
||||
$b_scope->close();
|
||||
|
||||
if ($before) {
|
||||
$m_scope = Tracer::start("method/$method");
|
||||
if ($method && method_exists($handler, $method)) {
|
||||
$reflection = new ReflectionMethod($handler, $method);
|
||||
|
||||
|
@ -137,6 +160,8 @@
|
|||
} else {
|
||||
user_error("Refusing to invoke method $method of handler $op which has required parameters.", E_USER_WARNING);
|
||||
header("Content-Type: text/json");
|
||||
|
||||
$m_scope->getSpan()->setTag('error', Errors::E_UNAUTHORIZED);
|
||||
print Errors::to_json(Errors::E_UNAUTHORIZED);
|
||||
}
|
||||
} else {
|
||||
|
@ -144,20 +169,34 @@
|
|||
$handler->catchall($method);
|
||||
} else {
|
||||
header("Content-Type: text/json");
|
||||
|
||||
$m_scope->getSpan()->setTag('error', Errors::E_UNKNOWN_METHOD);
|
||||
print Errors::to_json(Errors::E_UNKNOWN_METHOD, ["info" => get_class($handler) . "->$method"]);
|
||||
}
|
||||
}
|
||||
$m_scope->close();
|
||||
|
||||
$a_scope = Tracer::start("after/$method");
|
||||
$handler->after();
|
||||
$a_scope->close();
|
||||
|
||||
$scope->close();
|
||||
return;
|
||||
} else {
|
||||
header("Content-Type: text/json");
|
||||
print Errors::to_json(Errors::E_UNAUTHORIZED);
|
||||
|
||||
$scope->getSpan()->setTag('error', Errors::E_UNAUTHORIZED);
|
||||
$scope->close();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
user_error("Refusing to invoke method $method of handler $op with invalid CSRF token.", E_USER_WARNING);
|
||||
header("Content-Type: text/json");
|
||||
print Errors::to_json(Errors::E_UNAUTHORIZED);
|
||||
|
||||
$scope->getSpan()->setTag('error', Errors::E_UNAUTHORIZED);
|
||||
$scope->close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -166,4 +205,5 @@
|
|||
header("Content-Type: text/json");
|
||||
print Errors::to_json(Errors::E_UNKNOWN_METHOD, [ "info" => (isset($handler) ? get_class($handler) : "UNKNOWN:".$op) . "->$method"]);
|
||||
|
||||
?>
|
||||
$scope->getSpan()->setTag('error', Errors::E_UNKNOWN_METHOD);
|
||||
$scope->close();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
class API extends Handler {
|
||||
|
||||
const API_LEVEL = 20;
|
||||
const API_LEVEL = 21;
|
||||
|
||||
const STATUS_OK = 0;
|
||||
const STATUS_ERR = 1;
|
||||
|
@ -844,6 +844,8 @@ class API extends Handler {
|
|||
$headline_row["note"] = $line["note"];
|
||||
$headline_row["lang"] = $line["lang"];
|
||||
|
||||
$headline_row["site_url"] = $line["site_url"];
|
||||
|
||||
if ($show_content) {
|
||||
$hook_object = ["headline" => &$headline_row];
|
||||
|
||||
|
|
|
@ -239,8 +239,7 @@ class Article extends Handler_Protected {
|
|||
print json_encode(["id" => (int)$id, "tags" => $this->_get_tags($id)]);
|
||||
}
|
||||
|
||||
|
||||
/*function completeTags() {
|
||||
function completeTags(): void {
|
||||
$search = clean($_REQUEST["search"]);
|
||||
|
||||
$sth = $this->pdo->prepare("SELECT DISTINCT tag_name FROM ttrss_tags
|
||||
|
@ -250,12 +249,14 @@ class Article extends Handler_Protected {
|
|||
|
||||
$sth->execute([$_SESSION['uid'], "$search%"]);
|
||||
|
||||
print "<ul>";
|
||||
$results = [];
|
||||
|
||||
while ($line = $sth->fetch()) {
|
||||
print "<li>" . $line["tag_name"] . "</li>";
|
||||
array_push($results, $line["tag_name"]);
|
||||
}
|
||||
|
||||
print json_encode($results);
|
||||
}
|
||||
print "</ul>";
|
||||
}*/
|
||||
|
||||
function assigntolabel(): void {
|
||||
$this->_label_ops(true);
|
||||
|
@ -297,6 +298,8 @@ class Article extends Handler_Protected {
|
|||
* @return array{'formatted': string, 'entries': array<int, array<string, mixed>>}
|
||||
*/
|
||||
static function _format_enclosures(int $id, bool $always_display_enclosures, string $article_content, bool $hide_images = false): array {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$enclosures = self::_get_enclosures($id);
|
||||
$enclosures_formatted = "";
|
||||
|
||||
|
@ -323,6 +326,7 @@ class Article extends Handler_Protected {
|
|||
$enclosures_formatted, $enclosures, $id, $always_display_enclosures, $article_content, $hide_images);
|
||||
|
||||
if (!empty($enclosures_formatted)) {
|
||||
$scope->close();
|
||||
return [
|
||||
'formatted' => $enclosures_formatted,
|
||||
'entries' => []
|
||||
|
@ -366,6 +370,7 @@ class Article extends Handler_Protected {
|
|||
}
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
return $rv;
|
||||
}
|
||||
|
||||
|
@ -373,6 +378,7 @@ class Article extends Handler_Protected {
|
|||
* @return array<int, string>
|
||||
*/
|
||||
static function _get_tags(int $id, int $owner_uid = 0, ?string $tag_cache = null): array {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$a_id = $id;
|
||||
|
||||
|
@ -421,6 +427,7 @@ class Article extends Handler_Protected {
|
|||
$sth->execute([$tags_str, $id, $owner_uid]);
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
return $tags;
|
||||
}
|
||||
|
||||
|
@ -515,6 +522,8 @@ class Article extends Handler_Protected {
|
|||
* @return array<int, array<int, int|string>>
|
||||
*/
|
||||
static function _get_labels(int $id, ?int $owner_uid = null): array {
|
||||
$scope = Tracer::start(__METHOD__, []);
|
||||
|
||||
$rv = array();
|
||||
|
||||
if (!$owner_uid) $owner_uid = $_SESSION["uid"];
|
||||
|
@ -560,6 +569,8 @@ class Article extends Handler_Protected {
|
|||
else
|
||||
Labels::update_cache($owner_uid, $id, array("no-labels" => 1));
|
||||
|
||||
$scope->close();
|
||||
|
||||
return $rv;
|
||||
}
|
||||
|
||||
|
@ -570,6 +581,7 @@ class Article extends Handler_Protected {
|
|||
* @return array<int, Article::ARTICLE_KIND_*|string>
|
||||
*/
|
||||
static function _get_image(array $enclosures, string $content, string $site_url, array $headline) {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$article_image = "";
|
||||
$article_stream = "";
|
||||
|
@ -648,6 +660,8 @@ class Article extends Handler_Protected {
|
|||
if ($article_stream && $cache->exists(sha1($article_stream)))
|
||||
$article_stream = $cache->get_url(sha1($article_stream));
|
||||
|
||||
$scope->close();
|
||||
|
||||
return [$article_image, $article_stream, $article_kind];
|
||||
}
|
||||
|
||||
|
@ -661,6 +675,8 @@ class Article extends Handler_Protected {
|
|||
if (count($article_ids) == 0)
|
||||
return [];
|
||||
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$entries = ORM::for_table('ttrss_entries')
|
||||
->table_alias('e')
|
||||
->join('ttrss_user_entries', ['ref_id', '=', 'id'], 'ue')
|
||||
|
@ -680,6 +696,8 @@ class Article extends Handler_Protected {
|
|||
}
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
|
||||
return array_unique($rv);
|
||||
}
|
||||
|
||||
|
@ -691,6 +709,8 @@ class Article extends Handler_Protected {
|
|||
if (count($article_ids) == 0)
|
||||
return [];
|
||||
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$entries = ORM::for_table('ttrss_entries')
|
||||
->table_alias('e')
|
||||
->join('ttrss_user_entries', ['ref_id', '=', 'id'], 'ue')
|
||||
|
@ -703,6 +723,8 @@ class Article extends Handler_Protected {
|
|||
array_push($rv, $entry->feed_id);
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
|
||||
return array_unique($rv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,6 +192,12 @@ class Config {
|
|||
/** delay updates for this feed if received HTTP 429 (Too Many Requests) for this amount of seconds (base value, actual delay is base...base*2) */
|
||||
const HTTP_429_THROTTLE_INTERVAL = "HTTP_429_THROTTLE_INTERVAL";
|
||||
|
||||
/** host running Jaeger collector to receive traces (disabled if empty) */
|
||||
const JAEGER_REPORTING_HOST = "JAEGER_REPORTING_HOST";
|
||||
|
||||
/** Jaeger service name */
|
||||
const JAEGER_SERVICE_NAME = "JAEGER_SERVICE_NAME";
|
||||
|
||||
/** default values for all global configuration options */
|
||||
private const _DEFAULTS = [
|
||||
Config::DB_TYPE => [ "pgsql", Config::T_STRING ],
|
||||
|
@ -249,6 +255,8 @@ class Config {
|
|||
Config::HTTP_USER_AGENT => [ 'Tiny Tiny RSS/%s (https://tt-rss.org/)',
|
||||
Config::T_STRING ],
|
||||
Config::HTTP_429_THROTTLE_INTERVAL => [ 3600, Config::T_INT ],
|
||||
Config::JAEGER_REPORTING_HOST => [ "", Config::T_STRING ],
|
||||
Config::JAEGER_SERVICE_NAME => [ "tt-rss", Config::T_STRING ],
|
||||
];
|
||||
|
||||
/** @var Config|null */
|
||||
|
@ -303,7 +311,11 @@ class Config {
|
|||
static function get_version_html() : string {
|
||||
$version = self::get_version(false);
|
||||
|
||||
return sprintf("<span title=\"%s\">%s</span>", date("Y-m-d H:i:s", ($version['timestamp'] ?? 0)), $version['version']);
|
||||
return sprintf("<span title=\"%s\n%s\n%s\">%s</span>",
|
||||
date("Y-m-d H:i:s", ($version['timestamp'] ?? 0)),
|
||||
$version['commit'] ?? '',
|
||||
$version['branch'] ?? '',
|
||||
$version['version']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -315,8 +327,16 @@ class Config {
|
|||
if (empty($this->version)) {
|
||||
$this->version["status"] = -1;
|
||||
|
||||
if (PHP_OS === "Darwin") {
|
||||
$ttrss_version["version"] = "UNKNOWN (Unsupported, Darwin)";
|
||||
if (getenv("CI_COMMIT_SHORT_SHA") && getenv("CI_COMMIT_TIMESTAMP")) {
|
||||
|
||||
$this->version["branch"] = getenv("CI_COMMIT_BRANCH");
|
||||
$this->version["timestamp"] = strtotime(getenv("CI_COMMIT_TIMESTAMP"));
|
||||
$this->version["version"] = sprintf("%s-%s", date("y.m", $this->version["timestamp"]), getenv("CI_COMMIT_SHORT_SHA"));
|
||||
$this->version["commit"] = getenv("CI_COMMIT_SHORT_SHA");
|
||||
$this->version["status"] = 0;
|
||||
|
||||
} else if (PHP_OS === "Darwin") {
|
||||
$this->version["version"] = "UNKNOWN (Unsupported, Darwin)";
|
||||
} else if (file_exists("$root_dir/version_static.txt")) {
|
||||
$this->version["version"] = trim(file_get_contents("$root_dir/version_static.txt")) . " (Unsupported)";
|
||||
} else if (ini_get("open_basedir")) {
|
||||
|
@ -352,6 +372,7 @@ class Config {
|
|||
$rv = [
|
||||
"status" => -1,
|
||||
"version" => "",
|
||||
"branch" => "",
|
||||
"commit" => "",
|
||||
"timestamp" => 0,
|
||||
];
|
||||
|
|
|
@ -145,6 +145,7 @@ class Counters {
|
|||
* @return array<int, array<string, int|string>>
|
||||
*/
|
||||
private static function get_feeds(array $feed_ids = null): array {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$ret = [];
|
||||
|
||||
|
@ -211,6 +212,8 @@ class Counters {
|
|||
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
@ -218,6 +221,8 @@ class Counters {
|
|||
* @return array<int, array<string, int|string>>
|
||||
*/
|
||||
private static function get_global(): array {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$ret = [
|
||||
[
|
||||
"id" => "global-unread",
|
||||
|
@ -234,6 +239,8 @@ class Counters {
|
|||
"counter" => $subcribed_feeds
|
||||
]);
|
||||
|
||||
$scope->close();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
@ -241,6 +248,7 @@ class Counters {
|
|||
* @return array<int, array<string, int|string>>
|
||||
*/
|
||||
private static function get_virt(): array {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$ret = [];
|
||||
|
||||
|
@ -287,6 +295,7 @@ class Counters {
|
|||
}
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
@ -295,6 +304,7 @@ class Counters {
|
|||
* @return array<int, array<string, int|string>>
|
||||
*/
|
||||
static function get_labels(array $label_ids = null): array {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$ret = [];
|
||||
|
||||
|
@ -346,6 +356,7 @@ class Counters {
|
|||
array_push($ret, $cv);
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
class Digest
|
||||
{
|
||||
static function send_headlines_digests(): void {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$user_limit = 15; // amount of users to process (e.g. emails to send out)
|
||||
$limit = 1000; // maximum amount of headlines to include
|
||||
|
@ -75,6 +76,8 @@ class Digest
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
Debug::log("All done.");
|
||||
}
|
||||
|
||||
|
|
|
@ -221,7 +221,11 @@ class DiskCache implements Cache_Adapter {
|
|||
}
|
||||
|
||||
public function remove(string $filename): bool {
|
||||
return $this->adapter->remove($filename);
|
||||
$scope = Tracer::start(__METHOD__, ['filename' => $filename]);
|
||||
$rc = $this->adapter->remove($filename);
|
||||
$scope->close();
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
public function set_dir(string $dir) : void {
|
||||
|
@ -244,14 +248,22 @@ class DiskCache implements Cache_Adapter {
|
|||
}
|
||||
|
||||
public function exists(string $filename): bool {
|
||||
return $this->adapter->exists(basename($filename));
|
||||
$scope = Tracer::start(__METHOD__, ['filename' => $filename]);
|
||||
$rc = $this->adapter->exists(basename($filename));
|
||||
$scope->close();
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|false -1 if the file doesn't exist, false if an error occurred, size in bytes otherwise
|
||||
*/
|
||||
public function get_size(string $filename) {
|
||||
return $this->adapter->get_size(basename($filename));
|
||||
$scope = Tracer::start(__METHOD__, ['filename' => $filename]);
|
||||
$rc = $this->adapter->get_size(basename($filename));
|
||||
$scope->close();
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,7 +272,11 @@ class DiskCache implements Cache_Adapter {
|
|||
* @return int|false Bytes written or false if an error occurred.
|
||||
*/
|
||||
public function put(string $filename, $data) {
|
||||
return $this->adapter->put(basename($filename), $data);
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
$rc = $this->adapter->put(basename($filename), $data);
|
||||
$scope->close();
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
/** @deprecated we can't assume cached files are local, and other storages
|
||||
|
@ -304,11 +320,16 @@ class DiskCache implements Cache_Adapter {
|
|||
}
|
||||
|
||||
public function send(string $filename) {
|
||||
$scope = Tracer::start(__METHOD__, ['filename' => $filename]);
|
||||
|
||||
$filename = basename($filename);
|
||||
|
||||
if (!$this->exists($filename)) {
|
||||
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
|
||||
echo "File not found.";
|
||||
|
||||
$scope->getSpan()->setTag('error', '404 not found');
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -317,6 +338,9 @@ class DiskCache implements Cache_Adapter {
|
|||
|
||||
if (($_SERVER['HTTP_IF_MODIFIED_SINCE'] ?? '') == $gmt_modified || ($_SERVER['HTTP_IF_NONE_MATCH'] ?? '') == $file_mtime) {
|
||||
header('HTTP/1.1 304 Not Modified');
|
||||
|
||||
$scope->getSpan()->setTag('error', '304 not modified');
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -334,6 +358,9 @@ class DiskCache implements Cache_Adapter {
|
|||
header("Content-type: text/plain");
|
||||
|
||||
print "Stored file has disallowed content type ($mimetype)";
|
||||
|
||||
$scope->getSpan()->setTag('error', '400 disallowed content type');
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -355,7 +382,13 @@ class DiskCache implements Cache_Adapter {
|
|||
|
||||
header_remove("Pragma");
|
||||
|
||||
return $this->adapter->send($filename);
|
||||
$scope->getSpan()->setTag('mimetype', $mimetype);
|
||||
|
||||
$rc = $this->adapter->send($filename);
|
||||
|
||||
$scope->close();
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
public function get_full_path(string $filename): string {
|
||||
|
@ -384,8 +417,14 @@ class DiskCache implements Cache_Adapter {
|
|||
// plugins work on original source URLs used before caching
|
||||
// NOTE: URLs should be already absolutized because this is called after sanitize()
|
||||
static public function rewrite_urls(string $str): string {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$res = trim($str);
|
||||
if (!$res) return '';
|
||||
|
||||
if (!$res) {
|
||||
$scope->close();
|
||||
return '';
|
||||
}
|
||||
|
||||
$doc = new DOMDocument();
|
||||
if (@$doc->loadHTML('<?xml encoding="UTF-8">' . $res)) {
|
||||
|
@ -397,6 +436,8 @@ class DiskCache implements Cache_Adapter {
|
|||
$need_saving = false;
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$e_scope = Tracer::start('entry', ['tagName' => $entry->tagName]);
|
||||
|
||||
foreach (array('src', 'poster') as $attr) {
|
||||
if ($entry->hasAttribute($attr)) {
|
||||
$url = $entry->getAttribute($attr);
|
||||
|
@ -428,6 +469,8 @@ class DiskCache implements Cache_Adapter {
|
|||
|
||||
$entry->setAttribute("srcset", RSSUtils::encode_srcset($matches));
|
||||
}
|
||||
|
||||
$e_scope->close();
|
||||
}
|
||||
|
||||
if ($need_saving) {
|
||||
|
@ -437,6 +480,9 @@ class DiskCache implements Cache_Adapter {
|
|||
$res = $doc->saveHTML();
|
||||
}
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,12 +49,6 @@ class Feeds extends Handler_Protected {
|
|||
const NEVER_GROUP_FEEDS = [ Feeds::FEED_RECENTLY_READ, Feeds::FEED_ARCHIVED ];
|
||||
const NEVER_GROUP_BY_DATE = [ Feeds::FEED_PUBLISHED, Feeds::FEED_STARRED, Feeds::FEED_FRESH ];
|
||||
|
||||
/** @var int|float int on 64-bit, float on 32-bit */
|
||||
private $viewfeed_timestamp;
|
||||
|
||||
/** @var int|float int on 64-bit, float on 32-bit */
|
||||
private $viewfeed_timestamp_last;
|
||||
|
||||
function csrf_ignore(string $method): bool {
|
||||
$csrf_ignored = array("index");
|
||||
|
||||
|
@ -71,7 +65,7 @@ class Feeds extends Handler_Protected {
|
|||
|
||||
$disable_cache = false;
|
||||
|
||||
$this->_mark_timestamp("init");
|
||||
$scope = Tracer::start(__METHOD__, [], func_get_args());
|
||||
|
||||
$reply = [];
|
||||
$rgba_cache = [];
|
||||
|
@ -157,8 +151,6 @@ class Feeds extends Handler_Protected {
|
|||
$qfh_ret = $this->_get_headlines($params);
|
||||
}
|
||||
|
||||
$this->_mark_timestamp("db query");
|
||||
|
||||
$vfeed_group_enabled = get_pref(Prefs::VFEED_GROUP_BY_FEED) &&
|
||||
!(in_array($feed, self::NEVER_GROUP_FEEDS) && !$cat_view);
|
||||
|
||||
|
@ -176,6 +168,8 @@ class Feeds extends Handler_Protected {
|
|||
$reply['search_query'] = [$search, $search_language];
|
||||
$reply['vfeed_group_enabled'] = $vfeed_group_enabled;
|
||||
|
||||
$p_scope = Tracer::start('plugin_menu_items');
|
||||
|
||||
$plugin_menu_items = "";
|
||||
PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM2,
|
||||
function ($result) use (&$plugin_menu_items) {
|
||||
|
@ -208,13 +202,15 @@ class Feeds extends Handler_Protected {
|
|||
},
|
||||
$feed, $cat_view, $qfh_ret);
|
||||
|
||||
$this->_mark_timestamp("object header");
|
||||
$p_scope->close();
|
||||
|
||||
$a_scope = Tracer::start('articles');
|
||||
|
||||
$headlines_count = 0;
|
||||
|
||||
if ($result instanceof PDOStatement) {
|
||||
while ($line = $result->fetch(PDO::FETCH_ASSOC)) {
|
||||
$this->_mark_timestamp("article start: " . $line["id"] . " " . $line["title"]);
|
||||
$aa_scope = Tracer::start('article', ['id' => $line['id']]);
|
||||
|
||||
++$headlines_count;
|
||||
|
||||
|
@ -232,8 +228,6 @@ class Feeds extends Handler_Protected {
|
|||
$line, $max_excerpt_length);
|
||||
}
|
||||
|
||||
$this->_mark_timestamp(" hook_query_headlines");
|
||||
|
||||
$id = $line["id"];
|
||||
|
||||
// frontend doesn't expect pdo returning booleans as strings on mysql
|
||||
|
@ -281,8 +275,6 @@ class Feeds extends Handler_Protected {
|
|||
array_push($topmost_article_ids, $id);
|
||||
}
|
||||
|
||||
$this->_mark_timestamp(" labels");
|
||||
|
||||
$line["feed_title"] = $line["feed_title"] ?? "";
|
||||
|
||||
$button_doc = new DOMDocument();
|
||||
|
@ -312,6 +304,7 @@ class Feeds extends Handler_Protected {
|
|||
$line);
|
||||
|
||||
$line["buttons"] = "";
|
||||
|
||||
PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_ARTICLE_BUTTON,
|
||||
function ($result, $plugin) use (&$line, &$button_doc) {
|
||||
if ($result && $button_doc->loadXML($result)) {
|
||||
|
@ -335,13 +328,9 @@ class Feeds extends Handler_Protected {
|
|||
},
|
||||
$line);
|
||||
|
||||
$this->_mark_timestamp(" pre-sanitize");
|
||||
|
||||
$line["content"] = Sanitizer::sanitize($line["content"],
|
||||
$line['hide_images'], null, $line["site_url"], $highlight_words, $line["id"]);
|
||||
|
||||
$this->_mark_timestamp(" sanitize");
|
||||
|
||||
if (!get_pref(Prefs::CDM_EXPANDED)) {
|
||||
$line["cdm_excerpt"] = "<span class='collapse'>
|
||||
<i class='material-icons' onclick='return Article.cdmUnsetActive(event)'
|
||||
|
@ -352,8 +341,6 @@ class Feeds extends Handler_Protected {
|
|||
}
|
||||
}
|
||||
|
||||
$this->_mark_timestamp(" pre-enclosures");
|
||||
|
||||
if ($line["num_enclosures"] > 0) {
|
||||
$line["enclosures"] = Article::_format_enclosures($id,
|
||||
sql_bool_to_bool($line["always_display_enclosures"]),
|
||||
|
@ -363,16 +350,12 @@ class Feeds extends Handler_Protected {
|
|||
$line["enclosures"] = [ 'formatted' => '', 'entries' => [] ];
|
||||
}
|
||||
|
||||
$this->_mark_timestamp(" enclosures");
|
||||
|
||||
$line["updated_long"] = TimeHelper::make_local_datetime($line["updated"],true);
|
||||
$line["updated"] = TimeHelper::make_local_datetime($line["updated"], false, null, false, true);
|
||||
|
||||
$line['imported'] = T_sprintf("Imported at %s",
|
||||
TimeHelper::make_local_datetime($line["date_entered"], false));
|
||||
|
||||
$this->_mark_timestamp(" local-datetime");
|
||||
|
||||
if ($line["tag_cache"])
|
||||
$tags = explode(",", $line["tag_cache"]);
|
||||
else
|
||||
|
@ -382,14 +365,12 @@ class Feeds extends Handler_Protected {
|
|||
|
||||
//$line["tags"] = Article::_get_tags($line["id"], false, $line["tag_cache"]);
|
||||
|
||||
$this->_mark_timestamp(" tags");
|
||||
|
||||
$line['has_icon'] = self::_has_icon($feed_id);
|
||||
|
||||
//setting feed headline background color, needs to change text color based on dark/light
|
||||
$fav_color = $line['favicon_avg_color'] ?? false;
|
||||
|
||||
$this->_mark_timestamp(" pre-color");
|
||||
$c_scope = Tracer::start('colors');
|
||||
|
||||
require_once "colors.php";
|
||||
|
||||
|
@ -405,22 +386,16 @@ class Feeds extends Handler_Protected {
|
|||
$line['feed_bg_color'] = 'rgba(' . implode(",", $rgba_cache[$feed_id]) . ',0.3)';
|
||||
}
|
||||
|
||||
$this->_mark_timestamp(" color");
|
||||
$this->_mark_timestamp(" pre-hook_render_cdm");
|
||||
$c_scope->close();
|
||||
|
||||
PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_RENDER_ARTICLE_CDM,
|
||||
function ($result, $plugin) use (&$line) {
|
||||
$line = $result;
|
||||
$this->_mark_timestamp(" hook: " . get_class($plugin));
|
||||
},
|
||||
$line);
|
||||
|
||||
$this->_mark_timestamp(" hook_render_cdm");
|
||||
|
||||
$line['content'] = DiskCache::rewrite_urls($line['content']);
|
||||
|
||||
$this->_mark_timestamp(" disk_cache_rewrite");
|
||||
|
||||
/* we don't need those */
|
||||
|
||||
foreach (["date_entered", "guid", "last_published", "last_marked", "tag_cache", "favicon_avg_color",
|
||||
|
@ -429,11 +404,11 @@ class Feeds extends Handler_Protected {
|
|||
|
||||
array_push($reply['content'], $line);
|
||||
|
||||
$this->_mark_timestamp("article end");
|
||||
$aa_scope->close();
|
||||
}
|
||||
}
|
||||
|
||||
$this->_mark_timestamp("end of articles");
|
||||
$a_scope->close();
|
||||
|
||||
if (!$headlines_count) {
|
||||
|
||||
|
@ -494,7 +469,7 @@ class Feeds extends Handler_Protected {
|
|||
}
|
||||
}
|
||||
|
||||
$this->_mark_timestamp("end");
|
||||
$scope->close();
|
||||
|
||||
return array($topmost_article_ids, $headlines_count, $feed, $disable_cache, $reply);
|
||||
}
|
||||
|
@ -987,6 +962,7 @@ class Feeds extends Handler_Protected {
|
|||
* @throws PDOException
|
||||
*/
|
||||
static function _get_counters($feed, bool $is_cat = false, bool $unread_only = false, ?int $owner_uid = null): int {
|
||||
$scope = Tracer::start(__METHOD__, [], func_get_args());
|
||||
|
||||
$n_feed = (int) $feed;
|
||||
$need_entries = false;
|
||||
|
@ -1010,11 +986,14 @@ class Feeds extends Handler_Protected {
|
|||
$handler = PluginHost::getInstance()->get_feed_handler($feed_id);
|
||||
if (implements_interface($handler, 'IVirtualFeed')) {
|
||||
/** @var IVirtualFeed $handler */
|
||||
$scope->close();
|
||||
return $handler->get_unread($feed_id);
|
||||
} else {
|
||||
$scope->close();
|
||||
return 0;
|
||||
}
|
||||
} else if ($n_feed == Feeds::FEED_RECENTLY_READ) {
|
||||
$scope->close();
|
||||
return 0;
|
||||
// tags
|
||||
} else if ($feed != "0" && $n_feed == 0) {
|
||||
|
@ -1028,6 +1007,7 @@ class Feeds extends Handler_Protected {
|
|||
$row = $sth->fetch();
|
||||
|
||||
// Handle 'SUM()' returning null if there are no results
|
||||
$scope->close();
|
||||
return $row["count"] ?? 0;
|
||||
|
||||
} else if ($n_feed == Feeds::FEED_STARRED) {
|
||||
|
@ -1061,6 +1041,7 @@ class Feeds extends Handler_Protected {
|
|||
|
||||
$label_id = Labels::feed_to_label_id($feed);
|
||||
|
||||
$scope->close();
|
||||
return self::_get_label_unread($label_id, $owner_uid);
|
||||
}
|
||||
|
||||
|
@ -1080,6 +1061,7 @@ class Feeds extends Handler_Protected {
|
|||
$sth->execute([$owner_uid]);
|
||||
$row = $sth->fetch();
|
||||
|
||||
$scope->close();
|
||||
return $row["unread"];
|
||||
|
||||
} else {
|
||||
|
@ -1092,6 +1074,7 @@ class Feeds extends Handler_Protected {
|
|||
$sth->execute([$feed, $owner_uid]);
|
||||
$row = $sth->fetch();
|
||||
|
||||
$scope->close();
|
||||
return $row["unread"];
|
||||
}
|
||||
}
|
||||
|
@ -1489,6 +1472,8 @@ class Feeds extends Handler_Protected {
|
|||
*/
|
||||
static function _get_headlines($params): array {
|
||||
|
||||
$scope = Tracer::start(__METHOD__, [], func_get_args());
|
||||
|
||||
$pdo = Db::pdo();
|
||||
|
||||
// WARNING: due to highly dynamic nature of this query its going to quote parameters
|
||||
|
@ -1981,8 +1966,9 @@ class Feeds extends Handler_Protected {
|
|||
$res = $pdo->query($query);
|
||||
}
|
||||
|
||||
return array($res, $feed_title, $feed_site_url, $last_error, $last_updated, $search_words, $first_id, $vfeed_query_part != "", $query_error_override);
|
||||
$scope->close();
|
||||
|
||||
return array($res, $feed_title, $feed_site_url, $last_error, $last_updated, $search_words, $first_id, $vfeed_query_part != "", $query_error_override);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2472,6 +2458,9 @@ class Feeds extends Handler_Protected {
|
|||
PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_HEADLINES_CUSTOM_SORT_OVERRIDE,
|
||||
function ($result) use (&$query, &$skip_first_id) {
|
||||
list ($query, $skip_first_id) = $result;
|
||||
|
||||
// run until first hard match
|
||||
return !empty($query);
|
||||
},
|
||||
$order);
|
||||
|
||||
|
@ -2495,23 +2484,5 @@ class Feeds extends Handler_Protected {
|
|||
return [$query, $skip_first_id];
|
||||
}
|
||||
|
||||
private function _mark_timestamp(string $label): void {
|
||||
|
||||
if (empty($_REQUEST['timestamps']))
|
||||
return;
|
||||
|
||||
if (!$this->viewfeed_timestamp) $this->viewfeed_timestamp = hrtime(true);
|
||||
if (!$this->viewfeed_timestamp_last) $this->viewfeed_timestamp_last = hrtime(true);
|
||||
|
||||
$timestamp = hrtime(true);
|
||||
|
||||
printf("[%4d ms, %4d abs] %s\n",
|
||||
($timestamp - $this->viewfeed_timestamp_last) / 1e6,
|
||||
($timestamp - $this->viewfeed_timestamp) / 1e6,
|
||||
$label);
|
||||
|
||||
$this->viewfeed_timestamp_last = $timestamp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ class Handler_Public extends Handler {
|
|||
|
||||
function getUnread(): void {
|
||||
$login = clean($_REQUEST["login"]);
|
||||
$fresh = clean($_REQUEST["fresh"]) == "1";
|
||||
$fresh = clean($_REQUEST["fresh"] ?? "0") == "1";
|
||||
|
||||
$uid = UserHelper::find_user_by_login($login);
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
interface ICatchall {
|
||||
function catchall(string $method): void;
|
||||
}
|
|
@ -339,10 +339,13 @@ class PluginHost {
|
|||
*/
|
||||
function chain_hooks_callback(string $hook, Closure $callback, &...$args): void {
|
||||
$method = strtolower((string)$hook);
|
||||
$scope = Tracer::start(__METHOD__, ['hook' => $hook]);
|
||||
|
||||
foreach ($this->get_hooks((string)$hook) as $plugin) {
|
||||
//Debug::log("invoking: " . get_class($plugin) . "->$hook()", Debug::$LOG_VERBOSE);
|
||||
|
||||
$p_scope = Tracer::start("$hook - " . get_class($plugin));
|
||||
|
||||
try {
|
||||
if ($callback($plugin->$method(...$args), $plugin))
|
||||
break;
|
||||
|
@ -351,7 +354,11 @@ class PluginHost {
|
|||
} catch (Error $err) {
|
||||
user_error($err, E_USER_WARNING);
|
||||
}
|
||||
|
||||
$p_scope->close();
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -431,6 +438,8 @@ class PluginHost {
|
|||
* @param PluginHost::KIND_* $kind
|
||||
*/
|
||||
function load(string $classlist, int $kind, int $owner_uid = null, bool $skip_init = false): void {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$plugins = explode(",", $classlist);
|
||||
|
||||
$this->owner_uid = (int) $owner_uid;
|
||||
|
@ -439,18 +448,21 @@ class PluginHost {
|
|||
$class = trim($class);
|
||||
$class_file = strtolower(basename(clean($class)));
|
||||
|
||||
$p_scope = Tracer::start("loading $class_file");
|
||||
|
||||
// try system plugin directory first
|
||||
$file = dirname(__DIR__) . "/plugins/$class_file/init.php";
|
||||
|
||||
if (!file_exists($file)) {
|
||||
$file = dirname(__DIR__) . "/plugins.local/$class_file/init.php";
|
||||
|
||||
if (!file_exists($file))
|
||||
if (!file_exists($file)) {
|
||||
$p_scope->close();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($this->plugins[$class])) {
|
||||
|
||||
// WIP hack
|
||||
// we can't catch incompatible method signatures via Throwable
|
||||
// this also enables global tt-rss safe mode in case there are more plugins like this
|
||||
|
@ -464,6 +476,8 @@ class PluginHost {
|
|||
|
||||
$_SESSION["safe_mode"] = 1;
|
||||
|
||||
$p_scope->getSpan()->setTag('error', 'plugin is blacklisted');
|
||||
$p_scope->close();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -474,16 +488,21 @@ class PluginHost {
|
|||
|
||||
} catch (Error $err) {
|
||||
user_error($err, E_USER_WARNING);
|
||||
|
||||
$p_scope->getSpan()->setTag('error', $err);
|
||||
$p_scope->close();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (class_exists($class) && is_subclass_of($class, "Plugin")) {
|
||||
|
||||
$plugin = new $class($this);
|
||||
$plugin_api = $plugin->api_version();
|
||||
|
||||
if ($plugin_api < self::API_VERSION) {
|
||||
user_error("Plugin $class is not compatible with current API version (need: " . self::API_VERSION . ", got: $plugin_api)", E_USER_WARNING);
|
||||
|
||||
$p_scope->getSpan()->setTag('error', 'plugin is not compatible with API version');
|
||||
$p_scope->close();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -492,6 +511,8 @@ class PluginHost {
|
|||
_bind_textdomain_codeset($class, "UTF-8");
|
||||
}
|
||||
|
||||
$i_scope = Tracer::start('init and register plugin');
|
||||
|
||||
try {
|
||||
switch ($kind) {
|
||||
case $this::KIND_SYSTEM:
|
||||
|
@ -516,11 +537,17 @@ class PluginHost {
|
|||
} catch (Error $err) {
|
||||
user_error($err, E_USER_WARNING);
|
||||
}
|
||||
|
||||
$i_scope->close();
|
||||
|
||||
}
|
||||
}
|
||||
$p_scope->close();
|
||||
}
|
||||
|
||||
$this->load_data();
|
||||
|
||||
$scope->close();
|
||||
}
|
||||
|
||||
function is_system(Plugin $plugin): bool {
|
||||
|
@ -613,6 +640,8 @@ class PluginHost {
|
|||
}
|
||||
|
||||
private function load_data(): void {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
if ($this->owner_uid && !$this->data_loaded && get_schema_version() > 100) {
|
||||
$sth = $this->pdo->prepare("SELECT name, content FROM ttrss_plugin_storage
|
||||
WHERE owner_uid = ?");
|
||||
|
@ -624,10 +653,13 @@ class PluginHost {
|
|||
|
||||
$this->data_loaded = true;
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
}
|
||||
|
||||
private function save_data(string $plugin): void {
|
||||
if ($this->owner_uid) {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
if (!$this->pdo_data)
|
||||
$this->pdo_data = Db::instance()->pdo_connect();
|
||||
|
@ -655,6 +687,7 @@ class PluginHost {
|
|||
}
|
||||
|
||||
$this->pdo_data->commit();
|
||||
$scope->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1104,12 +1104,16 @@ class Pref_Feeds extends Handler_Protected {
|
|||
* @return array<string, mixed>
|
||||
*/
|
||||
private function feedlist_init_feed(int $feed_id, ?string $title = null, bool $unread = false, string $error = '', string $updated = ''): array {
|
||||
$scope = Tracer::start(__METHOD__, []);
|
||||
|
||||
if (!$title)
|
||||
$title = Feeds::_get_title($feed_id, false);
|
||||
|
||||
if ($unread === false)
|
||||
$unread = Feeds::_get_counters($feed_id, false, true);
|
||||
|
||||
$scope->close();
|
||||
|
||||
return [
|
||||
'id' => 'FEED:' . $feed_id,
|
||||
'name' => $title,
|
||||
|
|
|
@ -533,7 +533,11 @@ class Pref_Prefs extends Handler_Protected {
|
|||
<?php $this->index_auth_password() ?>
|
||||
</div>
|
||||
<div dojoType='dijit.layout.ContentPane' title="<?= __('App passwords') ?>">
|
||||
<?php if (PluginHost::getInstance()->get_plugin('auth_internal')) { ?>
|
||||
<?php $this->index_auth_app_passwords() ?>
|
||||
<?php } else { ?>
|
||||
<?= format_warning("App passwords are only available if <b>auth_internal<b> plugin is enabled."); ?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div dojoType='dijit.layout.ContentPane' title="<?= __('Authenticator (OTP)') ?>">
|
||||
<?php $this->index_auth_2fa() ?>
|
||||
|
|
|
@ -106,6 +106,8 @@ class RPC extends Handler_Protected {
|
|||
}
|
||||
|
||||
function getAllCounters(): void {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
@$seq = (int) $_REQUEST['seq'];
|
||||
|
||||
$feed_id_count = (int) ($_REQUEST["feed_id_count"] ?? -1);
|
||||
|
@ -132,6 +134,7 @@ class RPC extends Handler_Protected {
|
|||
'seq' => $seq
|
||||
];
|
||||
|
||||
$scope->close();
|
||||
print json_encode($reply);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@ class RSSUtils {
|
|||
* @param array<string, false|string> $options
|
||||
*/
|
||||
static function update_daemon_common(int $limit = 0, array $options = []): int {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
if (!$limit) $limit = Config::get(Config::DAEMON_FEED_LIMIT);
|
||||
|
||||
if (Config::get_schema_version() != Config::SCHEMA_VERSION) {
|
||||
|
@ -283,6 +285,8 @@ class RSSUtils {
|
|||
// Send feed digests by email if needed.
|
||||
Digest::send_headlines_digests();
|
||||
|
||||
$scope->close();
|
||||
|
||||
return $nf;
|
||||
}
|
||||
|
||||
|
@ -349,6 +353,7 @@ class RSSUtils {
|
|||
|
||||
static function update_rss_feed(int $feed, bool $no_cache = false) : bool {
|
||||
|
||||
$scope = Tracer::start(__METHOD__, [], func_get_args());
|
||||
Debug::log("start", Debug::LOG_VERBOSE);
|
||||
|
||||
$pdo = Db::pdo();
|
||||
|
@ -383,16 +388,19 @@ class RSSUtils {
|
|||
if ($user) {
|
||||
if ($user->access_level == UserHelper::ACCESS_LEVEL_READONLY) {
|
||||
Debug::log("error: denied update for $feed: permission denied by owner access level");
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// this would indicate database corruption of some kind
|
||||
Debug::log("error: owner not found for feed: $feed");
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
Debug::log("error: feeds table record not found for feed: $feed");
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -550,6 +558,7 @@ class RSSUtils {
|
|||
$feed_obj->save();
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
return $error_message == "";
|
||||
}
|
||||
|
||||
|
@ -675,7 +684,7 @@ class RSSUtils {
|
|||
]);
|
||||
|
||||
$feed_obj->save();
|
||||
|
||||
$scope->close();
|
||||
return true; // no articles
|
||||
}
|
||||
|
||||
|
@ -684,6 +693,8 @@ class RSSUtils {
|
|||
$tstart = time();
|
||||
|
||||
foreach ($items as $item) {
|
||||
$a_scope = Tracer::start('article');
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
Debug::log("=================================================================================================================================",
|
||||
|
@ -1276,6 +1287,7 @@ class RSSUtils {
|
|||
Debug::log("article processed.", Debug::LOG_VERBOSE);
|
||||
|
||||
$pdo->commit();
|
||||
$a_scope->close();
|
||||
}
|
||||
|
||||
Debug::log("=================================================================================================================================",
|
||||
|
@ -1317,10 +1329,12 @@ class RSSUtils {
|
|||
unset($rss);
|
||||
|
||||
Debug::log("update failed.", Debug::LOG_VERBOSE);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug::log("update done.", Debug::LOG_VERBOSE);
|
||||
$scope->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1485,6 +1499,8 @@ class RSSUtils {
|
|||
* @return array<int, array<string, string>> An array of filter action arrays with keys "type" and "param"
|
||||
*/
|
||||
static function get_article_filters(array $filters, string $title, string $content, string $link, string $author, array $tags, array &$matched_rules = null, array &$matched_filters = null): array {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
$matches = array();
|
||||
|
||||
foreach ($filters as $filter) {
|
||||
|
@ -1526,6 +1542,9 @@ class RSSUtils {
|
|||
$match = @preg_match("/$reg_exp/iu", $author);
|
||||
break;
|
||||
case "tag":
|
||||
if (count($tags) == 0)
|
||||
array_push($tags, ''); // allow matching if there are no tags
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if (@preg_match("/$reg_exp/iu", $tag)) {
|
||||
$match = true;
|
||||
|
@ -1565,6 +1584,8 @@ class RSSUtils {
|
|||
}
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
|
||||
return $matches;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ class Sanitizer {
|
|||
* @return false|string The HTML, or false if an error occurred.
|
||||
*/
|
||||
public static function sanitize(string $str, ?bool $force_remove_images = false, int $owner = null, string $site_url = null, array $highlight_words = null, int $article_id = null) {
|
||||
$scope = Tracer::start(__METHOD__);
|
||||
|
||||
if (!$owner && isset($_SESSION["uid"]))
|
||||
$owner = $_SESSION["uid"];
|
||||
|
@ -223,6 +224,8 @@ class Sanitizer {
|
|||
|
||||
$res = $doc->saveHTML();
|
||||
|
||||
$scope->close();
|
||||
|
||||
/* strip everything outside of <body>...</body> */
|
||||
|
||||
$res_frag = array();
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
use OpenTracing\GlobalTracer;
|
||||
use OpenTracing\Scope;
|
||||
|
||||
class Tracer {
|
||||
/** @var Tracer $instance */
|
||||
private static $instance;
|
||||
|
||||
public function __construct() {
|
||||
$jaeger_host = Config::get(Config::JAEGER_REPORTING_HOST);
|
||||
|
||||
if ($jaeger_host) {
|
||||
$config = new \Jaeger\Config(
|
||||
[
|
||||
'sampler' => [
|
||||
'type' => \Jaeger\SAMPLER_TYPE_CONST,
|
||||
'param' => true,
|
||||
],
|
||||
'logging' => true,
|
||||
"local_agent" => [
|
||||
"reporting_host" => $jaeger_host,
|
||||
"reporting_port" => 6832
|
||||
],
|
||||
'dispatch_mode' => \Jaeger\Config::JAEGER_OVER_BINARY_UDP,
|
||||
],
|
||||
Config::get(Config::JAEGER_SERVICE_NAME)
|
||||
);
|
||||
|
||||
$config->initializeTracer();
|
||||
|
||||
register_shutdown_function(function() {
|
||||
$tracer = GlobalTracer::get();
|
||||
$tracer->flush();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param array<string>|array<string, array<string, mixed>> $tags
|
||||
* @param array<string> $args
|
||||
* @return Scope
|
||||
*/
|
||||
private function _start(string $name, array $tags = [], array $args = []): Scope {
|
||||
$tracer = GlobalTracer::get();
|
||||
|
||||
$tags['args'] = json_encode($args);
|
||||
|
||||
return $tracer->startActiveSpan($name, ['tags' => $tags]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param array<string>|array<string, array<string, mixed>> $tags
|
||||
* @param array<string> $args
|
||||
* @return Scope
|
||||
*/
|
||||
public static function start(string $name, array $tags = [], array $args = []) : Scope {
|
||||
return self::get_instance()->_start($name, $tags, $args);
|
||||
}
|
||||
|
||||
public static function get_instance() : Tracer {
|
||||
if (self::$instance == null)
|
||||
self::$instance = new self();
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
}
|
|
@ -185,10 +185,14 @@ class UrlHelper {
|
|||
* @return false|string
|
||||
*/
|
||||
static function resolve_redirects(string $url, int $timeout, int $nest = 0) {
|
||||
$scope = Tracer::start(__METHOD__, ['url' => $url]);
|
||||
|
||||
// too many redirects
|
||||
if ($nest > 10)
|
||||
if ($nest > 10) {
|
||||
$scope->getSpan()->setTag('error', 'too many redirects');
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
$context_options = array(
|
||||
'http' => array(
|
||||
|
@ -222,9 +226,12 @@ class UrlHelper {
|
|||
}
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
return $url;
|
||||
}
|
||||
|
||||
$scope->getSpan()->setTag('error', 'request failed');
|
||||
$scope->close();
|
||||
// request failed?
|
||||
return false;
|
||||
}
|
||||
|
@ -270,8 +277,10 @@ class UrlHelper {
|
|||
"useragent" => @func_get_arg(7)
|
||||
); */
|
||||
}
|
||||
|
||||
$url = $options["url"];
|
||||
|
||||
$scope = Tracer::start(__METHOD__, ['url' => $url]);
|
||||
|
||||
$type = isset($options["type"]) ? $options["type"] : false;
|
||||
$login = isset($options["login"]) ? $options["login"] : false;
|
||||
$pass = isset($options["pass"]) ? $options["pass"] : false;
|
||||
|
@ -293,6 +302,9 @@ class UrlHelper {
|
|||
|
||||
if (!$url) {
|
||||
self::$fetch_last_error = "Requested URL failed extended validation.";
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -301,6 +313,9 @@ class UrlHelper {
|
|||
|
||||
if (!$ip_addr || strpos($ip_addr, "127.") === 0) {
|
||||
self::$fetch_last_error = "URL hostname failed to resolve or resolved to a loopback address ($ip_addr)";
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -310,7 +325,12 @@ class UrlHelper {
|
|||
|
||||
$ch = curl_init($url);
|
||||
|
||||
if (!$ch) return false;
|
||||
if (!$ch) {
|
||||
self::$fetch_last_error = "curl_init() failed";
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
$curl_http_headers = [];
|
||||
|
||||
|
@ -412,6 +432,8 @@ class UrlHelper {
|
|||
if (!self::validate(self::$fetch_effective_url, true)) {
|
||||
self::$fetch_last_error = "URL received after redirection failed extended validation.";
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -420,6 +442,8 @@ class UrlHelper {
|
|||
if (!self::$fetch_effective_ip_addr || strpos(self::$fetch_effective_ip_addr, "127.") === 0) {
|
||||
self::$fetch_last_error = "URL hostname received after redirection failed to resolve or resolved to a loopback address (".self::$fetch_effective_ip_addr.")";
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -435,6 +459,9 @@ class UrlHelper {
|
|||
|
||||
self::$fetch_last_error_content = $contents;
|
||||
curl_close($ch);
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -445,6 +472,9 @@ class UrlHelper {
|
|||
self::$fetch_last_error = curl_errno($ch) . " " . curl_error($ch);
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -458,6 +488,8 @@ class UrlHelper {
|
|||
if ($tmp) $contents = $tmp;
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
|
||||
return $contents;
|
||||
} else {
|
||||
|
||||
|
@ -511,6 +543,8 @@ class UrlHelper {
|
|||
if (!self::validate(self::$fetch_effective_url, true)) {
|
||||
self::$fetch_last_error = "URL received after redirection failed extended validation.";
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -519,6 +553,8 @@ class UrlHelper {
|
|||
if (!self::$fetch_effective_ip_addr || strpos(self::$fetch_effective_ip_addr, "127.") === 0) {
|
||||
self::$fetch_last_error = "URL hostname received after redirection failed to resolve or resolved to a loopback address (".self::$fetch_effective_ip_addr.")";
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -526,6 +562,9 @@ class UrlHelper {
|
|||
|
||||
if ($data === false) {
|
||||
self::$fetch_last_error = "'file_get_contents' failed.";
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -561,6 +600,8 @@ class UrlHelper {
|
|||
|
||||
self::$fetch_last_error_content = $data;
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -573,9 +614,13 @@ class UrlHelper {
|
|||
if ($tmp) $data = $tmp;
|
||||
}
|
||||
|
||||
$scope->close();
|
||||
return $data;
|
||||
} else {
|
||||
self::$fetch_last_error = 'Successful response, but no content was received.';
|
||||
|
||||
$scope->getSpan()->setTag('error', self::$fetch_last_error);
|
||||
$scope->close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
"spomky-labs/otphp": "^10.0",
|
||||
"chillerlan/php-qrcode": "^4.3.3",
|
||||
"mervick/material-design-icons": "^2.2",
|
||||
"j4mie/idiorm": "dev-master"
|
||||
"j4mie/idiorm": "dev-master",
|
||||
"jonahgeorge/jaeger-client-php": "^1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.3",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "d2be3e2749aff1bebf6257ecbfd6dcb3",
|
||||
"content-hash": "de4af0d5d452fc73fe4f5d584163af9a",
|
||||
"packages": [
|
||||
{
|
||||
"name": "beberlei/assert",
|
||||
|
@ -280,6 +280,74 @@
|
|||
},
|
||||
"time": "2022-03-26T15:19:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jonahgeorge/jaeger-client-php",
|
||||
"version": "v1.4.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jonahgeorge/jaeger-client-php.git",
|
||||
"reference": "3173d9c68ad8cea16058f25337982b00cc3d1c2b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jonahgeorge/jaeger-client-php/zipball/3173d9c68ad8cea16058f25337982b00cc3d1c2b",
|
||||
"reference": "3173d9c68ad8cea16058f25337982b00cc3d1c2b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-sockets": "*",
|
||||
"opentracing/opentracing": "^1.0",
|
||||
"packaged/thrift": "^0.13",
|
||||
"php": "^7.1 || ^8.0 || ^8.1",
|
||||
"psr/cache": "^1.0 || ^2.0 || ^3.0",
|
||||
"psr/log": "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"cache/array-adapter": "^1.0",
|
||||
"phpunit/phpunit": "^7 || ^8 || ^9",
|
||||
"squizlabs/php_codesniffer": "3.*",
|
||||
"symfony/polyfill-php73": "^1.10"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"./src/Jaeger/Constants.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Jaeger\\": "src/Jaeger/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jonah George",
|
||||
"homepage": "http://twitter.com/jonahgeorge"
|
||||
},
|
||||
{
|
||||
"name": "José Carlos Chávez",
|
||||
"email": "jcchavezs@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Contributors",
|
||||
"homepage": "https://github.com/jonahgeorge/jaeger-client-php/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Jaeger Bindings for PHP OpenTracing API",
|
||||
"keywords": [
|
||||
"jaeger",
|
||||
"opentracing",
|
||||
"trace",
|
||||
"tracing"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/jonahgeorge/jaeger-client-php/issues",
|
||||
"source": "https://github.com/jonahgeorge/jaeger-client-php/tree/v1.4.4"
|
||||
},
|
||||
"time": "2023-01-31T13:40:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mervick/material-design-icons",
|
||||
"version": "2.2.0",
|
||||
|
@ -323,6 +391,94 @@
|
|||
},
|
||||
"time": "2016-02-22T01:05:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "opentracing/opentracing",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opentracing/opentracing-php.git",
|
||||
"reference": "cd60bd1fb2a25280600bc74c7f9e0c13881a9116"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opentracing/opentracing-php/zipball/cd60bd1fb2a25280600bc74c7f9e0c13881a9116",
|
||||
"reference": "cd60bd1fb2a25280600bc74c7f9e0c13881a9116",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "~0.12",
|
||||
"phpunit/phpunit": "^7.0 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "3.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/OpenTracing/Tags.php",
|
||||
"src/OpenTracing/Formats.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"OpenTracing\\": "src/OpenTracing/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "José Carlos Chávez",
|
||||
"email": "jcchavezs@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "OpenTracing API for PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/opentracing/opentracing-php/issues",
|
||||
"source": "https://github.com/opentracing/opentracing-php/tree/1.0.2"
|
||||
},
|
||||
"time": "2022-01-27T19:59:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "packaged/thrift",
|
||||
"version": "0.13.01",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/packaged/thrift.git",
|
||||
"reference": "e3dbcfb79e319971d64264ffe9c340590cc8a228"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/packaged/thrift/zipball/e3dbcfb79e319971d64264ffe9c340590cc8a228",
|
||||
"reference": "e3dbcfb79e319971d64264ffe9c340590cc8a228",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5 || ^7.0 || ^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Thrift\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"description": "Apache Thrift",
|
||||
"homepage": "http://thrift.apache.org/",
|
||||
"keywords": [
|
||||
"apache",
|
||||
"thrift"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/packaged/thrift/issues",
|
||||
"source": "https://github.com/packaged/thrift/tree/0.13.01"
|
||||
},
|
||||
"time": "2021-01-25T13:32:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/constant_time_encoding",
|
||||
"version": "v2.6.3",
|
||||
|
@ -390,6 +546,105 @@
|
|||
},
|
||||
"time": "2022-06-14T06:56:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/cache.git",
|
||||
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
|
||||
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Cache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for caching libraries",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"psr",
|
||||
"psr-6"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/cache/tree/3.0.0"
|
||||
},
|
||||
"time": "2021-02-03T23:26:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/log/tree/3.0.0"
|
||||
},
|
||||
"time": "2021-07-14T16:46:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spomky-labs/otphp",
|
||||
"version": "v10.0.3",
|
||||
|
@ -2690,5 +2945,5 @@
|
|||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "2.0.0"
|
||||
}
|
||||
|
|
18
js/App.js
18
js/App.js
|
@ -810,8 +810,10 @@ const App = {
|
|||
dojo.connect(dijit.byId('content-insert'), 'resize',
|
||||
(args) => {
|
||||
if (args && args.w >= 0 && args.h >= 0) {
|
||||
Cookie.set("ttrss_ci_width", args.w, this.getInitParam("cookie_lifetime"));
|
||||
Cookie.set("ttrss_ci_height", args.h, this.getInitParam("cookie_lifetime"));
|
||||
const cookie_suffix = this._widescreen_mode ? "wide" : "normal";
|
||||
|
||||
Cookie.set("ttrss_ci_width:" + cookie_suffix, args.w, this.getInitParam("cookie_lifetime"));
|
||||
Cookie.set("ttrss_ci_height:" + cookie_suffix, args.h, this.getInitParam("cookie_lifetime"));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -918,10 +920,6 @@ const App = {
|
|||
return;
|
||||
}
|
||||
|
||||
// reset stored sizes because geometry changed
|
||||
Cookie.set("ttrss_ci_width", 0);
|
||||
Cookie.set("ttrss_ci_height", 0);
|
||||
|
||||
this._widescreen_mode = wide;
|
||||
|
||||
const article_id = Article.getActive();
|
||||
|
@ -938,9 +936,9 @@ const App = {
|
|||
height: 'auto',
|
||||
borderTopWidth: '0px' });
|
||||
|
||||
if (parseInt(Cookie.get("ttrss_ci_width")) > 0) {
|
||||
if (parseInt(Cookie.get("ttrss_ci_width:wide")) > 0) {
|
||||
content_insert.domNode.setStyle(
|
||||
{width: Cookie.get("ttrss_ci_width") + "px" });
|
||||
{width: Cookie.get("ttrss_ci_width:wide") + "px" });
|
||||
}
|
||||
|
||||
headlines_frame.setStyle({ borderBottomWidth: '0px' });
|
||||
|
@ -953,9 +951,9 @@ const App = {
|
|||
height: '50%',
|
||||
borderTopWidth: '0px'});
|
||||
|
||||
if (parseInt(Cookie.get("ttrss_ci_height")) > 0) {
|
||||
if (parseInt(Cookie.get("ttrss_ci_height:normal")) > 0) {
|
||||
content_insert.domNode.setStyle(
|
||||
{height: Cookie.get("ttrss_ci_height") + "px" });
|
||||
{height: Cookie.get("ttrss_ci_height:normal") + "px" });
|
||||
}
|
||||
|
||||
headlines_frame.setStyle({ borderBottomWidth: '1px' });
|
||||
|
|
|
@ -333,6 +333,20 @@ const Article = {
|
|||
|
||||
return false;
|
||||
},
|
||||
autocompleteInject: function(elem, targetId) {
|
||||
const target = App.byId(targetId);
|
||||
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target.value = target.value.split(',')
|
||||
.slice(0, -1)
|
||||
.map((w) => w.trim())
|
||||
.concat([elem.innerText])
|
||||
.join(', ') + ', ';
|
||||
|
||||
target.focus();
|
||||
},
|
||||
editTags: function (id) {
|
||||
const dialog = new fox.SingleUseDialog({
|
||||
title: __("Article tags"),
|
||||
|
@ -348,7 +362,7 @@ const Article = {
|
|||
<section>
|
||||
<textarea dojoType='dijit.form.SimpleTextarea' rows='4' disabled='true'
|
||||
id='tags_str' name='tags_str'>${__("Loading, please wait...")}</textarea>
|
||||
<div class='autocomplete' id='tags_choices' style='display:none'></div>
|
||||
<span id='tags_choices'></span>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
|
@ -387,9 +401,15 @@ const Article = {
|
|||
.attr('value', reply.tags.join(", "))
|
||||
.attr('disabled', false);
|
||||
|
||||
/* new Ajax.Autocompleter("tags_str", "tags_choices",
|
||||
"backend.php?op=article&method=completeTags",
|
||||
{tokens: ',', paramName: "search"}); */
|
||||
App.byId('tags_str').onkeyup = (e) => {
|
||||
const last_tag = e.target.value.split(',').pop().trim();
|
||||
|
||||
xhr.json("backend.php", {op: 'article', method: 'completeTags', search: last_tag}, (data) => {
|
||||
App.byId("tags_choices").innerHTML = `${data.map((tag) =>
|
||||
`<a href="#" onclick="Article.autocompleteInject(this, 'tags_str')">${tag}</a>` )
|
||||
.join(', ')}`
|
||||
});
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -599,7 +599,7 @@ const CommonDialogs = {
|
|||
<input style="display: none" type="file" onchange="App.dialogOf(this).uploadIcon(this)">
|
||||
</label>
|
||||
|
||||
${App.FormFields.submit_tag(App.FormFields.icon("delete") + " " + __("Remove"), {class: "alt-danger", onclick: "App.dialogOf(this).removeIcon("+feed_id+")"})}
|
||||
${App.FormFields.button_tag(App.FormFields.icon("delete") + " " + __("Remove"), "", {class: "alt-danger", onclick: "App.dialogOf(this).removeIcon("+feed_id+")"})}
|
||||
</div>
|
||||
<div dojoType="dijit.layout.ContentPane" title="${__('Plugins')}">
|
||||
${reply.plugin_data}
|
||||
|
|
|
@ -13,6 +13,7 @@ const Headlines = {
|
|||
_scroll_reset_timeout: false,
|
||||
default_force_previous: false,
|
||||
default_force_to_top: false,
|
||||
default_move_on_expand: true,
|
||||
line_scroll_offset: 120, /* px */
|
||||
sticky_header_observer: new IntersectionObserver(
|
||||
(entries, observer) => {
|
||||
|
@ -255,6 +256,7 @@ const Headlines = {
|
|||
// this would only work if there's enough space
|
||||
App.byId("headlines-frame").scrollTop -= scroll_position_A-scroll_position_B;
|
||||
|
||||
if (this.default_move_on_expand)
|
||||
Article.cdmMoveToId(id);
|
||||
}
|
||||
|
||||
|
|
19
js/common.js
19
js/common.js
|
@ -29,6 +29,25 @@ function $$(query) {
|
|||
return document.querySelectorAll(query);
|
||||
}
|
||||
|
||||
// polyfill for safari https://raw.githubusercontent.com/pladaria/requestidlecallback-polyfill/master/index.js
|
||||
window.requestIdleCallback =
|
||||
window.requestIdleCallback ||
|
||||
function (callback) {
|
||||
const start = Date.now();
|
||||
return setTimeout(() => {
|
||||
callback({
|
||||
didTimeout: false,
|
||||
timeRemaining: () => Math.max(0, 50 - (Date.now() - start))
|
||||
},
|
||||
);
|
||||
}, 1);
|
||||
};
|
||||
|
||||
window.cancelIdleCallback =
|
||||
window.cancelIdleCallback ||
|
||||
function (id) {
|
||||
clearTimeout(id);
|
||||
};
|
||||
|
||||
Element.prototype.hasClassName = function(className) {
|
||||
return this.classList.contains(className);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"url": "https://github.com/dojo/dijit.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"dojo": "1.16.4"
|
||||
"dojo": "1.16.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "dijit",
|
||||
"version": "1.16.4",
|
||||
"version": "1.16.5",
|
||||
"directories": {
|
||||
"lib": "."
|
||||
},
|
||||
"main": "main",
|
||||
"dependencies": {
|
||||
"dojo": "1.16.4"
|
||||
"dojo": "1.16.5"
|
||||
},
|
||||
"description": "Dijit provides a complete collection of user interface controls based on Dojo, giving you the power to create web applications that are highly optimized for usability, performance, internationalization, accessibility, but above all deliver an incredible user experience.",
|
||||
"license" : "BSD-3-Clause OR AFL-2.1",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# Dojo requires Java runtime to build. Further information on rebuilding Dojo
|
||||
# is available here: http://dojotoolkit.org/reference-guide/build/index.html
|
||||
|
||||
VERSION=1.16.4
|
||||
VERSION=1.16.5
|
||||
|
||||
# Download and extract dojo src code if it doesn't already exist
|
||||
if [ ! -d "dojo" ]; then
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
*/
|
||||
|
||||
//>>built
|
||||
define("dojo/_base/kernel",["../global","../has","./config","require","module"],function(_1,_2,_3,_4,_5){var i,p,_6={},_7={},_8={config:_3,global:_1,dijit:_6,dojox:_7};var _9={dojo:["dojo",_8],dijit:["dijit",_6],dojox:["dojox",_7]},_a=(_4.map&&_4.map[_5.id.match(/[^\/]+/)[0]]),_b;for(p in _a){if(_9[p]){_9[p][0]=_a[p];}else{_9[p]=[_a[p],{}];}}for(p in _9){_b=_9[p];_b[1]._scopeName=_b[0];if(!_3.noGlobals){_1[_b[0]]=_b[1];}}_8.scopeMap=_9;_8.baseUrl=_8.config.baseUrl=_4.baseUrl;_8.isAsync=!1||_4.async;_8.locale=_3.locale;var _c="$Rev:$".match(/[0-9a-f]{7,}/);_8.version={major:1,minor:16,patch:4,flag:"",revision:_c?_c[0]:NaN,toString:function(){var v=_8.version;return v.major+"."+v.minor+"."+v.patch+v.flag+" ("+v.revision+")";}};1||_2.add("extend-dojo",1);if(!_2("csp-restrictions")){(Function("d","d.eval = function(){return d.global.eval ? d.global.eval(arguments[0]) : eval(arguments[0]);}"))(_8);}if(0){_8.exit=function(_d){quit(_d);};}else{_8.exit=function(){};}if(!_2("host-webworker")){1||_2.add("dojo-guarantee-console",1);}if(1){_2.add("console-as-object",function(){return Function.prototype.bind&&console&&typeof console.log==="object";});typeof console!="undefined"||(console={});var cn=["assert","count","debug","dir","dirxml","error","group","groupEnd","info","profile","profileEnd","time","timeEnd","trace","warn","log"];var tn;i=0;while((tn=cn[i++])){if(!console[tn]){(function(){var _e=tn+"";console[_e]=("log" in console)?function(){var a=Array.prototype.slice.call(arguments);a.unshift(_e+":");console["log"](a.join(" "));}:function(){};console[_e]._fake=true;})();}else{if(_2("console-as-object")){console[tn]=Function.prototype.bind.call(console[tn],console);}}}}_2.add("dojo-debug-messages",!!_3.isDebug);_8.deprecated=_8.experimental=function(){};if(_2("dojo-debug-messages")){_8.deprecated=function(_f,_10,_11){var _12="DEPRECATED: "+_f;if(_10){_12+=" "+_10;}if(_11){_12+=" -- will be removed in version: "+_11;}console.warn(_12);};_8.experimental=function(_13,_14){var _15="EXPERIMENTAL: "+_13+" -- APIs subject to change without notice.";if(_14){_15+=" "+_14;}console.warn(_15);};}1||_2.add("dojo-modulePaths",1);if(1){if(_3.modulePaths){_8.deprecated("dojo.modulePaths","use paths configuration");var _16={};for(p in _3.modulePaths){_16[p.replace(/\./g,"/")]=_3.modulePaths[p];}_4({paths:_16});}}1||_2.add("dojo-moduleUrl",1);if(1){_8.moduleUrl=function(_17,url){_8.deprecated("dojo.moduleUrl()","use require.toUrl","2.0");var _18=null;if(_17){_18=_4.toUrl(_17.replace(/\./g,"/")+(url?("/"+url):"")+"/*.*").replace(/\/\*\.\*/,"")+(url?"":"/");}return _18;};}_8._hasResource={};return _8;});
|
||||
define("dojo/_base/kernel",["../global","../has","./config","require","module"],function(_1,_2,_3,_4,_5){var i,p,_6={},_7={},_8={config:_3,global:_1,dijit:_6,dojox:_7};var _9={dojo:["dojo",_8],dijit:["dijit",_6],dojox:["dojox",_7]},_a=(_4.map&&_4.map[_5.id.match(/[^\/]+/)[0]]),_b;for(p in _a){if(_9[p]){_9[p][0]=_a[p];}else{_9[p]=[_a[p],{}];}}for(p in _9){_b=_9[p];_b[1]._scopeName=_b[0];if(!_3.noGlobals){_1[_b[0]]=_b[1];}}_8.scopeMap=_9;_8.baseUrl=_8.config.baseUrl=_4.baseUrl;_8.isAsync=!1||_4.async;_8.locale=_3.locale;var _c="$Rev:$".match(/[0-9a-f]{7,}/);_8.version={major:1,minor:16,patch:5,flag:"",revision:_c?_c[0]:NaN,toString:function(){var v=_8.version;return v.major+"."+v.minor+"."+v.patch+v.flag+" ("+v.revision+")";}};1||_2.add("extend-dojo",1);if(!_2("csp-restrictions")){(Function("d","d.eval = function(){return d.global.eval ? d.global.eval(arguments[0]) : eval(arguments[0]);}"))(_8);}if(0){_8.exit=function(_d){quit(_d);};}else{_8.exit=function(){};}if(!_2("host-webworker")){1||_2.add("dojo-guarantee-console",1);}if(1){_2.add("console-as-object",function(){return Function.prototype.bind&&console&&typeof console.log==="object";});typeof console!="undefined"||(console={});var cn=["assert","count","debug","dir","dirxml","error","group","groupEnd","info","profile","profileEnd","time","timeEnd","trace","warn","log"];var tn;i=0;while((tn=cn[i++])){if(!console[tn]){(function(){var _e=tn+"";console[_e]=("log" in console)?function(){var a=Array.prototype.slice.call(arguments);a.unshift(_e+":");console["log"](a.join(" "));}:function(){};console[_e]._fake=true;})();}else{if(_2("console-as-object")){console[tn]=Function.prototype.bind.call(console[tn],console);}}}}_2.add("dojo-debug-messages",!!_3.isDebug);_8.deprecated=_8.experimental=function(){};if(_2("dojo-debug-messages")){_8.deprecated=function(_f,_10,_11){var _12="DEPRECATED: "+_f;if(_10){_12+=" "+_10;}if(_11){_12+=" -- will be removed in version: "+_11;}console.warn(_12);};_8.experimental=function(_13,_14){var _15="EXPERIMENTAL: "+_13+" -- APIs subject to change without notice.";if(_14){_15+=" "+_14;}console.warn(_15);};}1||_2.add("dojo-modulePaths",1);if(1){if(_3.modulePaths){_8.deprecated("dojo.modulePaths","use paths configuration");var _16={};for(p in _3.modulePaths){_16[p.replace(/\./g,"/")]=_3.modulePaths[p];}_4({paths:_16});}}1||_2.add("dojo-moduleUrl",1);if(1){_8.moduleUrl=function(_17,url){_8.deprecated("dojo.moduleUrl()","use require.toUrl","2.0");var _18=null;if(_17){_18=_4.toUrl(_17.replace(/\./g,"/")+(url?("/"+url):"")+"/*.*").replace(/\/\*\.\*/,"")+(url?"":"/");}return _18;};}_8._hasResource={};return _8;});
|
|
@ -5,4 +5,4 @@
|
|||
*/
|
||||
|
||||
//>>built
|
||||
define("dojo/_base/lang",["./kernel","../has","../sniff"],function(_1,_2){_2.add("bug-for-in-skips-shadowed",function(){for(var i in {toString:1}){return 0;}return 1;});var _3=_2("bug-for-in-skips-shadowed")?"hasOwnProperty.valueOf.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.constructor".split("."):[],_4=_3.length,_5=function(_6,_7,_8){if(!_8){if(_6[0]&&_1.scopeMap[_6[0]]){_8=_1.scopeMap[_6.shift()][1];}else{_8=_1.global;}}try{for(var i=0;i<_6.length;i++){var p=_6[i];if(!(p in _8)){if(_7){_8[p]={};}else{return;}}_8=_8[p];}return _8;}catch(e){}},_9=Object.prototype.toString,_a=function(_b,_c,_d){return (_d||[]).concat(Array.prototype.slice.call(_b,_c||0));},_e=/\{([^\}]+)\}/g;var _f={_extraNames:_3,_mixin:function(_10,_11,_12){var _13,s,i,_14={};for(_13 in _11){s=_11[_13];if(!(_13 in _10)||(_10[_13]!==s&&(!(_13 in _14)||_14[_13]!==s))){_10[_13]=_12?_12(s):s;}}if(_2("bug-for-in-skips-shadowed")){if(_11){for(i=0;i<_4;++i){_13=_3[i];s=_11[_13];if(!(_13 in _10)||(_10[_13]!==s&&(!(_13 in _14)||_14[_13]!==s))){_10[_13]=_12?_12(s):s;}}}}return _10;},mixin:function(_15,_16){if(!_15){_15={};}for(var i=1,l=arguments.length;i<l;i++){_f._mixin(_15,arguments[i]);}return _15;},setObject:function(_17,_18,_19){var _1a=_17.split("."),p=_1a.pop(),obj=_5(_1a,true,_19);return obj&&p?(obj[p]=_18):undefined;},getObject:function(_1b,_1c,_1d){return !_1b?_1d:_5(_1b.split("."),_1c,_1d);},exists:function(_1e,obj){return _f.getObject(_1e,false,obj)!==undefined;},isString:function(it){return (typeof it=="string"||it instanceof String);},isArray:Array.isArray||function(it){return _9.call(it)=="[object Array]";},isFunction:function(it){return _9.call(it)==="[object Function]";},isObject:function(it){return it!==undefined&&(it===null||typeof it=="object"||_f.isArray(it)||_f.isFunction(it));},isArrayLike:function(it){return !!it&&!_f.isString(it)&&!_f.isFunction(it)&&!(it.tagName&&it.tagName.toLowerCase()=="form")&&(_f.isArray(it)||isFinite(it.length));},isAlien:function(it){return it&&!_f.isFunction(it)&&/\{\s*\[native code\]\s*\}/.test(String(it));},extend:function(_1f,_20){for(var i=1,l=arguments.length;i<l;i++){_f._mixin(_1f.prototype,arguments[i]);}return _1f;},_hitchArgs:function(_21,_22){var pre=_f._toArray(arguments,2);var _23=_f.isString(_22);return function(){var _24=_f._toArray(arguments);var f=_23?(_21||_1.global)[_22]:_22;return f&&f.apply(_21||this,pre.concat(_24));};},hitch:function(_25,_26){if(arguments.length>2){return _f._hitchArgs.apply(_1,arguments);}if(!_26){_26=_25;_25=null;}if(_f.isString(_26)){_25=_25||_1.global;if(!_25[_26]){throw (["lang.hitch: scope[\"",_26,"\"] is null (scope=\"",_25,"\")"].join(""));}return function(){return _25[_26].apply(_25,arguments||[]);};}return !_25?_26:function(){return _26.apply(_25,arguments||[]);};},delegate:(function(){function TMP(){};return function(obj,_27){TMP.prototype=obj;var tmp=new TMP();TMP.prototype=null;if(_27){_f._mixin(tmp,_27);}return tmp;};})(),_toArray:_2("ie")?(function(){function _28(obj,_29,_2a){var arr=_2a||[];for(var x=_29||0;x<obj.length;x++){arr.push(obj[x]);}return arr;};return function(obj){return ((obj.item)?_28:_a).apply(this,arguments);};})():_a,partial:function(_2b){var arr=[null];return _f.hitch.apply(_1,arr.concat(_f._toArray(arguments)));},clone:function(src){if(!src||typeof src!="object"||_f.isFunction(src)){return src;}if(src.nodeType&&"cloneNode" in src){return src.cloneNode(true);}if(src instanceof Date){return new Date(src.getTime());}if(src instanceof RegExp){return new RegExp(src);}var r,i,l;if(_f.isArray(src)){r=[];for(i=0,l=src.length;i<l;++i){if(i in src){r[i]=_f.clone(src[i]);}}}else{r=src.constructor?new src.constructor():{};}return _f._mixin(r,src,_f.clone);},trim:String.prototype.trim?function(str){return str.trim();}:function(str){return str.replace(/^\s\s*/,"").replace(/\s\s*$/,"");},replace:function(_2c,map,_2d){return _2c.replace(_2d||_e,_f.isFunction(map)?map:function(_2e,k){return _f.getObject(k,false,map);});}};1&&_f.mixin(_1,_f);return _f;});
|
||||
define("dojo/_base/lang",["./kernel","../has","../sniff"],function(_1,_2){_2.add("bug-for-in-skips-shadowed",function(){for(var i in {toString:1}){return 0;}return 1;});var _3=_2("bug-for-in-skips-shadowed")?"hasOwnProperty.valueOf.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.constructor".split("."):[],_4=_3.length,_5=function(_6,_7,_8){if(!_8){if(_6[0]&&_1.scopeMap[_6[0]]){_8=_1.scopeMap[_6.shift()][1];}else{_8=_1.global;}}try{for(var i=0;i<_6.length;i++){var p=_6[i];if(p==="__proto__"||p==="constructor"){return;}if(!(p in _8)){if(_7){_8[p]={};}else{return;}}_8=_8[p];}return _8;}catch(e){}},_9=Object.prototype.toString,_a=function(_b,_c,_d){return (_d||[]).concat(Array.prototype.slice.call(_b,_c||0));},_e=/\{([^\}]+)\}/g;var _f={_extraNames:_3,_mixin:function(_10,_11,_12){var _13,s,i,_14={};for(_13 in _11){s=_11[_13];if(!(_13 in _10)||(_10[_13]!==s&&(!(_13 in _14)||_14[_13]!==s))){_10[_13]=_12?_12(s):s;}}if(_2("bug-for-in-skips-shadowed")){if(_11){for(i=0;i<_4;++i){_13=_3[i];s=_11[_13];if(!(_13 in _10)||(_10[_13]!==s&&(!(_13 in _14)||_14[_13]!==s))){_10[_13]=_12?_12(s):s;}}}}return _10;},mixin:function(_15,_16){if(!_15){_15={};}for(var i=1,l=arguments.length;i<l;i++){_f._mixin(_15,arguments[i]);}return _15;},setObject:function(_17,_18,_19){var _1a=_17.split("."),p=_1a.pop(),obj=_5(_1a,true,_19);return obj&&p?(obj[p]=_18):undefined;},getObject:function(_1b,_1c,_1d){return !_1b?_1d:_5(_1b.split("."),_1c,_1d);},exists:function(_1e,obj){return _f.getObject(_1e,false,obj)!==undefined;},isString:function(it){return (typeof it=="string"||it instanceof String);},isArray:Array.isArray||function(it){return _9.call(it)=="[object Array]";},isFunction:function(it){return _9.call(it)==="[object Function]";},isObject:function(it){return it!==undefined&&(it===null||typeof it=="object"||_f.isArray(it)||_f.isFunction(it));},isArrayLike:function(it){return !!it&&!_f.isString(it)&&!_f.isFunction(it)&&!(it.tagName&&it.tagName.toLowerCase()=="form")&&(_f.isArray(it)||isFinite(it.length));},isAlien:function(it){return it&&!_f.isFunction(it)&&/\{\s*\[native code\]\s*\}/.test(String(it));},extend:function(_1f,_20){for(var i=1,l=arguments.length;i<l;i++){_f._mixin(_1f.prototype,arguments[i]);}return _1f;},_hitchArgs:function(_21,_22){var pre=_f._toArray(arguments,2);var _23=_f.isString(_22);return function(){var _24=_f._toArray(arguments);var f=_23?(_21||_1.global)[_22]:_22;return f&&f.apply(_21||this,pre.concat(_24));};},hitch:function(_25,_26){if(arguments.length>2){return _f._hitchArgs.apply(_1,arguments);}if(!_26){_26=_25;_25=null;}if(_f.isString(_26)){_25=_25||_1.global;if(!_25[_26]){throw (["lang.hitch: scope[\"",_26,"\"] is null (scope=\"",_25,"\")"].join(""));}return function(){return _25[_26].apply(_25,arguments||[]);};}return !_25?_26:function(){return _26.apply(_25,arguments||[]);};},delegate:(function(){function TMP(){};return function(obj,_27){TMP.prototype=obj;var tmp=new TMP();TMP.prototype=null;if(_27){_f._mixin(tmp,_27);}return tmp;};})(),_toArray:_2("ie")?(function(){function _28(obj,_29,_2a){var arr=_2a||[];for(var x=_29||0;x<obj.length;x++){arr.push(obj[x]);}return arr;};return function(obj){return ((obj.item)?_28:_a).apply(this,arguments);};})():_a,partial:function(_2b){var arr=[null];return _f.hitch.apply(_1,arr.concat(_f._toArray(arguments)));},clone:function(src){if(!src||typeof src!="object"||_f.isFunction(src)){return src;}if(src.nodeType&&"cloneNode" in src){return src.cloneNode(true);}if(src instanceof Date){return new Date(src.getTime());}if(src instanceof RegExp){return new RegExp(src);}var r,i,l;if(_f.isArray(src)){r=[];for(i=0,l=src.length;i<l;++i){if(i in src){r[i]=_f.clone(src[i]);}}}else{r=src.constructor?new src.constructor():{};}return _f._mixin(r,src,_f.clone);},trim:String.prototype.trim?function(str){return str.trim();}:function(str){return str.replace(/^\s\s*/,"").replace(/\s\s*$/,"");},replace:function(_2c,map,_2d){return _2c.replace(_2d||_e,_f.isFunction(map)?map:function(_2e,k){return _f.getObject(k,false,map);});}};1&&_f.mixin(_1,_f);return _f;});
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "dojo",
|
||||
"version": "1.16.4",
|
||||
"version": "1.16.5",
|
||||
"directories": {
|
||||
"lib": "."
|
||||
},
|
||||
|
@ -11,7 +11,7 @@
|
|||
"jsgi-node": "0.3.1",
|
||||
"formidable": "1.0.17",
|
||||
"sinon": "1.12.2",
|
||||
"dojo": "1.16.4"
|
||||
"dojo": "1.16.5"
|
||||
},
|
||||
"main": "main",
|
||||
"scripts": {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -10,8 +10,10 @@ echo PWD: $(pwd)
|
|||
while true; do
|
||||
inotifywait . -e close_write -r -t 300 | grep -q .php && \
|
||||
(
|
||||
MODIFIED=$(git ls-files -m | grep .php)
|
||||
|
||||
docker run --rm -v $(pwd):/app -v /tmp/phpstan-8.1:/tmp/phpstan \
|
||||
--workdir /app php:${PHP_VERSION}-cli php -d memory_limit=-1 ./vendor/bin/phpstan --memory-limit=2G --error-format=raw
|
||||
--workdir /app registry.fakecake.org/cthulhoo/ci-alpine:3.16 php81 -d memory_limit=-1 ./vendor/bin/phpstan --memory-limit=2G --error-format=raw analyze ${MODIFIED}
|
||||
echo All done, RC=$?.
|
||||
)
|
||||
sleep 1
|
||||
|
|
|
@ -2,24 +2,6 @@
|
|||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit19fc2ff1c0f9a92279c7979386bb2056::getLoader();
|
||||
|
|
|
@ -42,79 +42,30 @@ namespace Composer\Autoload;
|
|||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
|
@ -124,47 +75,28 @@ class ClassLoader
|
|||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
* @param array $classMap Class to filename map
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
|
@ -180,10 +112,8 @@ class ClassLoader
|
|||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
|
@ -227,12 +157,10 @@ class ClassLoader
|
|||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
|
@ -277,9 +205,7 @@ class ClassLoader
|
|||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
|
@ -295,11 +221,9 @@ class ClassLoader
|
|||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
|
@ -319,8 +243,6 @@ class ClassLoader
|
|||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
|
@ -343,8 +265,6 @@ class ClassLoader
|
|||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
|
@ -365,8 +285,6 @@ class ClassLoader
|
|||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
|
@ -387,18 +305,14 @@ class ClassLoader
|
|||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
//no-op
|
||||
} elseif ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
|
@ -408,8 +322,6 @@ class ClassLoader
|
|||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
|
@ -424,18 +336,15 @@ class ClassLoader
|
|||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -490,11 +399,6 @@ class ClassLoader
|
|||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
|
@ -560,26 +464,14 @@ class ClassLoader
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,29 +18,459 @@ use Composer\Semver\VersionParser;
|
|||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
* To require it's presence, you can require `composer-runtime-api ^2.0`
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $installed = array (
|
||||
'root' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a37eab2610a0a2bcb655258781c1c7e925dc94c0',
|
||||
'name' => '__root__',
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'__root__' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a37eab2610a0a2bcb655258781c1c7e925dc94c0',
|
||||
),
|
||||
'beberlei/assert' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.3.2',
|
||||
'version' => '3.3.2.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'cb70015c04be1baee6f5f5c953703347c0ac1655',
|
||||
),
|
||||
'chillerlan/php-qrcode' =>
|
||||
array (
|
||||
'pretty_version' => '4.3.4',
|
||||
'version' => '4.3.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d',
|
||||
),
|
||||
'chillerlan/php-settings-container' =>
|
||||
array (
|
||||
'pretty_version' => '2.1.4',
|
||||
'version' => '2.1.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '1beb7df3c14346d4344b0b2e12f6f9a74feabd4a',
|
||||
),
|
||||
'doctrine/instantiator' =>
|
||||
array (
|
||||
'pretty_version' => '1.4.1',
|
||||
'version' => '1.4.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '10dcfce151b967d20fde1b34ae6640712c3891bc',
|
||||
),
|
||||
'j4mie/idiorm' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
0 => '9999999-dev',
|
||||
),
|
||||
'reference' => 'efc8ea06698f53e2c479c7696f2b154c47c3a3cb',
|
||||
),
|
||||
'jonahgeorge/jaeger-client-php' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.4.4',
|
||||
'version' => '1.4.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '3173d9c68ad8cea16058f25337982b00cc3d1c2b',
|
||||
),
|
||||
'mervick/material-design-icons' =>
|
||||
array (
|
||||
'pretty_version' => '2.2.0',
|
||||
'version' => '2.2.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '635435c8d3df3a6da3241648caf8a65d1c07cc1a',
|
||||
),
|
||||
'myclabs/deep-copy' =>
|
||||
array (
|
||||
'pretty_version' => '1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '14daed4296fae74d9e3201d2c4925d1acb7aa614',
|
||||
),
|
||||
'nikic/php-parser' =>
|
||||
array (
|
||||
'pretty_version' => 'v4.14.0',
|
||||
'version' => '4.14.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '34bea19b6e03d8153165d8f30bba4c3be86184c1',
|
||||
),
|
||||
'opentracing/opentracing' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'cd60bd1fb2a25280600bc74c7f9e0c13881a9116',
|
||||
),
|
||||
'packaged/thrift' =>
|
||||
array (
|
||||
'pretty_version' => '0.13.01',
|
||||
'version' => '0.13.01.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'e3dbcfb79e319971d64264ffe9c340590cc8a228',
|
||||
),
|
||||
'paragonie/constant_time_encoding' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.6.3',
|
||||
'version' => '2.6.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '58c3f47f650c94ec05a151692652a868995d2938',
|
||||
),
|
||||
'phar-io/manifest' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.3',
|
||||
'version' => '2.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '97803eca37d319dfa7826cc2437fc020857acb53',
|
||||
),
|
||||
'phar-io/version' =>
|
||||
array (
|
||||
'pretty_version' => '3.2.1',
|
||||
'version' => '3.2.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '4f7fd7836c6f332bb2933569e566a0d6c4cbed74',
|
||||
),
|
||||
'phpdocumentor/reflection-common' =>
|
||||
array (
|
||||
'pretty_version' => '2.2.0',
|
||||
'version' => '2.2.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b',
|
||||
),
|
||||
'phpdocumentor/reflection-docblock' =>
|
||||
array (
|
||||
'pretty_version' => '5.3.0',
|
||||
'version' => '5.3.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '622548b623e81ca6d78b721c5e029f4ce664f170',
|
||||
),
|
||||
'phpdocumentor/type-resolver' =>
|
||||
array (
|
||||
'pretty_version' => '1.6.1',
|
||||
'version' => '1.6.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '77a32518733312af16a44300404e945338981de3',
|
||||
),
|
||||
'phpspec/prophecy' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.15.0',
|
||||
'version' => '1.15.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'bbcd7380b0ebf3961ee21409db7b38bc31d69a13',
|
||||
),
|
||||
'phpstan/phpstan' =>
|
||||
array (
|
||||
'pretty_version' => '1.10.3',
|
||||
'version' => '1.10.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5419375b5891add97dc74be71e6c1c34baaddf64',
|
||||
),
|
||||
'phpunit/php-code-coverage' =>
|
||||
array (
|
||||
'pretty_version' => '9.2.15',
|
||||
'version' => '9.2.15.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '2e9da11878c4202f97915c1cb4bb1ca318a63f5f',
|
||||
),
|
||||
'phpunit/php-file-iterator' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.6',
|
||||
'version' => '3.0.6.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf',
|
||||
),
|
||||
'phpunit/php-invoker' =>
|
||||
array (
|
||||
'pretty_version' => '3.1.1',
|
||||
'version' => '3.1.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5a10147d0aaf65b58940a0b72f71c9ac0423cc67',
|
||||
),
|
||||
'phpunit/php-text-template' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.4',
|
||||
'version' => '2.0.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28',
|
||||
),
|
||||
'phpunit/php-timer' =>
|
||||
array (
|
||||
'pretty_version' => '5.0.3',
|
||||
'version' => '5.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2',
|
||||
),
|
||||
'phpunit/phpunit' =>
|
||||
array (
|
||||
'pretty_version' => '9.5.16',
|
||||
'version' => '9.5.16.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5ff8c545a50226c569310a35f4fa89d79f1ddfdc',
|
||||
),
|
||||
'psr/cache' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf',
|
||||
),
|
||||
'psr/log' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001',
|
||||
),
|
||||
'sebastian/cli-parser' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '442e7c7e687e42adc03470c7b668bc4b2402c0b2',
|
||||
),
|
||||
'sebastian/code-unit' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.8',
|
||||
'version' => '1.0.8.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '1fc9f64c0927627ef78ba436c9b17d967e68e120',
|
||||
),
|
||||
'sebastian/code-unit-reverse-lookup' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.3',
|
||||
'version' => '2.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5',
|
||||
),
|
||||
'sebastian/comparator' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.6',
|
||||
'version' => '4.0.6.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '55f4261989e546dc112258c7a75935a81a7ce382',
|
||||
),
|
||||
'sebastian/complexity' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.2',
|
||||
'version' => '2.0.2.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '739b35e53379900cc9ac327b2147867b8b6efd88',
|
||||
),
|
||||
'sebastian/diff' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.4',
|
||||
'version' => '4.0.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '3461e3fccc7cfdfc2720be910d3bd73c69be590d',
|
||||
),
|
||||
'sebastian/environment' =>
|
||||
array (
|
||||
'pretty_version' => '5.1.4',
|
||||
'version' => '5.1.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '1b5dff7bb151a4db11d49d90e5408e4e938270f7',
|
||||
),
|
||||
'sebastian/exporter' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.4',
|
||||
'version' => '4.0.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '65e8b7db476c5dd267e65eea9cab77584d3cfff9',
|
||||
),
|
||||
'sebastian/global-state' =>
|
||||
array (
|
||||
'pretty_version' => '5.0.5',
|
||||
'version' => '5.0.5.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '0ca8db5a5fc9c8646244e629625ac486fa286bf2',
|
||||
),
|
||||
'sebastian/lines-of-code' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.3',
|
||||
'version' => '1.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'c1c2e997aa3146983ed888ad08b15470a2e22ecc',
|
||||
),
|
||||
'sebastian/object-enumerator' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.4',
|
||||
'version' => '4.0.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5c9eeac41b290a3712d88851518825ad78f45c71',
|
||||
),
|
||||
'sebastian/object-reflector' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.4',
|
||||
'version' => '2.0.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b4f479ebdbf63ac605d183ece17d8d7fe49c15c7',
|
||||
),
|
||||
'sebastian/recursion-context' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.4',
|
||||
'version' => '4.0.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'cd9d8cf3c5804de4341c283ed787f099f5506172',
|
||||
),
|
||||
'sebastian/resource-operations' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.3',
|
||||
'version' => '3.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8',
|
||||
),
|
||||
'sebastian/type' =>
|
||||
array (
|
||||
'pretty_version' => '2.3.4',
|
||||
'version' => '2.3.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'b8cd8a1c753c90bc1a0f5372170e3e489136f914',
|
||||
),
|
||||
'sebastian/version' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.2',
|
||||
'version' => '3.0.2.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'c6c1022351a901512170118436c764e473f6de8c',
|
||||
),
|
||||
'spomky-labs/otphp' =>
|
||||
array (
|
||||
'pretty_version' => 'v10.0.3',
|
||||
'version' => '10.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9784d9f7c790eed26e102d6c78f12c754036c366',
|
||||
),
|
||||
'thecodingmachine/safe' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.2.2',
|
||||
'version' => '2.2.2.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '440284f9592c9df402832452a6871a8b3c48d97e',
|
||||
),
|
||||
'theseer/tokenizer' =>
|
||||
array (
|
||||
'pretty_version' => '1.2.1',
|
||||
'version' => '1.2.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '34a41e998c2183e22995f158c581e7b5e755ab9e',
|
||||
),
|
||||
'webmozart/assert' =>
|
||||
array (
|
||||
'pretty_version' => '1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
|
||||
),
|
||||
),
|
||||
);
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
|
@ -56,6 +486,7 @@ class InstalledVersions
|
|||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
@ -63,42 +494,19 @@ class InstalledVersions
|
|||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
public static function isInstalled($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +523,7 @@ class InstalledVersions
|
|||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
|
@ -224,26 +633,9 @@ class InstalledVersions
|
|||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
|
@ -255,38 +647,14 @@ class InstalledVersions
|
|||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}, versions: list<string, array{pretty_version: ?string, version: ?string, aliases: ?string[], reference: ?string, replaced: ?string[], provided: ?string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
|
@ -303,7 +671,7 @@ class InstalledVersions
|
|||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}, versions: list<string, array{pretty_version: ?string, version: ?string, aliases: ?string[], reference: ?string, replaced: ?string[], provided: ?string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
|
@ -313,7 +681,6 @@ class InstalledVersions
|
|||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
|
@ -324,27 +691,16 @@ class InstalledVersions
|
|||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
// @phpstan-ignore-next-line
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = require __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
$installed[] = self::$installed;
|
||||
|
||||
return $installed;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -18,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
|
||||
'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
|
||||
'a4ecaeafb8cfb009ad0e052c90355e98' => $vendorDir . '/beberlei/assert/lib/Assert/functions.php',
|
||||
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
|
||||
'51fcf4e06c07cc00c920b44bcd900e7a' => $vendorDir . '/thecodingmachine/safe/deprecated/apc.php',
|
||||
|
@ -95,6 +97,7 @@ return array(
|
|||
'4af1dca6db8c527c6eed27bff85ff0e5' => $vendorDir . '/thecodingmachine/safe/generated/yaz.php',
|
||||
'fe43ca06499ac37bc2dedd823af71eb5' => $vendorDir . '/thecodingmachine/safe/generated/zip.php',
|
||||
'356736db98a6834f0a886b8d509b0ecd' => $vendorDir . '/thecodingmachine/safe/generated/zlib.php',
|
||||
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
|
||||
'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
|
||||
'ff1b7935a93a4a9517db3ebe0533892a' => $vendorDir . '/opentracing/opentracing/src/OpenTracing/Tags.php',
|
||||
'0db36546c71c357f5ee70c39bb03966f' => $vendorDir . '/opentracing/opentracing/src/OpenTracing/Formats.php',
|
||||
'822502b10d2c1dae82956ef999e8b4be' => $vendorDir . '/jonahgeorge/jaeger-client-php/src/Jaeger/Constants.php',
|
||||
);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
|
@ -10,10 +10,15 @@ return array(
|
|||
'chillerlan\\Settings\\' => array($vendorDir . '/chillerlan/php-settings-container/src'),
|
||||
'chillerlan\\QRCode\\' => array($vendorDir . '/chillerlan/php-qrcode/src'),
|
||||
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
|
||||
'Thrift\\' => array($vendorDir . '/packaged/thrift/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
|
||||
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
||||
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
|
||||
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
|
||||
'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
|
||||
'OpenTracing\\' => array($vendorDir . '/opentracing/opentracing/src/OpenTracing'),
|
||||
'OTPHP\\' => array($vendorDir . '/spomky-labs/otphp/src'),
|
||||
'Jaeger\\' => array($vendorDir . '/jonahgeorge/jaeger-client-php/src/Jaeger'),
|
||||
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
|
||||
'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
|
||||
'Assert\\' => array($vendorDir . '/beberlei/assert/lib/Assert'),
|
||||
|
|
|
@ -23,26 +23,51 @@ class ComposerAutoloaderInit19fc2ff1c0f9a92279c7979386bb2056
|
|||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit19fc2ff1c0f9a92279c7979386bb2056', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit19fc2ff1c0f9a92279c7979386bb2056', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire19fc2ff1c0f9a92279c7979386bb2056($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequire19fc2ff1c0f9a92279c7979386bb2056($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ namespace Composer\Autoload;
|
|||
class ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056
|
||||
{
|
||||
public static $files = array (
|
||||
'9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
|
||||
'ec07570ca5a812141189b1fa81503674' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
|
||||
'a4ecaeafb8cfb009ad0e052c90355e98' => __DIR__ . '/..' . '/beberlei/assert/lib/Assert/functions.php',
|
||||
'6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
|
||||
'51fcf4e06c07cc00c920b44bcd900e7a' => __DIR__ . '/..' . '/thecodingmachine/safe/deprecated/apc.php',
|
||||
|
@ -96,8 +98,9 @@ class ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056
|
|||
'4af1dca6db8c527c6eed27bff85ff0e5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/yaz.php',
|
||||
'fe43ca06499ac37bc2dedd823af71eb5' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/zip.php',
|
||||
'356736db98a6834f0a886b8d509b0ecd' => __DIR__ . '/..' . '/thecodingmachine/safe/generated/zlib.php',
|
||||
'9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
|
||||
'ec07570ca5a812141189b1fa81503674' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
|
||||
'ff1b7935a93a4a9517db3ebe0533892a' => __DIR__ . '/..' . '/opentracing/opentracing/src/OpenTracing/Tags.php',
|
||||
'0db36546c71c357f5ee70c39bb03966f' => __DIR__ . '/..' . '/opentracing/opentracing/src/OpenTracing/Formats.php',
|
||||
'822502b10d2c1dae82956ef999e8b4be' => __DIR__ . '/..' . '/jonahgeorge/jaeger-client-php/src/Jaeger/Constants.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
|
@ -114,16 +117,27 @@ class ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056
|
|||
array (
|
||||
'Webmozart\\Assert\\' => 17,
|
||||
),
|
||||
'T' =>
|
||||
array (
|
||||
'Thrift\\' => 7,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\Cache\\' => 10,
|
||||
'Prophecy\\' => 9,
|
||||
'PhpParser\\' => 10,
|
||||
'ParagonIE\\ConstantTime\\' => 23,
|
||||
),
|
||||
'O' =>
|
||||
array (
|
||||
'OpenTracing\\' => 12,
|
||||
'OTPHP\\' => 6,
|
||||
),
|
||||
'J' =>
|
||||
array (
|
||||
'Jaeger\\' => 7,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'Doctrine\\Instantiator\\' => 22,
|
||||
|
@ -154,6 +168,18 @@ class ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056
|
|||
array (
|
||||
0 => __DIR__ . '/..' . '/webmozart/assert/src',
|
||||
),
|
||||
'Thrift\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/packaged/thrift/src',
|
||||
),
|
||||
'Psr\\Log\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/src',
|
||||
),
|
||||
'Psr\\Cache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/cache/src',
|
||||
),
|
||||
'Prophecy\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phpspec/prophecy/src/Prophecy',
|
||||
|
@ -166,10 +192,18 @@ class ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056
|
|||
array (
|
||||
0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
|
||||
),
|
||||
'OpenTracing\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/opentracing/opentracing/src/OpenTracing',
|
||||
),
|
||||
'OTPHP\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/spomky-labs/otphp/src',
|
||||
),
|
||||
'Jaeger\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/jonahgeorge/jaeger-client-php/src/Jaeger',
|
||||
),
|
||||
'Doctrine\\Instantiator\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator',
|
||||
|
|
|
@ -359,6 +359,77 @@
|
|||
},
|
||||
"install-path": "../j4mie/idiorm"
|
||||
},
|
||||
{
|
||||
"name": "jonahgeorge/jaeger-client-php",
|
||||
"version": "v1.4.4",
|
||||
"version_normalized": "1.4.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jonahgeorge/jaeger-client-php.git",
|
||||
"reference": "3173d9c68ad8cea16058f25337982b00cc3d1c2b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jonahgeorge/jaeger-client-php/zipball/3173d9c68ad8cea16058f25337982b00cc3d1c2b",
|
||||
"reference": "3173d9c68ad8cea16058f25337982b00cc3d1c2b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-sockets": "*",
|
||||
"opentracing/opentracing": "^1.0",
|
||||
"packaged/thrift": "^0.13",
|
||||
"php": "^7.1 || ^8.0 || ^8.1",
|
||||
"psr/cache": "^1.0 || ^2.0 || ^3.0",
|
||||
"psr/log": "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"cache/array-adapter": "^1.0",
|
||||
"phpunit/phpunit": "^7 || ^8 || ^9",
|
||||
"squizlabs/php_codesniffer": "3.*",
|
||||
"symfony/polyfill-php73": "^1.10"
|
||||
},
|
||||
"time": "2023-01-31T13:40:20+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"./src/Jaeger/Constants.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Jaeger\\": "src/Jaeger/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jonah George",
|
||||
"homepage": "http://twitter.com/jonahgeorge"
|
||||
},
|
||||
{
|
||||
"name": "José Carlos Chávez",
|
||||
"email": "jcchavezs@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Contributors",
|
||||
"homepage": "https://github.com/jonahgeorge/jaeger-client-php/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Jaeger Bindings for PHP OpenTracing API",
|
||||
"keywords": [
|
||||
"jaeger",
|
||||
"opentracing",
|
||||
"trace",
|
||||
"tracing"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/jonahgeorge/jaeger-client-php/issues",
|
||||
"source": "https://github.com/jonahgeorge/jaeger-client-php/tree/v1.4.4"
|
||||
},
|
||||
"install-path": "../jonahgeorge/jaeger-client-php"
|
||||
},
|
||||
{
|
||||
"name": "mervick/material-design-icons",
|
||||
"version": "2.2.0",
|
||||
|
@ -526,6 +597,100 @@
|
|||
},
|
||||
"install-path": "../nikic/php-parser"
|
||||
},
|
||||
{
|
||||
"name": "opentracing/opentracing",
|
||||
"version": "1.0.2",
|
||||
"version_normalized": "1.0.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opentracing/opentracing-php.git",
|
||||
"reference": "cd60bd1fb2a25280600bc74c7f9e0c13881a9116"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opentracing/opentracing-php/zipball/cd60bd1fb2a25280600bc74c7f9e0c13881a9116",
|
||||
"reference": "cd60bd1fb2a25280600bc74c7f9e0c13881a9116",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "~0.12",
|
||||
"phpunit/phpunit": "^7.0 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "3.*"
|
||||
},
|
||||
"time": "2022-01-27T19:59:21+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/OpenTracing/Tags.php",
|
||||
"src/OpenTracing/Formats.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"OpenTracing\\": "src/OpenTracing/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "José Carlos Chávez",
|
||||
"email": "jcchavezs@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "OpenTracing API for PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/opentracing/opentracing-php/issues",
|
||||
"source": "https://github.com/opentracing/opentracing-php/tree/1.0.2"
|
||||
},
|
||||
"install-path": "../opentracing/opentracing"
|
||||
},
|
||||
{
|
||||
"name": "packaged/thrift",
|
||||
"version": "0.13.01",
|
||||
"version_normalized": "0.13.01.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/packaged/thrift.git",
|
||||
"reference": "e3dbcfb79e319971d64264ffe9c340590cc8a228"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/packaged/thrift/zipball/e3dbcfb79e319971d64264ffe9c340590cc8a228",
|
||||
"reference": "e3dbcfb79e319971d64264ffe9c340590cc8a228",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5 || ^7.0 || ^8.0"
|
||||
},
|
||||
"time": "2021-01-25T13:32:28+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Thrift\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"description": "Apache Thrift",
|
||||
"homepage": "http://thrift.apache.org/",
|
||||
"keywords": [
|
||||
"apache",
|
||||
"thrift"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/packaged/thrift/issues",
|
||||
"source": "https://github.com/packaged/thrift/tree/0.13.01"
|
||||
},
|
||||
"install-path": "../packaged/thrift"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/constant_time_encoding",
|
||||
"version": "v2.6.3",
|
||||
|
@ -1453,6 +1618,111 @@
|
|||
],
|
||||
"install-path": "../phpunit/phpunit"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
"version": "3.0.0",
|
||||
"version_normalized": "3.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/cache.git",
|
||||
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
|
||||
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"time": "2021-02-03T23:26:27+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Cache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for caching libraries",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"psr",
|
||||
"psr-6"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/cache/tree/3.0.0"
|
||||
},
|
||||
"install-path": "../psr/cache"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "3.0.0",
|
||||
"version_normalized": "3.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"time": "2021-07-14T16:46:02+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/log/tree/3.0.0"
|
||||
},
|
||||
"install-path": "../psr/log"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
"version": "1.0.1",
|
||||
|
|
|
@ -1,403 +1,448 @@
|
|||
<?php return array (
|
||||
'root' => array(
|
||||
'root' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a37eab2610a0a2bcb655258781c1c7e925dc94c0',
|
||||
'name' => '__root__',
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'__root__' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => 'b7a6c948d078a59739f14de8454e0e7237d0722e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => 'b7a6c948d078a59739f14de8454e0e7237d0722e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
'reference' => 'a37eab2610a0a2bcb655258781c1c7e925dc94c0',
|
||||
),
|
||||
'beberlei/assert' => array(
|
||||
'beberlei/assert' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.3.2',
|
||||
'version' => '3.3.2.0',
|
||||
'reference' => 'cb70015c04be1baee6f5f5c953703347c0ac1655',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../beberlei/assert',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'chillerlan/php-qrcode' => array(
|
||||
'reference' => 'cb70015c04be1baee6f5f5c953703347c0ac1655',
|
||||
),
|
||||
'chillerlan/php-qrcode' =>
|
||||
array (
|
||||
'pretty_version' => '4.3.4',
|
||||
'version' => '4.3.4.0',
|
||||
'reference' => '2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../chillerlan/php-qrcode',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'chillerlan/php-settings-container' => array(
|
||||
'reference' => '2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d',
|
||||
),
|
||||
'chillerlan/php-settings-container' =>
|
||||
array (
|
||||
'pretty_version' => '2.1.4',
|
||||
'version' => '2.1.4.0',
|
||||
'reference' => '1beb7df3c14346d4344b0b2e12f6f9a74feabd4a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../chillerlan/php-settings-container',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'doctrine/instantiator' => array(
|
||||
'reference' => '1beb7df3c14346d4344b0b2e12f6f9a74feabd4a',
|
||||
),
|
||||
'doctrine/instantiator' =>
|
||||
array (
|
||||
'pretty_version' => '1.4.1',
|
||||
'version' => '1.4.1.0',
|
||||
'reference' => '10dcfce151b967d20fde1b34ae6640712c3891bc',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../doctrine/instantiator',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'j4mie/idiorm' => array(
|
||||
'reference' => '10dcfce151b967d20fde1b34ae6640712c3891bc',
|
||||
),
|
||||
'j4mie/idiorm' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => 'efc8ea06698f53e2c479c7696f2b154c47c3a3cb',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../j4mie/idiorm',
|
||||
'aliases' => array(
|
||||
'aliases' =>
|
||||
array (
|
||||
0 => '9999999-dev',
|
||||
),
|
||||
'dev_requirement' => false,
|
||||
'reference' => 'efc8ea06698f53e2c479c7696f2b154c47c3a3cb',
|
||||
),
|
||||
'mervick/material-design-icons' => array(
|
||||
'jonahgeorge/jaeger-client-php' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.4.4',
|
||||
'version' => '1.4.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '3173d9c68ad8cea16058f25337982b00cc3d1c2b',
|
||||
),
|
||||
'mervick/material-design-icons' =>
|
||||
array (
|
||||
'pretty_version' => '2.2.0',
|
||||
'version' => '2.2.0.0',
|
||||
'reference' => '635435c8d3df3a6da3241648caf8a65d1c07cc1a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../mervick/material-design-icons',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'myclabs/deep-copy' => array(
|
||||
'reference' => '635435c8d3df3a6da3241648caf8a65d1c07cc1a',
|
||||
),
|
||||
'myclabs/deep-copy' =>
|
||||
array (
|
||||
'pretty_version' => '1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'reference' => '14daed4296fae74d9e3201d2c4925d1acb7aa614',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../myclabs/deep-copy',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'nikic/php-parser' => array(
|
||||
'reference' => '14daed4296fae74d9e3201d2c4925d1acb7aa614',
|
||||
),
|
||||
'nikic/php-parser' =>
|
||||
array (
|
||||
'pretty_version' => 'v4.14.0',
|
||||
'version' => '4.14.0.0',
|
||||
'reference' => '34bea19b6e03d8153165d8f30bba4c3be86184c1',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../nikic/php-parser',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'paragonie/constant_time_encoding' => array(
|
||||
'reference' => '34bea19b6e03d8153165d8f30bba4c3be86184c1',
|
||||
),
|
||||
'opentracing/opentracing' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'cd60bd1fb2a25280600bc74c7f9e0c13881a9116',
|
||||
),
|
||||
'packaged/thrift' =>
|
||||
array (
|
||||
'pretty_version' => '0.13.01',
|
||||
'version' => '0.13.01.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'e3dbcfb79e319971d64264ffe9c340590cc8a228',
|
||||
),
|
||||
'paragonie/constant_time_encoding' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.6.3',
|
||||
'version' => '2.6.3.0',
|
||||
'reference' => '58c3f47f650c94ec05a151692652a868995d2938',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../paragonie/constant_time_encoding',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phar-io/manifest' => array(
|
||||
'reference' => '58c3f47f650c94ec05a151692652a868995d2938',
|
||||
),
|
||||
'phar-io/manifest' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.3',
|
||||
'version' => '2.0.3.0',
|
||||
'reference' => '97803eca37d319dfa7826cc2437fc020857acb53',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phar-io/manifest',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phar-io/version' => array(
|
||||
'reference' => '97803eca37d319dfa7826cc2437fc020857acb53',
|
||||
),
|
||||
'phar-io/version' =>
|
||||
array (
|
||||
'pretty_version' => '3.2.1',
|
||||
'version' => '3.2.1.0',
|
||||
'reference' => '4f7fd7836c6f332bb2933569e566a0d6c4cbed74',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phar-io/version',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpdocumentor/reflection-common' => array(
|
||||
'reference' => '4f7fd7836c6f332bb2933569e566a0d6c4cbed74',
|
||||
),
|
||||
'phpdocumentor/reflection-common' =>
|
||||
array (
|
||||
'pretty_version' => '2.2.0',
|
||||
'version' => '2.2.0.0',
|
||||
'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpdocumentor/reflection-common',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpdocumentor/reflection-docblock' => array(
|
||||
'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b',
|
||||
),
|
||||
'phpdocumentor/reflection-docblock' =>
|
||||
array (
|
||||
'pretty_version' => '5.3.0',
|
||||
'version' => '5.3.0.0',
|
||||
'reference' => '622548b623e81ca6d78b721c5e029f4ce664f170',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpdocumentor/reflection-docblock',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpdocumentor/type-resolver' => array(
|
||||
'reference' => '622548b623e81ca6d78b721c5e029f4ce664f170',
|
||||
),
|
||||
'phpdocumentor/type-resolver' =>
|
||||
array (
|
||||
'pretty_version' => '1.6.1',
|
||||
'version' => '1.6.1.0',
|
||||
'reference' => '77a32518733312af16a44300404e945338981de3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpdocumentor/type-resolver',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpspec/prophecy' => array(
|
||||
'reference' => '77a32518733312af16a44300404e945338981de3',
|
||||
),
|
||||
'phpspec/prophecy' =>
|
||||
array (
|
||||
'pretty_version' => 'v1.15.0',
|
||||
'version' => '1.15.0.0',
|
||||
'reference' => 'bbcd7380b0ebf3961ee21409db7b38bc31d69a13',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpspec/prophecy',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpstan/phpstan' => array(
|
||||
'reference' => 'bbcd7380b0ebf3961ee21409db7b38bc31d69a13',
|
||||
),
|
||||
'phpstan/phpstan' =>
|
||||
array (
|
||||
'pretty_version' => '1.10.3',
|
||||
'version' => '1.10.3.0',
|
||||
'reference' => '5419375b5891add97dc74be71e6c1c34baaddf64',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpstan/phpstan',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpunit/php-code-coverage' => array(
|
||||
'reference' => '5419375b5891add97dc74be71e6c1c34baaddf64',
|
||||
),
|
||||
'phpunit/php-code-coverage' =>
|
||||
array (
|
||||
'pretty_version' => '9.2.15',
|
||||
'version' => '9.2.15.0',
|
||||
'reference' => '2e9da11878c4202f97915c1cb4bb1ca318a63f5f',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpunit/php-code-coverage',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpunit/php-file-iterator' => array(
|
||||
'reference' => '2e9da11878c4202f97915c1cb4bb1ca318a63f5f',
|
||||
),
|
||||
'phpunit/php-file-iterator' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.6',
|
||||
'version' => '3.0.6.0',
|
||||
'reference' => 'cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpunit/php-file-iterator',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpunit/php-invoker' => array(
|
||||
'reference' => 'cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf',
|
||||
),
|
||||
'phpunit/php-invoker' =>
|
||||
array (
|
||||
'pretty_version' => '3.1.1',
|
||||
'version' => '3.1.1.0',
|
||||
'reference' => '5a10147d0aaf65b58940a0b72f71c9ac0423cc67',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpunit/php-invoker',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpunit/php-text-template' => array(
|
||||
'reference' => '5a10147d0aaf65b58940a0b72f71c9ac0423cc67',
|
||||
),
|
||||
'phpunit/php-text-template' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.4',
|
||||
'version' => '2.0.4.0',
|
||||
'reference' => '5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpunit/php-text-template',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpunit/php-timer' => array(
|
||||
'reference' => '5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28',
|
||||
),
|
||||
'phpunit/php-timer' =>
|
||||
array (
|
||||
'pretty_version' => '5.0.3',
|
||||
'version' => '5.0.3.0',
|
||||
'reference' => '5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpunit/php-timer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'phpunit/phpunit' => array(
|
||||
'reference' => '5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2',
|
||||
),
|
||||
'phpunit/phpunit' =>
|
||||
array (
|
||||
'pretty_version' => '9.5.16',
|
||||
'version' => '9.5.16.0',
|
||||
'reference' => '5ff8c545a50226c569310a35f4fa89d79f1ddfdc',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpunit/phpunit',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/cli-parser' => array(
|
||||
'reference' => '5ff8c545a50226c569310a35f4fa89d79f1ddfdc',
|
||||
),
|
||||
'psr/cache' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'aa5030cfa5405eccfdcb1083ce040c2cb8d253bf',
|
||||
),
|
||||
'psr/log' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001',
|
||||
),
|
||||
'sebastian/cli-parser' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => '442e7c7e687e42adc03470c7b668bc4b2402c0b2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/cli-parser',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/code-unit' => array(
|
||||
'reference' => '442e7c7e687e42adc03470c7b668bc4b2402c0b2',
|
||||
),
|
||||
'sebastian/code-unit' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.8',
|
||||
'version' => '1.0.8.0',
|
||||
'reference' => '1fc9f64c0927627ef78ba436c9b17d967e68e120',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/code-unit',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/code-unit-reverse-lookup' => array(
|
||||
'reference' => '1fc9f64c0927627ef78ba436c9b17d967e68e120',
|
||||
),
|
||||
'sebastian/code-unit-reverse-lookup' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.3',
|
||||
'version' => '2.0.3.0',
|
||||
'reference' => 'ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/code-unit-reverse-lookup',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/comparator' => array(
|
||||
'reference' => 'ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5',
|
||||
),
|
||||
'sebastian/comparator' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.6',
|
||||
'version' => '4.0.6.0',
|
||||
'reference' => '55f4261989e546dc112258c7a75935a81a7ce382',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/comparator',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/complexity' => array(
|
||||
'reference' => '55f4261989e546dc112258c7a75935a81a7ce382',
|
||||
),
|
||||
'sebastian/complexity' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.2',
|
||||
'version' => '2.0.2.0',
|
||||
'reference' => '739b35e53379900cc9ac327b2147867b8b6efd88',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/complexity',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/diff' => array(
|
||||
'reference' => '739b35e53379900cc9ac327b2147867b8b6efd88',
|
||||
),
|
||||
'sebastian/diff' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.4',
|
||||
'version' => '4.0.4.0',
|
||||
'reference' => '3461e3fccc7cfdfc2720be910d3bd73c69be590d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/diff',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/environment' => array(
|
||||
'reference' => '3461e3fccc7cfdfc2720be910d3bd73c69be590d',
|
||||
),
|
||||
'sebastian/environment' =>
|
||||
array (
|
||||
'pretty_version' => '5.1.4',
|
||||
'version' => '5.1.4.0',
|
||||
'reference' => '1b5dff7bb151a4db11d49d90e5408e4e938270f7',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/environment',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/exporter' => array(
|
||||
'reference' => '1b5dff7bb151a4db11d49d90e5408e4e938270f7',
|
||||
),
|
||||
'sebastian/exporter' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.4',
|
||||
'version' => '4.0.4.0',
|
||||
'reference' => '65e8b7db476c5dd267e65eea9cab77584d3cfff9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/exporter',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/global-state' => array(
|
||||
'reference' => '65e8b7db476c5dd267e65eea9cab77584d3cfff9',
|
||||
),
|
||||
'sebastian/global-state' =>
|
||||
array (
|
||||
'pretty_version' => '5.0.5',
|
||||
'version' => '5.0.5.0',
|
||||
'reference' => '0ca8db5a5fc9c8646244e629625ac486fa286bf2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/global-state',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/lines-of-code' => array(
|
||||
'reference' => '0ca8db5a5fc9c8646244e629625ac486fa286bf2',
|
||||
),
|
||||
'sebastian/lines-of-code' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.3',
|
||||
'version' => '1.0.3.0',
|
||||
'reference' => 'c1c2e997aa3146983ed888ad08b15470a2e22ecc',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/lines-of-code',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/object-enumerator' => array(
|
||||
'reference' => 'c1c2e997aa3146983ed888ad08b15470a2e22ecc',
|
||||
),
|
||||
'sebastian/object-enumerator' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.4',
|
||||
'version' => '4.0.4.0',
|
||||
'reference' => '5c9eeac41b290a3712d88851518825ad78f45c71',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/object-enumerator',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/object-reflector' => array(
|
||||
'reference' => '5c9eeac41b290a3712d88851518825ad78f45c71',
|
||||
),
|
||||
'sebastian/object-reflector' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.4',
|
||||
'version' => '2.0.4.0',
|
||||
'reference' => 'b4f479ebdbf63ac605d183ece17d8d7fe49c15c7',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/object-reflector',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/recursion-context' => array(
|
||||
'reference' => 'b4f479ebdbf63ac605d183ece17d8d7fe49c15c7',
|
||||
),
|
||||
'sebastian/recursion-context' =>
|
||||
array (
|
||||
'pretty_version' => '4.0.4',
|
||||
'version' => '4.0.4.0',
|
||||
'reference' => 'cd9d8cf3c5804de4341c283ed787f099f5506172',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/recursion-context',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/resource-operations' => array(
|
||||
'reference' => 'cd9d8cf3c5804de4341c283ed787f099f5506172',
|
||||
),
|
||||
'sebastian/resource-operations' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.3',
|
||||
'version' => '3.0.3.0',
|
||||
'reference' => '0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/resource-operations',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/type' => array(
|
||||
'reference' => '0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8',
|
||||
),
|
||||
'sebastian/type' =>
|
||||
array (
|
||||
'pretty_version' => '2.3.4',
|
||||
'version' => '2.3.4.0',
|
||||
'reference' => 'b8cd8a1c753c90bc1a0f5372170e3e489136f914',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/type',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'sebastian/version' => array(
|
||||
'reference' => 'b8cd8a1c753c90bc1a0f5372170e3e489136f914',
|
||||
),
|
||||
'sebastian/version' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.2',
|
||||
'version' => '3.0.2.0',
|
||||
'reference' => 'c6c1022351a901512170118436c764e473f6de8c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../sebastian/version',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'spomky-labs/otphp' => array(
|
||||
'reference' => 'c6c1022351a901512170118436c764e473f6de8c',
|
||||
),
|
||||
'spomky-labs/otphp' =>
|
||||
array (
|
||||
'pretty_version' => 'v10.0.3',
|
||||
'version' => '10.0.3.0',
|
||||
'reference' => '9784d9f7c790eed26e102d6c78f12c754036c366',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../spomky-labs/otphp',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'thecodingmachine/safe' => array(
|
||||
'reference' => '9784d9f7c790eed26e102d6c78f12c754036c366',
|
||||
),
|
||||
'thecodingmachine/safe' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.2.2',
|
||||
'version' => '2.2.2.0',
|
||||
'reference' => '440284f9592c9df402832452a6871a8b3c48d97e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../thecodingmachine/safe',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'theseer/tokenizer' => array(
|
||||
'reference' => '440284f9592c9df402832452a6871a8b3c48d97e',
|
||||
),
|
||||
'theseer/tokenizer' =>
|
||||
array (
|
||||
'pretty_version' => '1.2.1',
|
||||
'version' => '1.2.1.0',
|
||||
'reference' => '34a41e998c2183e22995f158c581e7b5e755ab9e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../theseer/tokenizer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'webmozart/assert' => array(
|
||||
'reference' => '34a41e998c2183e22995f158c581e7b5e755ab9e',
|
||||
),
|
||||
'webmozart/assert' =>
|
||||
array (
|
||||
'pretty_version' => '1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../webmozart/assert',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
|
@ -0,0 +1,44 @@
|
|||
name: Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
|
||||
name: PHP ${{ matrix.php-versions }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
coverage: xdebug
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composercache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.composercache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
composer install \
|
||||
--no-interaction \
|
||||
--no-ansi \
|
||||
--no-progress
|
||||
|
||||
- name: Run lint
|
||||
run: composer lint
|
||||
|
||||
- name: Run test
|
||||
run: composer test
|
|
@ -0,0 +1,17 @@
|
|||
# Please do not use this ignore file to define platform specific files.
|
||||
#
|
||||
# For these purposes create a global .gitignore file, which is a list of rules
|
||||
# for ignoring files in every Git repository on your computer.
|
||||
#
|
||||
# https://help.github.com/articles/ignoring-files/#create-a-global-gitignore
|
||||
|
||||
jaeger-idl
|
||||
vendor
|
||||
|
||||
composer.lock
|
||||
composer.phar
|
||||
|
||||
jaeger-client-php.iml
|
||||
|
||||
phpunit.xml
|
||||
phpcs.xml
|
|
@ -0,0 +1,3 @@
|
|||
# How to Contribute to Jaeger
|
||||
|
||||
We'd love your help!
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 Jonah George, José Carlos Chávez
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), 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 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
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,219 @@
|
|||
![Build Status](https://github.com/jonahgeorge/jaeger-client-php/workflows/Test/badge.svg) [![PHP version][packagist-img]][packagist]
|
||||
|
||||
# Jaeger Bindings for PHP OpenTracing API
|
||||
|
||||
This is a client-side library that can be used to instrument PHP apps for distributed trace collection,
|
||||
and to send those traces to Jaeger. See the [OpenTracing PHP API](https://github.com/opentracing/opentracing-php)
|
||||
for additional detail.
|
||||
|
||||
## Contributing and Developing
|
||||
|
||||
Please see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
||||
|
||||
## Installation
|
||||
|
||||
Jaeger client can be installed via Composer:
|
||||
|
||||
```bash
|
||||
composer require jonahgeorge/jaeger-client-php
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use Jaeger\Config;
|
||||
use OpenTracing\GlobalTracer;
|
||||
|
||||
$config = new Config(
|
||||
[
|
||||
'sampler' => [
|
||||
'type' => Jaeger\SAMPLER_TYPE_CONST,
|
||||
'param' => true,
|
||||
],
|
||||
'logging' => true,
|
||||
],
|
||||
'your-app-name'
|
||||
);
|
||||
$config->initializeTracer();
|
||||
|
||||
$tracer = GlobalTracer::get();
|
||||
|
||||
$scope = $tracer->startActiveSpan('TestSpan', []);
|
||||
$scope->close();
|
||||
|
||||
$tracer->flush();
|
||||
```
|
||||
|
||||
### Samplers
|
||||
|
||||
List of supported samplers, for more info about samplers, please read [Jaeger Sampling](https://www.jaegertracing.io/docs/1.9/sampling/) guide.
|
||||
|
||||
#### Const sampler
|
||||
This sampler either samples everything, or nothing.
|
||||
|
||||
##### Configuration
|
||||
```
|
||||
'sampler' => [
|
||||
'type' => Jaeger\SAMPLER_TYPE_CONST,
|
||||
'param' => true, // boolean wheter to trace or not
|
||||
],
|
||||
```
|
||||
|
||||
#### Probabilistic sampler
|
||||
This sampler samples request by given rate.
|
||||
|
||||
##### Configuration
|
||||
```
|
||||
'sampler' => [
|
||||
'type' => Jaeger\SAMPLER_TYPE_PROBABILISTIC,
|
||||
'param' => 0.5, // float [0.0, 1.0]
|
||||
],
|
||||
```
|
||||
|
||||
#### Rate limiting sampler
|
||||
Samples maximum specified number of traces (requests) per second.
|
||||
|
||||
##### Requirements
|
||||
* `psr/cache` PSR-6 cache component to store and retrieve sampler state between requests.
|
||||
Cache component is passed to `Jaeger\Config` trough its constructor.
|
||||
* `hrtime()` function, that can retrieve time in nanoseconds. You need either `php 7.3` or [PECL/hrtime](http://pecl.php.net/package/hrtime) extension.
|
||||
|
||||
##### Configuration
|
||||
```
|
||||
'sampler' => [
|
||||
'type' => Jaeger\SAMPLER_TYPE_RATE_LIMITING,
|
||||
'param' => 100 // integer maximum number of traces per second,
|
||||
'cache' => [
|
||||
'currentBalanceKey' => 'rate.currentBalance' // string
|
||||
'lastTickKey' => 'rate.lastTick' // string
|
||||
]
|
||||
],
|
||||
```
|
||||
## Dispatch mode
|
||||
|
||||
The library supports 3 ways of sending data to Jaeger Agent:
|
||||
|
||||
1. `Zipkin.thrift` over Compact protocol (socket - UDP) - default
|
||||
2. `Jaeger.thrift` over Binary protocol (socket - UDP)
|
||||
2. `Jaeger.thrift` over Binary protocol (HTTP)
|
||||
|
||||
If you want to enable "`Jaeger.thrift` over Binary protocol" one or other, than
|
||||
you need to set `dispatch_mode` config option or `JAEGER_DISPATCH_MODE` env
|
||||
variable.
|
||||
|
||||
Allowed values for `dispatch_mode` are:
|
||||
- `jaeger_over_binary_udp`
|
||||
- `jaeger_over_binary_http`
|
||||
- `zipkin_over_compact_udp`
|
||||
|
||||
There are 3 constants available, so it is better to use them:
|
||||
```php
|
||||
class Config
|
||||
{
|
||||
const ZIPKIN_OVER_COMPACT_UDP = "zipkin_over_compact_udp";
|
||||
const JAEGER_OVER_BINARY_UDP = "jaeger_over_binary_udp";
|
||||
const JAEGER_OVER_BINARY_HTTP = "jaeger_over_binary_http";
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
A possible config with custom `dispatch_mode` can look like this:
|
||||
```php
|
||||
// config.php
|
||||
|
||||
use Jaeger\Config;
|
||||
|
||||
return [
|
||||
'sampler' => [
|
||||
'type' => Jaeger\SAMPLER_TYPE_CONST,
|
||||
'param' => true,
|
||||
],
|
||||
'logging' => true,
|
||||
"tags" => [
|
||||
// process. prefix works only with JAEGER_OVER_HTTP, JAEGER_OVER_BINARY
|
||||
// otherwise it will be shown as simple global tag
|
||||
"process.process-tag-key-1" => "process-value-1", // all tags with `process.` prefix goes to process section
|
||||
"process.process-tag-key-2" => "process-value-2", // all tags with `process.` prefix goes to process section
|
||||
"global-tag-key-1" => "global-tag-value-1", // this tag will be appended to all spans
|
||||
"global-tag-key-2" => "global-tag-value-2", // this tag will be appended to all spans
|
||||
],
|
||||
"local_agent" => [
|
||||
"reporting_host" => "localhost",
|
||||
// You can override port by setting local_agent.reporting_port value
|
||||
"reporting_port" => 6832
|
||||
],
|
||||
// Different ways to send data to Jaeger. Config::ZIPKIN_OVER_COMPACT - default):
|
||||
'dispatch_mode' => Config::JAEGER_OVER_BINARY_UDP,
|
||||
];
|
||||
```
|
||||
The full example you can see at `examples` directory.
|
||||
|
||||
By default, for each `dispatch_mode` there is default `reporting_port` config value. Table with
|
||||
default values you can see below:
|
||||
|
||||
`dispatch_mode` | default `reporting_port`
|
||||
------------------------ | ----------------
|
||||
ZIPKIN_OVER_COMPACT_UDP | 5775
|
||||
JAEGER_OVER_BINARY_UDP | 6832
|
||||
JAEGER_OVER_BINARY_HTTP | 14268
|
||||
|
||||
## IPv6
|
||||
|
||||
In case you need IPv6 support you need to set `ip_version` Config variable.
|
||||
By default, IPv4 is used. There is an alias `Config::IP_VERSION` which you can use
|
||||
as an alternative to raw `ip_version`.
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
use Jaeger\Config;
|
||||
|
||||
$config = new Config(
|
||||
[
|
||||
"ip_version" => Config::IPV6, // <-- or use Config::IP_VERSION constant
|
||||
'logging' => true,
|
||||
'dispatch_mode' => Config::JAEGER_OVER_BINARY_UDP,
|
||||
],
|
||||
'serviceNameExample',
|
||||
);
|
||||
$config->initializeTracer();
|
||||
```
|
||||
or
|
||||
|
||||
```php
|
||||
use Jaeger\Config;
|
||||
|
||||
$config = new Config(
|
||||
[
|
||||
Config::IP_VERSION => Config::IPV6, // <--
|
||||
'logging' => true,
|
||||
'dispatch_mode' => Config::JAEGER_OVER_BINARY_UDP,
|
||||
],
|
||||
'serviceNameExample',
|
||||
);
|
||||
$config->initializeTracer();
|
||||
```
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
Tests are located in the `tests` directory. See [tests/README.md](./tests/README.md).
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [Support Span baggage](https://github.com/jonahgeorge/jaeger-client-php/issues/5)
|
||||
- [Support Tracer metrics](https://github.com/jonahgeorge/jaeger-client-php/issues/12)
|
||||
- [Support Tracer error reporting](https://github.com/jonahgeorge/jaeger-client-php/issues/13)
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](./LICENSE).
|
||||
|
||||
[ci-img]: https://travis-ci.org/jonahgeorge/jaeger-client-php.svg?branch=travis
|
||||
[ci]: https://travis-ci.org/jonahgeorge/jaeger-client-php
|
||||
[packagist-img]: https://badge.fury.io/ph/jonahgeorge%2Fjaeger-client-php.svg
|
||||
[packagist]: https://badge.fury.io/ph/jonahgeorge%2Fjaeger-client-php
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"name": "jonahgeorge/jaeger-client-php",
|
||||
"description": "Jaeger Bindings for PHP OpenTracing API",
|
||||
"keywords": [
|
||||
"jaeger",
|
||||
"opentracing",
|
||||
"trace",
|
||||
"tracing"
|
||||
],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jonah George",
|
||||
"homepage": "http://twitter.com/jonahgeorge"
|
||||
},
|
||||
{
|
||||
"name": "José Carlos Chávez",
|
||||
"email": "jcchavezs@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Contributors",
|
||||
"homepage": "https://github.com/jonahgeorge/jaeger-client-php/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0 || ^8.1",
|
||||
"ext-sockets": "*",
|
||||
"opentracing/opentracing": "^1.0",
|
||||
"packaged/thrift": "^0.13",
|
||||
"psr/cache": "^1.0 || ^2.0 || ^3.0",
|
||||
"psr/log": "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7 || ^8 || ^9",
|
||||
"squizlabs/php_codesniffer": "3.*",
|
||||
"cache/array-adapter": "^1.0",
|
||||
"symfony/polyfill-php73": "^1.10"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Jaeger\\": "src/Jaeger/"
|
||||
},
|
||||
"files": [
|
||||
"./src/Jaeger/Constants.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"Jaeger\\Tests\\": "tests/Jaeger/"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"scripts": {
|
||||
"fix-lint": "./vendor/bin/phpcbf",
|
||||
"lint": "./vendor/bin/phpcs",
|
||||
"test": "./vendor/bin/phpunit"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use Jaeger\Config;
|
||||
|
||||
return [
|
||||
'sampler' => [
|
||||
'type' => Jaeger\SAMPLER_TYPE_CONST,
|
||||
'param' => true,
|
||||
],
|
||||
'logging' => true,
|
||||
"tags" => [
|
||||
// process. prefix works only with JAEGER_OVER_HTTP, JAEGER_OVER_BINARY
|
||||
// otherwise it will be shown as simple global tag
|
||||
"process.process-tag-key-1" => "process-value-1", // all tags with `process.` prefix goes to process section
|
||||
"process.process-tag-key-2" => "process-value-2", // all tags with `process.` prefix goes to process section
|
||||
"global-tag-key-1" => "global-tag-value-1", // this tag will be appended to all spans
|
||||
"global-tag-key-2" => "global-tag-value-2", // this tag will be appended to all spans
|
||||
],
|
||||
"local_agent" => [
|
||||
"reporting_host" => "localhost",
|
||||
// You can override port by setting local_agent.reporting_port value
|
||||
// "reporting_port" => 6832
|
||||
],
|
||||
// Different ways to send data to Jaeger. Config::ZIPKIN_OVER_COMPACT - default):
|
||||
'dispatch_mode' => Config::JAEGER_OVER_BINARY_UDP,
|
||||
];
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use Jaeger\Config;
|
||||
use OpenTracing\GlobalTracer;
|
||||
|
||||
$config = new Config(
|
||||
require_once __DIR__.'/config.php',
|
||||
'your-app-name'
|
||||
);
|
||||
|
||||
$config->initializeTracer();
|
||||
|
||||
$tracer = GlobalTracer::get();
|
||||
|
||||
$scope = $tracer->startActiveSpan('JaegerSpan', []);
|
||||
$scope->getSpan()->setTag("tag1", "value1");
|
||||
$scope->getSpan()->setTag("tag2", "value2");
|
||||
$scope->getSpan()->setTag("tag3", "value2");
|
||||
$scope->getSpan()->log([
|
||||
"key1" => "value1",
|
||||
"key2" => 2,
|
||||
"key3" => true
|
||||
]);
|
||||
|
||||
$scope->getSpan()->addBaggageItem("baggage-item1", "baggage-value1");
|
||||
$scope->getSpan()->addBaggageItem("baggage-item2", "baggage-value2");
|
||||
$scope->getSpan()->addBaggageItem("baggage-item3", "baggage-value3");
|
||||
|
||||
$nestedSpanScope = $tracer->startActiveSpan("Nested1");
|
||||
$nestedSpanScope->getSpan()->setTag("tag1", "value1");
|
||||
$nestedSpanScope->getSpan()->setTag("tag2", "value2");
|
||||
$nestedSpanScope->getSpan()->setTag("tag3", "value2");
|
||||
$nestedSpanScope->getSpan()->log([
|
||||
"key1" => "value1",
|
||||
"key2" => 2,
|
||||
"key3" => true
|
||||
]);
|
||||
|
||||
$nestedSpanScope->getSpan()->addBaggageItem("baggage-item1", "baggage-value1");
|
||||
$nestedSpanScope->getSpan()->addBaggageItem("baggage-item2", "baggage-value2");
|
||||
$nestedSpanScope->getSpan()->addBaggageItem("baggage-item3", "baggage-value3");
|
||||
|
||||
sleep(1);
|
||||
|
||||
$nestedSpanScope->close();
|
||||
|
||||
sleep(1);
|
||||
$scope->close();
|
||||
$tracer->flush();
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0"?>
|
||||
<ruleset name="Jaeger">
|
||||
|
||||
<!--
|
||||
The name attribute of the ruleset tag is displayed
|
||||
when running PHP_CodeSniffer with the -v command line
|
||||
argument. The description tag below is not displayed anywhere
|
||||
except in this file, so it can contain information for
|
||||
developers who may change this file in the future.
|
||||
-->
|
||||
<description>The coding standard for Jaeger Client</description>
|
||||
|
||||
<!-- Show sniff codes in all reports -->
|
||||
<arg value="s"/>
|
||||
|
||||
<!-- Use PSR-2 as a base -->
|
||||
<rule ref="PSR2"/>
|
||||
|
||||
<!-- Uncomment to use colors in progress or report -->
|
||||
<!-- arg name="colors" / -->
|
||||
|
||||
<!--
|
||||
If no files or directories are specified on the command line
|
||||
your custom standard can specify what files should be checked
|
||||
instead.
|
||||
Note that specifying any file or directory path
|
||||
on the command line will ignore all file tags.
|
||||
-->
|
||||
<file>src</file>
|
||||
|
||||
<!--
|
||||
You can hard-code ignore patterns directly into your
|
||||
custom standard so you don't have to specify the
|
||||
patterns on the command line.
|
||||
-->
|
||||
<exclude-pattern>src/Jaeger/Thrift/*</exclude-pattern>
|
||||
</ruleset>
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src/Jaeger</directory>
|
||||
<exclude>
|
||||
<directory suffix="Interface.php">src/</directory>
|
||||
<file>src/Jaeger/Constants.php</file>
|
||||
<file>src/Jaeger/Thrift/Agent/AgentIf.php</file>
|
||||
<file>src/Jaeger/Thrift/Agent/AggregationValidatorIf.php</file>
|
||||
<file>src/Jaeger/Thrift/Agent/BaggageRestrictionManagerIf.php</file>
|
||||
<file>src/Jaeger/Thrift/Agent/DependencyIf.php</file>
|
||||
<file>src/Jaeger/Thrift/Agent/SamplingManagerIf.php</file>
|
||||
<file>src/Jaeger/Thrift/CollectorIf.php</file>
|
||||
<file>src/Jaeger/Thrift/Crossdock/TracedServiceIf.php</file>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Jaeger Test Suite">
|
||||
<directory suffix=".php">tests/Jaeger</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<php>
|
||||
<ini name="date.timezone" value="UTC"/>
|
||||
<ini name="display_errors" value="on"/>
|
||||
<ini name="display_startup_errors" value="on"/>
|
||||
</php>
|
||||
|
||||
<logging>
|
||||
<log
|
||||
type="coverage-text"
|
||||
target="php://stdout"
|
||||
lowUpperBound="60"
|
||||
highLowerBound="90"/>
|
||||
|
||||
<log
|
||||
type="coverage-clover"
|
||||
target="build/coverage.xml"/>
|
||||
</logging>
|
||||
</phpunit>
|
|
@ -0,0 +1,27 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
# checkout jaeger thrift files
|
||||
rm -rf jaeger-idl
|
||||
git clone https://github.com/jaegertracing/jaeger-idl
|
||||
|
||||
# define thrift cmd
|
||||
THRIFT="docker run -u $(id -u) -v '${PWD}:/data' thrift:0.11.0 thrift -o /data/jaeger-idl"
|
||||
THRIFT_CMD="${THRIFT} --gen php:psr4,oop"
|
||||
|
||||
# generate php files
|
||||
FILES=$(find jaeger-idl/thrift -type f -name \*.thrift)
|
||||
for f in ${FILES}; do
|
||||
echo "${THRIFT_CMD} "/data/${f}""
|
||||
eval $THRIFT_CMD "/data/${f}"
|
||||
done
|
||||
|
||||
# move generated files
|
||||
rm -rf src/Jaeger/Thrift
|
||||
mv jaeger-idl/gen-php/Jaeger/Thrift src/Jaeger/Thrift
|
||||
|
||||
# remove thrift files
|
||||
rm -rf jaeger-idl
|
27
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/AgentClient/HttpAgentClient.php
vendored
Normal file
27
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/AgentClient/HttpAgentClient.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\AgentClient;
|
||||
|
||||
class HttpAgentClient implements \Jaeger\Thrift\Agent\AgentIf
|
||||
{
|
||||
protected $input_ = null;
|
||||
protected $output_ = null;
|
||||
|
||||
protected $seqid_ = 0;
|
||||
|
||||
public function __construct($input, $output = null)
|
||||
{
|
||||
$this->input_ = $input;
|
||||
$this->output_ = $output ? $output : $input;
|
||||
}
|
||||
|
||||
public function emitZipkinBatch(array $spans)
|
||||
{
|
||||
}
|
||||
|
||||
public function emitBatch(\Jaeger\Thrift\Batch $batch)
|
||||
{
|
||||
$batch->write($this->output_);
|
||||
$this->output_->getTransport()->flush();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Codec;
|
||||
|
||||
use Jaeger\SpanContext;
|
||||
use OpenTracing\UnsupportedFormatException;
|
||||
|
||||
class BinaryCodec implements CodecInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see \Jaeger\Tracer::inject
|
||||
*
|
||||
* @param SpanContext $spanContext
|
||||
* @param mixed $carrier
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function inject(SpanContext $spanContext, &$carrier)
|
||||
{
|
||||
throw new UnsupportedFormatException('Binary encoding not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see \Jaeger\Tracer::extract
|
||||
*
|
||||
* @param mixed $carrier
|
||||
* @return SpanContext|null
|
||||
*
|
||||
* @throws UnsupportedFormatException
|
||||
*/
|
||||
public function extract($carrier)
|
||||
{
|
||||
throw new UnsupportedFormatException('Binary encoding not implemented');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Codec;
|
||||
|
||||
use Jaeger\SpanContext;
|
||||
|
||||
interface CodecInterface
|
||||
{
|
||||
/**
|
||||
* Handle the logic behind injecting propagation scheme specific information into the carrier
|
||||
* (e.g. http request headers, amqp message headers, etc.).
|
||||
*
|
||||
* This method can modify the carrier.
|
||||
*
|
||||
* @see \Jaeger\Tracer::inject
|
||||
*
|
||||
* @param SpanContext $spanContext
|
||||
* @param mixed $carrier
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function inject(SpanContext $spanContext, &$carrier);
|
||||
|
||||
/**
|
||||
* Handle the logic behind extracting propagation-scheme specific information from carrier
|
||||
* (e.g. http request headers, amqp message headers, etc.).
|
||||
*
|
||||
* This method must not modify the carrier.
|
||||
*
|
||||
* @see \Jaeger\Tracer::extract
|
||||
*
|
||||
* @param mixed $carrier
|
||||
* @return SpanContext|null
|
||||
*/
|
||||
public function extract($carrier);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Codec;
|
||||
|
||||
class CodecUtility
|
||||
{
|
||||
|
||||
/**
|
||||
* Incoming trace/span IDs are hex representations of 64-bit values. PHP
|
||||
* represents ints internally as signed 32- or 64-bit values, but base_convert
|
||||
* converts to string representations of arbitrarily large positive numbers.
|
||||
* This means at least half the incoming IDs will be larger than PHP_INT_MAX.
|
||||
*
|
||||
* Thrift, while building a binary representation of the IDs, performs bitwise
|
||||
* operations on the string values, implicitly casting to int and capping them
|
||||
* at PHP_INT_MAX. So, incoming IDs larger than PHP_INT_MAX will be serialized
|
||||
* and sent to the agent as PHP_INT_MAX, breaking trace/span correlation.
|
||||
*
|
||||
* This method therefore, on 64-bit architectures, splits the hex string into
|
||||
* high and low values, converts them separately to ints, and manually combines
|
||||
* them into a proper signed int. This int is then handled properly by the
|
||||
* Thrift package.
|
||||
*
|
||||
* On 32-bit architectures, it falls back to base_convert.
|
||||
*
|
||||
* @param string $hex
|
||||
* @return string|int
|
||||
*/
|
||||
public static function hexToInt64($hex)
|
||||
{
|
||||
// If we're on a 32-bit architecture, fall back to base_convert.
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
return base_convert($hex, 16, 10);
|
||||
}
|
||||
|
||||
$hi = intval(substr($hex, -16, -8), 16);
|
||||
$lo = intval(substr($hex, -8, 8), 16);
|
||||
|
||||
return $hi << 32 | $lo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Codec;
|
||||
|
||||
use Exception;
|
||||
use Jaeger\SpanContext;
|
||||
|
||||
use const Jaeger\TRACE_ID_HEADER;
|
||||
use const Jaeger\BAGGAGE_HEADER_PREFIX;
|
||||
use const Jaeger\DEBUG_ID_HEADER_KEY;
|
||||
|
||||
class TextCodec implements CodecInterface
|
||||
{
|
||||
private $urlEncoding;
|
||||
private $traceIdHeader;
|
||||
private $baggagePrefix;
|
||||
private $debugIdHeader;
|
||||
private $prefixLength;
|
||||
|
||||
/**
|
||||
* @param bool $urlEncoding
|
||||
* @param string $traceIdHeader
|
||||
* @param string $baggageHeaderPrefix
|
||||
* @param string $debugIdHeader
|
||||
*/
|
||||
public function __construct(
|
||||
bool $urlEncoding = false,
|
||||
string $traceIdHeader = TRACE_ID_HEADER,
|
||||
string $baggageHeaderPrefix = BAGGAGE_HEADER_PREFIX,
|
||||
string $debugIdHeader = DEBUG_ID_HEADER_KEY
|
||||
) {
|
||||
$this->urlEncoding = $urlEncoding;
|
||||
$this->traceIdHeader = str_replace('_', '-', strtolower($traceIdHeader));
|
||||
$this->baggagePrefix = str_replace('_', '-', strtolower($baggageHeaderPrefix));
|
||||
$this->debugIdHeader = str_replace('_', '-', strtolower($debugIdHeader));
|
||||
$this->prefixLength = strlen($baggageHeaderPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see \Jaeger\Tracer::inject
|
||||
*
|
||||
* @param SpanContext $spanContext
|
||||
* @param mixed $carrier
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function inject(SpanContext $spanContext, &$carrier)
|
||||
{
|
||||
$carrier[$this->traceIdHeader] = $this->spanContextToString(
|
||||
$spanContext->getTraceId(),
|
||||
$spanContext->getSpanId(),
|
||||
$spanContext->getParentId(),
|
||||
$spanContext->getFlags()
|
||||
);
|
||||
|
||||
$baggage = $spanContext->getBaggage();
|
||||
if (empty($baggage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($baggage as $key => $value) {
|
||||
$encodedValue = $value;
|
||||
|
||||
if ($this->urlEncoding) {
|
||||
$encodedValue = urlencode($value);
|
||||
}
|
||||
|
||||
$carrier[$this->baggagePrefix . $key] = $encodedValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see \Jaeger\Tracer::extract
|
||||
*
|
||||
* @param mixed $carrier
|
||||
* @return SpanContext|null
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function extract($carrier)
|
||||
{
|
||||
$traceId = null;
|
||||
$spanId = null;
|
||||
$parentId = null;
|
||||
$flags = null;
|
||||
$baggage = null;
|
||||
$debugId = null;
|
||||
|
||||
foreach ($carrier as $key => $value) {
|
||||
$ucKey = strtolower($key);
|
||||
|
||||
if ($ucKey === $this->traceIdHeader) {
|
||||
if ($this->urlEncoding) {
|
||||
$value = urldecode($value);
|
||||
}
|
||||
list($traceId, $spanId, $parentId, $flags) =
|
||||
$this->spanContextFromString($value);
|
||||
} elseif ($this->startsWith($ucKey, $this->baggagePrefix)) {
|
||||
if ($this->urlEncoding) {
|
||||
$value = urldecode($value);
|
||||
}
|
||||
$attrKey = substr($key, $this->prefixLength);
|
||||
if ($baggage === null) {
|
||||
$baggage = [strtolower($attrKey) => $value];
|
||||
} else {
|
||||
$baggage[strtolower($attrKey)] = $value;
|
||||
}
|
||||
} elseif ($ucKey === $this->debugIdHeader) {
|
||||
if ($this->urlEncoding) {
|
||||
$value = urldecode($value);
|
||||
}
|
||||
$debugId = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($traceId === null && $baggage !== null) {
|
||||
throw new Exception('baggage without trace ctx');
|
||||
}
|
||||
|
||||
if ($traceId === null) {
|
||||
if ($debugId !== null) {
|
||||
return new SpanContext(null, null, null, null, [], $debugId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return new SpanContext($traceId, $spanId, $parentId, $flags, $baggage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a span context to a string.
|
||||
*
|
||||
* @param int $traceId
|
||||
* @param int $spanId
|
||||
* @param int $parentId
|
||||
* @param int $flags
|
||||
* @return string
|
||||
*/
|
||||
private function spanContextToString($traceId, $spanId, $parentId, $flags)
|
||||
{
|
||||
$parentId = $parentId ?? 0;
|
||||
return sprintf('%x:%x:%x:%x', $traceId, $spanId, $parentId, $flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a span context from a string.
|
||||
*
|
||||
* @param string $value
|
||||
* @return array
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function spanContextFromString($value): array
|
||||
{
|
||||
$parts = explode(':', $value);
|
||||
|
||||
if (count($parts) != 4) {
|
||||
throw new Exception('Malformed tracer state string.');
|
||||
}
|
||||
|
||||
return [
|
||||
CodecUtility::hexToInt64($parts[0]),
|
||||
CodecUtility::hexToInt64($parts[1]),
|
||||
CodecUtility::hexToInt64($parts[2]),
|
||||
$parts[3],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a string ($haystack) starts with a given prefix ($needle).
|
||||
*
|
||||
* @param string $haystack
|
||||
* @param string $needle
|
||||
* @return bool
|
||||
*/
|
||||
private function startsWith(string $haystack, string $needle): bool
|
||||
{
|
||||
return substr($haystack, 0, strlen($needle)) == $needle;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Codec;
|
||||
|
||||
use Jaeger\SpanContext;
|
||||
|
||||
use const Jaeger\DEBUG_FLAG;
|
||||
use const Jaeger\SAMPLED_FLAG;
|
||||
|
||||
class ZipkinCodec implements CodecInterface
|
||||
{
|
||||
const SAMPLED_NAME = 'X-B3-Sampled';
|
||||
const TRACE_ID_NAME = 'X-B3-TraceId';
|
||||
const SPAN_ID_NAME = 'X-B3-SpanId';
|
||||
const PARENT_ID_NAME = 'X-B3-ParentSpanId';
|
||||
const FLAGS_NAME = 'X-B3-Flags';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see \Jaeger\Tracer::inject
|
||||
*
|
||||
* @param SpanContext $spanContext
|
||||
* @param mixed $carrier
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function inject(SpanContext $spanContext, &$carrier)
|
||||
{
|
||||
$carrier[self::TRACE_ID_NAME] = dechex($spanContext->getTraceId());
|
||||
$carrier[self::SPAN_ID_NAME] = dechex($spanContext->getSpanId());
|
||||
if ($spanContext->getParentId() != null) {
|
||||
$carrier[self::PARENT_ID_NAME] = dechex($spanContext->getParentId());
|
||||
}
|
||||
$carrier[self::FLAGS_NAME] = (int) $spanContext->getFlags();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @see \Jaeger\Tracer::extract
|
||||
*
|
||||
* @param mixed $carrier
|
||||
* @return SpanContext|null
|
||||
*/
|
||||
public function extract($carrier)
|
||||
{
|
||||
$traceId = "0";
|
||||
$spanId = "0";
|
||||
$parentId = "0";
|
||||
$flags = 0;
|
||||
|
||||
if (isset($carrier[strtolower(self::SAMPLED_NAME)])) {
|
||||
if ($carrier[strtolower(self::SAMPLED_NAME)] === "1" ||
|
||||
strtolower($carrier[strtolower(self::SAMPLED_NAME)] === "true")
|
||||
) {
|
||||
$flags = $flags | SAMPLED_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($carrier[strtolower(self::TRACE_ID_NAME)])) {
|
||||
$traceId = CodecUtility::hexToInt64($carrier[strtolower(self::TRACE_ID_NAME)], 16, 10);
|
||||
}
|
||||
|
||||
if (isset($carrier[strtolower(self::PARENT_ID_NAME)])) {
|
||||
$parentId = CodecUtility::hexToInt64($carrier[strtolower(self::PARENT_ID_NAME)], 16, 10);
|
||||
}
|
||||
|
||||
if (isset($carrier[strtolower(self::SPAN_ID_NAME)])) {
|
||||
$spanId = CodecUtility::hexToInt64($carrier[strtolower(self::SPAN_ID_NAME)], 16, 10);
|
||||
}
|
||||
|
||||
if (isset($carrier[strtolower(self::FLAGS_NAME)])) {
|
||||
if ($carrier[strtolower(self::FLAGS_NAME)] === "1") {
|
||||
$flags = $flags | DEBUG_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
if ($traceId != "0" && $spanId != "0") {
|
||||
return new SpanContext($traceId, $spanId, $parentId, $flags);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,390 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger;
|
||||
|
||||
use Exception;
|
||||
use Jaeger\Reporter\CompositeReporter;
|
||||
use Jaeger\Reporter\LoggingReporter;
|
||||
use Jaeger\Reporter\ReporterInterface;
|
||||
use Jaeger\ReporterFactory\JaegerHttpReporterFactory;
|
||||
use Jaeger\ReporterFactory\JaegerReporterFactory;
|
||||
use Jaeger\ReporterFactory\ZipkinReporterFactory;
|
||||
use Jaeger\Sampler\ConstSampler;
|
||||
use Jaeger\Sampler\ProbabilisticSampler;
|
||||
use Jaeger\Sampler\RateLimitingSampler;
|
||||
use Jaeger\Sampler\SamplerInterface;
|
||||
use Jaeger\Util\RateLimiter;
|
||||
use OpenTracing\GlobalTracer;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
class Config
|
||||
{
|
||||
const IP_VERSION = "ip_version";
|
||||
|
||||
const ZIPKIN_OVER_COMPACT_UDP = "zipkin_over_compact_udp";
|
||||
const JAEGER_OVER_BINARY_UDP = "jaeger_over_binary_udp";
|
||||
const JAEGER_OVER_BINARY_HTTP = "jaeger_over_binary_http";
|
||||
|
||||
const IPV6 = "IPv6";
|
||||
const IPV4 = "IPv4";
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getAvailableDispatchModes()
|
||||
{
|
||||
return [self::ZIPKIN_OVER_COMPACT_UDP, self::JAEGER_OVER_BINARY_UDP, self::JAEGER_OVER_BINARY_HTTP];
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $serviceName;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $initialized = false;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
public function getLogger()
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var CacheItemPoolInterface
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* Config constructor.
|
||||
* @param array $config
|
||||
* @param string|null $serviceName
|
||||
* @param LoggerInterface|null $logger
|
||||
* @param CacheItemPoolInterface|null $cache
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(
|
||||
array $config,
|
||||
string $serviceName = null,
|
||||
LoggerInterface $logger = null,
|
||||
CacheItemPoolInterface $cache = null
|
||||
) {
|
||||
$this->config = $config;
|
||||
|
||||
$this->setConfigFromEnv();
|
||||
|
||||
if (empty($this->config["dispatch_mode"])) {
|
||||
$this->config["dispatch_mode"] = self::ZIPKIN_OVER_COMPACT_UDP;
|
||||
}
|
||||
|
||||
if (empty($this->config[Config::IP_VERSION])) {
|
||||
$this->config[Config::IP_VERSION] = self::IPV4;
|
||||
}
|
||||
|
||||
$this->serviceName = $this->config['service_name'] ?? $serviceName;
|
||||
|
||||
if ($this->serviceName === null) {
|
||||
throw new Exception('service_name required in the config or param.');
|
||||
}
|
||||
|
||||
$this->logger = $logger ?: new NullLogger();
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tracer|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function initializeTracer()
|
||||
{
|
||||
if ($this->initialized) {
|
||||
$this->logger->warning('Jaeger tracer already initialized, skipping');
|
||||
return null;
|
||||
}
|
||||
|
||||
$reporter = $this->getReporter();
|
||||
$sampler = $this->getSampler();
|
||||
|
||||
|
||||
$tracer = $this->createTracer($reporter, $sampler);
|
||||
|
||||
$this->initializeGlobalTracer($tracer);
|
||||
|
||||
return $tracer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReporterInterface $reporter
|
||||
* @param SamplerInterface $sampler
|
||||
* @return Tracer
|
||||
*/
|
||||
public function createTracer(ReporterInterface $reporter, SamplerInterface $sampler): Tracer
|
||||
{
|
||||
return new Tracer(
|
||||
$this->serviceName,
|
||||
$reporter,
|
||||
$sampler,
|
||||
$this->shouldUseOneSpanPerRpc(),
|
||||
$this->logger,
|
||||
null,
|
||||
$this->getTraceIdHeader(),
|
||||
$this->getBaggageHeaderPrefix(),
|
||||
$this->getDebugIdHeaderKey(),
|
||||
$this->getConfiguredTags()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getServiceName(): string
|
||||
{
|
||||
return $this->serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tracer $tracer
|
||||
*/
|
||||
private function initializeGlobalTracer(Tracer $tracer)
|
||||
{
|
||||
GlobalTracer::set($tracer);
|
||||
$this->logger->debug('OpenTracing\GlobalTracer initialized to ' . $tracer->getServiceName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function getLogging(): bool
|
||||
{
|
||||
return (bool)($this->config['logging'] ?? false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ReporterInterface
|
||||
*/
|
||||
private function getReporter(): ReporterInterface
|
||||
{
|
||||
switch ($this->config["dispatch_mode"]) {
|
||||
case self::JAEGER_OVER_BINARY_UDP:
|
||||
$reporter = (new JaegerReporterFactory($this))->createReporter();
|
||||
break;
|
||||
case self::ZIPKIN_OVER_COMPACT_UDP:
|
||||
$reporter = (new ZipkinReporterFactory($this))->createReporter();
|
||||
break;
|
||||
case self::JAEGER_OVER_BINARY_HTTP:
|
||||
$reporter = (new JaegerHttpReporterFactory($this))->createReporter();
|
||||
break;
|
||||
default:
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
"Unsupported `dispatch_mode` value: %s. Allowed values are: %s",
|
||||
$this->config["dispatch_mode"],
|
||||
implode(", ", Config::getAvailableDispatchModes())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->getLogging()) {
|
||||
$reporter = new CompositeReporter($reporter, new LoggingReporter($this->logger));
|
||||
}
|
||||
|
||||
return $reporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SamplerInterface
|
||||
* @throws \Psr\Cache\InvalidArgumentException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getSampler(): SamplerInterface
|
||||
{
|
||||
$samplerConfig = $this->config['sampler'] ?? [];
|
||||
$samplerType = $samplerConfig['type'] ?? null;
|
||||
$samplerParam = $samplerConfig['param'] ?? null;
|
||||
|
||||
if ($samplerType === null || $samplerType === SAMPLER_TYPE_REMOTE) {
|
||||
// todo: implement remote sampling
|
||||
return new ProbabilisticSampler((float)$samplerParam);
|
||||
} elseif ($samplerType === SAMPLER_TYPE_CONST) {
|
||||
return new ConstSampler($samplerParam ?? false);
|
||||
} elseif ($samplerType === SAMPLER_TYPE_PROBABILISTIC) {
|
||||
return new ProbabilisticSampler((float)$samplerParam);
|
||||
} elseif ($samplerType === SAMPLER_TYPE_RATE_LIMITING) {
|
||||
if (!$this->cache) {
|
||||
throw new Exception('You cannot use RateLimitingSampler without cache component');
|
||||
}
|
||||
$cacheConfig = $samplerConfig['cache'] ?? [];
|
||||
return new RateLimitingSampler(
|
||||
$samplerParam ?? 0,
|
||||
new RateLimiter(
|
||||
$this->cache,
|
||||
$cacheConfig['currentBalanceKey'] ?? 'rate.currentBalance',
|
||||
$cacheConfig['lastTickKey'] ?? 'rate.lastTick'
|
||||
)
|
||||
);
|
||||
}
|
||||
throw new Exception('Unknown sampler type ' . $samplerType);
|
||||
}
|
||||
|
||||
/**
|
||||
* The UDP max buffer length.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getMaxBufferLength(): int
|
||||
{
|
||||
return (int)($this->config['max_buffer_length'] ?? 64000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalAgentReportingHost(): string
|
||||
{
|
||||
return $this->getLocalAgentGroup()['reporting_host'] ?? DEFAULT_REPORTING_HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLocalAgentReportingPort(): int
|
||||
{
|
||||
$port = $this->getLocalAgentGroup()['reporting_port'] ?? null;
|
||||
if (empty($this->getLocalAgentGroup()['reporting_port'])) {
|
||||
switch ($this->config['dispatch_mode']) {
|
||||
case self::JAEGER_OVER_BINARY_UDP:
|
||||
$port = DEFAULT_JAEGER_UDP_BINARY_REPORTING_PORT;
|
||||
break;
|
||||
case self::JAEGER_OVER_BINARY_HTTP:
|
||||
$port = DEFAULT_JAEGER_HTTP_BINARY_REPORTING_PORT;
|
||||
break;
|
||||
default:
|
||||
$port = DEFAULT_ZIPKIN_UDP_COMPACT_REPORTING_PORT;
|
||||
}
|
||||
}
|
||||
return (int)$port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getLocalAgentGroup(): array
|
||||
{
|
||||
return $this->config['local_agent'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getTraceIdHeader(): string
|
||||
{
|
||||
return $this->config['trace_id_header'] ?? TRACE_ID_HEADER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getBaggageHeaderPrefix(): string
|
||||
{
|
||||
return $this->config['baggage_header_prefix'] ?? BAGGAGE_HEADER_PREFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getDebugIdHeaderKey(): string
|
||||
{
|
||||
return $this->config['debug_id_header_key'] ?? DEBUG_ID_HEADER_KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of user-defined tags to be added to each span created by the tracer initialized by this config.
|
||||
* @return string[]
|
||||
*/
|
||||
private function getConfiguredTags(): array
|
||||
{
|
||||
return $this->config['tags'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to follow the Zipkin model of using one span per RPC,
|
||||
* as opposed to the model of using separate spans on the RPC client and server.
|
||||
* Defaults to true.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldUseOneSpanPerRpc(): bool
|
||||
{
|
||||
return $this->config['one_span_per_rpc'] ?? true;
|
||||
}
|
||||
|
||||
public function ipProtocolVersion(): string
|
||||
{
|
||||
return $this->config[self::IP_VERSION] ?? self::IPV4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets values from env vars into config props, unless ones has been already set.
|
||||
*/
|
||||
private function setConfigFromEnv()
|
||||
{
|
||||
// general
|
||||
if (isset($_ENV['JAEGER_SERVICE_NAME']) && !isset($this->config['service_name'])) {
|
||||
$this->config['service_name'] = $_ENV['JAEGER_SERVICE_NAME'];
|
||||
}
|
||||
|
||||
if (isset($_ENV['JAEGER_TAGS']) && !isset($this->config["tags"])) {
|
||||
$this->config['tags'] = $_ENV['JAEGER_TAGS'];
|
||||
}
|
||||
|
||||
if (isset($_ENV['JAEGER_DISPATCH_MODE']) && !isset($this->config['dispatch_mode'])) {
|
||||
$this->config['dispatch_mode'] = $_ENV['JAEGER_DISPATCH_MODE'];
|
||||
}
|
||||
|
||||
// reporting
|
||||
if (isset($_ENV['JAEGER_AGENT_HOST']) && !isset($this->config['local_agent']['reporting_host'])) {
|
||||
$this->config['local_agent']['reporting_host'] = $_ENV['JAEGER_AGENT_HOST'];
|
||||
}
|
||||
|
||||
if (isset($_ENV['JAEGER_AGENT_PORT']) && !isset($this->config['local_agent']['reporting_port'])) {
|
||||
$this->config['local_agent']['reporting_port'] = intval($_ENV['JAEGER_AGENT_PORT']);
|
||||
}
|
||||
|
||||
if (isset($_ENV['JAEGER_REPORTER_LOG_SPANS']) && !isset($this->config['logging'])) {
|
||||
$this->config['logging'] = filter_var($_ENV['JAEGER_REPORTER_LOG_SPANS'], FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
if (isset($_ENV['JAEGER_REPORTER_MAX_QUEUE_SIZE']) && !isset($this->config['max_buffer_length'])) {
|
||||
$this->config['max_buffer_length'] = intval($_ENV['JAEGER_REPORTER_MAX_QUEUE_SIZE']);
|
||||
}
|
||||
|
||||
// sampling
|
||||
if (isset($_ENV['JAEGER_SAMPLER_TYPE']) && !isset($this->config['sampler']['type'])) {
|
||||
$this->config['sampler']['type'] = $_ENV['JAEGER_SAMPLER_TYPE'];
|
||||
}
|
||||
|
||||
if (isset($_ENV['JAEGER_SAMPLER_PARAM']) && !isset($this->config['sampler']['param'])) {
|
||||
$this->config['sampler']['param'] = $_ENV['JAEGER_SAMPLER_PARAM'];
|
||||
}
|
||||
|
||||
if (isset($_ENV['IP_VERSION']) && !isset($this->config[Config::IP_VERSION])) {
|
||||
$this->config[Config::IP_VERSION] = $_ENV['IP_VERSION'];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger;
|
||||
|
||||
// Max number of bits to use when generating random ID
|
||||
const MAX_ID_BITS = 64;
|
||||
|
||||
// How often remotely controller sampler polls for sampling strategy
|
||||
const DEFAULT_SAMPLING_INTERVAL = 60;
|
||||
|
||||
// How often remote reporter does a preemptive flush of its buffers
|
||||
const DEFAULT_FLUSH_INTERVAL = 1;
|
||||
|
||||
// Name of the HTTP header used to encode trace ID
|
||||
const TRACE_ID_HEADER = 'uber-trace-id';
|
||||
|
||||
// Prefix for HTTP headers used to record baggage items
|
||||
const BAGGAGE_HEADER_PREFIX = 'uberctx-';
|
||||
|
||||
// The name of HTTP header or a TextMap carrier key which, if found in the
|
||||
// carrier, forces the trace to be sampled as "debug" trace. The value of the
|
||||
// header is recorded as the tag on the # root span, so that the trace can
|
||||
// be found in the UI using this value as a correlation ID.
|
||||
const DEBUG_ID_HEADER_KEY = 'jaeger-debug-id';
|
||||
|
||||
const JAEGER_CLIENT_VERSION = 'PHP-' . PHP_VERSION;
|
||||
|
||||
// Tracer-scoped tag that tells the version of Jaeger client library
|
||||
const JAEGER_VERSION_TAG_KEY = 'jaeger.version';
|
||||
|
||||
// Tracer-scoped tag that contains the hostname
|
||||
const JAEGER_HOSTNAME_TAG_KEY = 'jaeger.hostname';
|
||||
|
||||
const SAMPLER_TYPE_TAG_KEY = 'sampler.type';
|
||||
|
||||
const SAMPLER_PARAM_TAG_KEY = 'sampler.param';
|
||||
|
||||
const DEFAULT_SAMPLING_PROBABILITY = 0.001;
|
||||
|
||||
const DEFAULT_LOWER_BOUND = 1.0 / (10.0 * 60.0); # sample once every 10 minutes
|
||||
|
||||
const DEFAULT_MAX_OPERATIONS = 2000;
|
||||
|
||||
const STRATEGIES_STR = 'perOperationStrategies';
|
||||
|
||||
const OPERATION_STR = 'operation';
|
||||
|
||||
const DEFAULT_LOWER_BOUND_STR = 'defaultLowerBoundTracesPerSecond';
|
||||
|
||||
const PROBABILISTIC_SAMPLING_STR = 'probabilisticSampling';
|
||||
|
||||
const SAMPLING_RATE_STR = 'samplingRate';
|
||||
|
||||
const DEFAULT_SAMPLING_PROBABILITY_STR = 'defaultSamplingProbability';
|
||||
|
||||
const OPERATION_SAMPLING_STR = 'operationSampling';
|
||||
|
||||
const MAX_TRACES_PER_SECOND_STR = 'maxTracesPerSecond';
|
||||
|
||||
const RATE_LIMITING_SAMPLING_STR = 'rateLimitingSampling';
|
||||
|
||||
const STRATEGY_TYPE_STR = 'strategyType';
|
||||
|
||||
// the type of sampler that always makes the same decision.
|
||||
const SAMPLER_TYPE_CONST = 'const';
|
||||
|
||||
// the type of sampler that polls Jaeger agent for sampling strategy.
|
||||
const SAMPLER_TYPE_REMOTE = 'remote';
|
||||
|
||||
// the type of sampler that samples traces with a certain fixed probability.
|
||||
const SAMPLER_TYPE_PROBABILISTIC = 'probabilistic';
|
||||
|
||||
// the type of sampler that samples only up to a fixed number
|
||||
// of traces per second.
|
||||
// noinspection SpellCheckingInspection
|
||||
const SAMPLER_TYPE_RATE_LIMITING = 'ratelimiting';
|
||||
|
||||
// the type of sampler that samples only up to a fixed number
|
||||
// of traces per second.
|
||||
// noinspection SpellCheckingInspection
|
||||
const SAMPLER_TYPE_LOWER_BOUND = 'lowerbound';
|
||||
|
||||
const DEFAULT_REPORTING_HOST = 'localhost';
|
||||
|
||||
/** @deprecated */
|
||||
const DEFAULT_REPORTING_PORT = 5775;
|
||||
|
||||
const DEFAULT_ZIPKIN_UDP_COMPACT_REPORTING_PORT = 5775;
|
||||
const DEFAULT_JAEGER_UDP_BINARY_REPORTING_PORT = 6832;
|
||||
const DEFAULT_JAEGER_HTTP_BINARY_REPORTING_PORT = 14268;
|
||||
|
||||
const DEFAULT_SAMPLING_PORT = 5778;
|
||||
|
||||
const LOCAL_AGENT_DEFAULT_ENABLED = true;
|
||||
|
||||
const ZIPKIN_SPAN_FORMAT = 'zipkin-span-format';
|
||||
|
||||
const SAMPLED_FLAG = 0x01;
|
||||
|
||||
const DEBUG_FLAG = 0x02;
|
171
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Mapper/SpanToJaegerMapper.php
vendored
Normal file
171
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Mapper/SpanToJaegerMapper.php
vendored
Normal file
|
@ -0,0 +1,171 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Mapper;
|
||||
|
||||
use Jaeger\Span;
|
||||
use Jaeger\Thrift\Agent\Zipkin\AnnotationType;
|
||||
use Jaeger\Thrift\Agent\Zipkin\BinaryAnnotation;
|
||||
use Jaeger\Thrift\Log;
|
||||
use Jaeger\Thrift\Span as JaegerThriftSpan;
|
||||
use Jaeger\Thrift\Tag;
|
||||
use Jaeger\Thrift\TagType;
|
||||
use const OpenTracing\Tags\COMPONENT;
|
||||
use const OpenTracing\Tags\PEER_HOST_IPV4;
|
||||
use const OpenTracing\Tags\PEER_PORT;
|
||||
use const OpenTracing\Tags\PEER_SERVICE;
|
||||
use const OpenTracing\Tags\SPAN_KIND;
|
||||
|
||||
class SpanToJaegerMapper
|
||||
{
|
||||
private $specialSpanTags = ["jaeger.hostname", "jaeger.version"];
|
||||
|
||||
private $processTagsPrefix = "process.";
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getSpecialSpanTags(): array
|
||||
{
|
||||
return $this->specialSpanTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getProcessTagsPrefix(): string
|
||||
{
|
||||
return $this->processTagsPrefix;
|
||||
}
|
||||
|
||||
public function mapSpanToJaeger(Span $span) : JaegerThriftSpan
|
||||
{
|
||||
$timestamp = $span->getStartTime();
|
||||
$duration = $span->getEndTime() - $span->getStartTime();
|
||||
|
||||
/** @var Tag[] $tags */
|
||||
$tags = [];
|
||||
|
||||
$tags[] = new Tag([
|
||||
"key" => COMPONENT,
|
||||
"vType" => TagType::STRING,
|
||||
"vStr" => $span->getComponent() ?? $span->getTracer()->getServiceName(),
|
||||
]);
|
||||
|
||||
// Handle special tags
|
||||
$peerService = $span->peer['service_name'] ?? null;
|
||||
if ($peerService !== null) {
|
||||
$tags[] = new Tag([
|
||||
"key" => PEER_SERVICE,
|
||||
"vType" => TagType::STRING,
|
||||
"vStr" => $peerService,
|
||||
]);
|
||||
}
|
||||
|
||||
$peerHostIpv4 = $span->peer['ipv4'] ?? null;
|
||||
if ($peerHostIpv4 !== null) {
|
||||
$tags[] = new Tag([
|
||||
"key" => PEER_HOST_IPV4,
|
||||
"vType" => TagType::STRING,
|
||||
"vStr" => $peerHostIpv4,
|
||||
]);
|
||||
}
|
||||
|
||||
$peerPort = $span->peer['port'] ?? null;
|
||||
if ($peerPort !== null) {
|
||||
$tags[] = new Tag([
|
||||
"key" => PEER_PORT,
|
||||
"vType" => TagType::LONG,
|
||||
"vLong" => $peerPort,
|
||||
]);
|
||||
}
|
||||
|
||||
$spanKind = $span->getKind();
|
||||
if ($spanKind !== null) {
|
||||
$tags[] = new Tag([
|
||||
"key" => SPAN_KIND,
|
||||
"vType" => TagType::STRING,
|
||||
"vStr" => $spanKind,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @var BinaryAnnotation[] $binaryAnnotationTags */
|
||||
$binaryAnnotationTags = $span->getTags();
|
||||
foreach ($binaryAnnotationTags as $binaryAnnotationTag) {
|
||||
if (in_array($binaryAnnotationTag->key, $this->specialSpanTags, true)) {
|
||||
continue ;
|
||||
}
|
||||
|
||||
if (strpos($binaryAnnotationTag->key, $this->processTagsPrefix) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = "";
|
||||
$vkey = "";
|
||||
switch ($binaryAnnotationTag->annotation_type) {
|
||||
case AnnotationType::BOOL:
|
||||
$type = TagType::BOOL;
|
||||
$vkey = "vBool";
|
||||
break;
|
||||
case AnnotationType::BYTES:
|
||||
$type = TagType::BINARY;
|
||||
$vkey = "vBinary";
|
||||
break;
|
||||
case AnnotationType::DOUBLE:
|
||||
$type = TagType::DOUBLE;
|
||||
$vkey = "vDouble";
|
||||
break;
|
||||
case AnnotationType::I16:
|
||||
case AnnotationType::I32:
|
||||
case AnnotationType::I64:
|
||||
$type = TagType::LONG;
|
||||
$vkey = "vLong";
|
||||
break;
|
||||
default:
|
||||
$type = TagType::STRING;
|
||||
$vkey = "vStr";
|
||||
}
|
||||
|
||||
$tags[] = new Tag([
|
||||
"key" => $binaryAnnotationTag->key,
|
||||
"vType" => $type,
|
||||
$vkey => $binaryAnnotationTag->value,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @var Log[] $logs */
|
||||
$logs = [];
|
||||
|
||||
$spanLogs = $span->getLogs();
|
||||
|
||||
foreach ($spanLogs as $spanLog) {
|
||||
/** @var Tag $fields */
|
||||
$fields = [];
|
||||
|
||||
if (!empty($spanLog["fields"])) {
|
||||
$fields[] = new Tag([
|
||||
"key" => "event",
|
||||
"vType" => TagType::STRING,
|
||||
"vStr" => json_encode($spanLog["fields"])
|
||||
]);
|
||||
}
|
||||
|
||||
$logs[] = new Log([
|
||||
"timestamp" => $spanLog["timestamp"],
|
||||
"fields" => $fields
|
||||
]);
|
||||
}
|
||||
|
||||
return new JaegerThriftSpan([
|
||||
"traceIdLow" => (int)$span->getContext()->getTraceId(),
|
||||
"traceIdHigh" => 0,
|
||||
"spanId" => (int)$span->getContext()->getSpanId(),
|
||||
"parentSpanId" => (int)$span->getContext()->getParentId(),
|
||||
"operationName" => $span->getOperationName(),
|
||||
"startTime" => $timestamp,
|
||||
"duration" => $duration,
|
||||
"flags" => (int)$span->isDebug(),
|
||||
"tags" => $tags,
|
||||
"logs" => $logs
|
||||
]);
|
||||
}
|
||||
}
|
51
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Reporter/CompositeReporter.php
vendored
Normal file
51
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Reporter/CompositeReporter.php
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Reporter;
|
||||
|
||||
use Jaeger\Span;
|
||||
|
||||
/**
|
||||
* CompositeReporter delegates reporting to one or more underlying reporters.
|
||||
*/
|
||||
class CompositeReporter implements ReporterInterface
|
||||
{
|
||||
/**
|
||||
* @var ReporterInterface[]
|
||||
*/
|
||||
private $reporters;
|
||||
|
||||
/**
|
||||
* CompositeReporter constructor.
|
||||
*
|
||||
* @param ReporterInterface ...$reporters
|
||||
*/
|
||||
public function __construct(ReporterInterface ...$reporters)
|
||||
{
|
||||
$this->reporters = $reporters;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param Span $span
|
||||
* @return void
|
||||
*/
|
||||
public function reportSpan(Span $span)
|
||||
{
|
||||
foreach ($this->reporters as $reporter) {
|
||||
$reporter->reportSpan($span);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
foreach ($this->reporters as $reporter) {
|
||||
$reporter->close();
|
||||
}
|
||||
}
|
||||
}
|
47
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Reporter/InMemoryReporter.php
vendored
Normal file
47
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Reporter/InMemoryReporter.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Reporter;
|
||||
|
||||
use Jaeger\Span;
|
||||
|
||||
/**
|
||||
* InMemoryReporter stores spans in memory and returns them via getSpans().
|
||||
*/
|
||||
class InMemoryReporter implements ReporterInterface
|
||||
{
|
||||
/**
|
||||
* @var Span[]
|
||||
*/
|
||||
private $spans = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param Span $span
|
||||
* @return void
|
||||
*/
|
||||
public function reportSpan(Span $span)
|
||||
{
|
||||
$this->spans[] = $span;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Span[]
|
||||
*/
|
||||
public function getSpans(): array
|
||||
{
|
||||
return $this->spans;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Only implemented to satisfy the sampler interface.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Reporter;
|
||||
|
||||
use Jaeger\Sender\SenderInterface;
|
||||
use Jaeger\Span;
|
||||
|
||||
class JaegerReporter implements ReporterInterface
|
||||
{
|
||||
/**
|
||||
* @var SenderInterface
|
||||
*/
|
||||
private $sender;
|
||||
|
||||
/**
|
||||
* RemoteReporter constructor.
|
||||
*
|
||||
* @param SenderInterface $sender
|
||||
*/
|
||||
public function __construct(SenderInterface $sender)
|
||||
{
|
||||
$this->sender = $sender;
|
||||
}
|
||||
|
||||
public function reportSpan(Span $span)
|
||||
{
|
||||
$this->sender->append($span);
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
$this->sender->flush();
|
||||
$this->sender->close();
|
||||
}
|
||||
}
|
51
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Reporter/LoggingReporter.php
vendored
Normal file
51
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Reporter/LoggingReporter.php
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Reporter;
|
||||
|
||||
use Jaeger\Span;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
/**
|
||||
* LoggingReporter logs all spans.
|
||||
*/
|
||||
class LoggingReporter implements ReporterInterface
|
||||
{
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* LoggingReporter constructor.
|
||||
*
|
||||
* @param LoggerInterface|null $logger
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger = null)
|
||||
{
|
||||
$this->logger = $logger ?? new NullLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param Span $span
|
||||
* @return void
|
||||
*/
|
||||
public function reportSpan(Span $span)
|
||||
{
|
||||
$this->logger->debug('Reporting span ' . $span->getOperationName());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Only implemented to satisfy the sampler interface.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Reporter;
|
||||
|
||||
use Jaeger\Span;
|
||||
|
||||
/**
|
||||
* NullReporter ignores all spans.
|
||||
*/
|
||||
class NullReporter implements ReporterInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param Span $span
|
||||
* @return void
|
||||
*/
|
||||
public function reportSpan(Span $span)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Reporter;
|
||||
|
||||
use Jaeger\Sender\UdpSender;
|
||||
use Jaeger\Span;
|
||||
|
||||
class RemoteReporter implements ReporterInterface
|
||||
{
|
||||
/**
|
||||
* @var UdpSender
|
||||
*/
|
||||
private $transport;
|
||||
|
||||
/**
|
||||
* RemoteReporter constructor.
|
||||
*
|
||||
* @param UdpSender $transport
|
||||
*/
|
||||
public function __construct(UdpSender $transport)
|
||||
{
|
||||
$this->transport = $transport;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param Span $span
|
||||
* @return void
|
||||
*/
|
||||
public function reportSpan(Span $span)
|
||||
{
|
||||
$this->transport->append($span);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->transport->flush();
|
||||
$this->transport->close();
|
||||
}
|
||||
}
|
28
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Reporter/ReporterInterface.php
vendored
Normal file
28
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Reporter/ReporterInterface.php
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Reporter;
|
||||
|
||||
use Jaeger\Span;
|
||||
|
||||
/**
|
||||
* Uses to report finished span to something that collects those spans.
|
||||
*
|
||||
* @package Jaeger\Reporter
|
||||
*/
|
||||
interface ReporterInterface
|
||||
{
|
||||
/**
|
||||
* Report finished span.
|
||||
*
|
||||
* @param Span $span
|
||||
* @return void
|
||||
*/
|
||||
public function reportSpan(Span $span);
|
||||
|
||||
/**
|
||||
* Release any resources used by the reporter and flushes/sends the data.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close();
|
||||
}
|
23
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/AbstractReporterFactory.php
vendored
Normal file
23
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/AbstractReporterFactory.php
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\ReporterFactory;
|
||||
|
||||
use Jaeger\Config;
|
||||
use Thrift\Transport\TTransport;
|
||||
|
||||
abstract class AbstractReporterFactory implements ReporterFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @var Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* AbstractReporterFactory constructor.
|
||||
* @param Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
}
|
35
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/JaegerHttpReporterFactory.php
vendored
Normal file
35
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/JaegerHttpReporterFactory.php
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\ReporterFactory;
|
||||
|
||||
use Jaeger\AgentClient\HttpAgentClient;
|
||||
use Jaeger\Reporter\JaegerReporter;
|
||||
use Jaeger\Reporter\ReporterInterface;
|
||||
use Jaeger\Sender\JaegerSender;
|
||||
use Thrift\Exception\TTransportException;
|
||||
use Thrift\Protocol\TBinaryProtocol;
|
||||
use Thrift\Transport\THttpClient;
|
||||
|
||||
class JaegerHttpReporterFactory extends AbstractReporterFactory implements ReporterFactoryInterface
|
||||
{
|
||||
public function createReporter() : ReporterInterface
|
||||
{
|
||||
$transport = new THttpClient(
|
||||
$this->config->getLocalAgentReportingHost(),
|
||||
$this->config->getLocalAgentReportingPort(),
|
||||
"/api/traces"
|
||||
);
|
||||
|
||||
try {
|
||||
$transport->open();
|
||||
} catch (TTransportException $e) {
|
||||
$this->config->getLogger()->warning($e->getMessage());
|
||||
}
|
||||
$protocol = new TBinaryProtocol($transport);
|
||||
$client = new HttpAgentClient($protocol);
|
||||
$this->config->getLogger()->debug('Initializing HTTP Jaeger Tracer with Jaeger.Thrift over Binary protocol');
|
||||
$sender = new JaegerSender($client, $this->config->getLogger());
|
||||
$sender->setMaxBufferLength($this->config->getMaxBufferLength());
|
||||
return new JaegerReporter($sender);
|
||||
}
|
||||
}
|
44
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/JaegerReporterFactory.php
vendored
Normal file
44
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/JaegerReporterFactory.php
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\ReporterFactory;
|
||||
|
||||
use Jaeger\AgentClient\HttpAgentClient;
|
||||
use Jaeger\Reporter\JaegerReporter;
|
||||
use Jaeger\Reporter\ReporterInterface;
|
||||
use Jaeger\Sender\JaegerSender;
|
||||
use Jaeger\Thrift\Agent\AgentClient;
|
||||
use Jaeger\ThriftUdpTransport;
|
||||
use Thrift\Exception\TTransportException;
|
||||
use Thrift\Protocol\TBinaryProtocol;
|
||||
use Thrift\Transport\TBufferedTransport;
|
||||
|
||||
class JaegerReporterFactory extends AbstractReporterFactory implements ReporterFactoryInterface
|
||||
{
|
||||
public function createReporter() : ReporterInterface
|
||||
{
|
||||
$udp = new ThriftUdpTransport(
|
||||
$this->config->getLocalAgentReportingHost(),
|
||||
$this->config->getLocalAgentReportingPort(),
|
||||
$this->config->getLogger(),
|
||||
$this->config
|
||||
);
|
||||
|
||||
$transport = new TBufferedTransport(
|
||||
$udp,
|
||||
$this->config->getMaxBufferLength(),
|
||||
$this->config->getMaxBufferLength()
|
||||
);
|
||||
|
||||
try {
|
||||
$transport->open();
|
||||
} catch (TTransportException $e) {
|
||||
$this->config->getLogger()->warning($e->getMessage());
|
||||
}
|
||||
$protocol = new TBinaryProtocol($transport);
|
||||
$client = new AgentClient($protocol);
|
||||
$this->config->getLogger()->debug('Initializing UDP Jaeger Tracer with Jaeger.Thrift over Binary protocol');
|
||||
$sender = new JaegerSender($client, $this->config->getLogger());
|
||||
$sender->setMaxBufferLength($this->config->getMaxBufferLength());
|
||||
return new JaegerReporter($sender);
|
||||
}
|
||||
}
|
10
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/ReporterFactoryInterface.php
vendored
Normal file
10
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/ReporterFactoryInterface.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\ReporterFactory;
|
||||
|
||||
use Jaeger\Reporter\ReporterInterface;
|
||||
|
||||
interface ReporterFactoryInterface
|
||||
{
|
||||
public function createReporter() : ReporterInterface;
|
||||
}
|
46
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/ZipkinReporterFactory.php
vendored
Normal file
46
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/ReporterFactory/ZipkinReporterFactory.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\ReporterFactory;
|
||||
|
||||
use Jaeger\Reporter\JaegerReporter;
|
||||
use Jaeger\Reporter\RemoteReporter;
|
||||
use Jaeger\Reporter\ReporterInterface;
|
||||
use Jaeger\Sender\JaegerSender;
|
||||
use Jaeger\Sender\UdpSender;
|
||||
use Jaeger\Thrift\Agent\AgentClient;
|
||||
use Jaeger\ThriftUdpTransport;
|
||||
use Thrift\Exception\TTransportException;
|
||||
use Thrift\Protocol\TBinaryProtocol;
|
||||
use Thrift\Protocol\TCompactProtocol;
|
||||
use Thrift\Transport\TBufferedTransport;
|
||||
use Thrift\Transport\TTransport;
|
||||
|
||||
class ZipkinReporterFactory extends AbstractReporterFactory implements ReporterFactoryInterface
|
||||
{
|
||||
public function createReporter() : ReporterInterface
|
||||
{
|
||||
$udp = new ThriftUdpTransport(
|
||||
$this->config->getLocalAgentReportingHost(),
|
||||
$this->config->getLocalAgentReportingPort(),
|
||||
$this->config->getLogger(),
|
||||
$this->config
|
||||
);
|
||||
|
||||
$transport = new TBufferedTransport(
|
||||
$udp,
|
||||
$this->config->getMaxBufferLength(),
|
||||
$this->config->getMaxBufferLength()
|
||||
);
|
||||
|
||||
try {
|
||||
$transport->open();
|
||||
} catch (TTransportException $e) {
|
||||
$this->config->getLogger()->warning($e->getMessage());
|
||||
}
|
||||
$protocol = new TCompactProtocol($transport);
|
||||
$client = new AgentClient($protocol);
|
||||
$this->config->getLogger()->debug('Initializing UDP Jaeger Tracer with Zipkin.Thrift over Compact protocol');
|
||||
$sender = new UdpSender($client, $this->config->getMaxBufferLength(), $this->config->getLogger());
|
||||
return new RemoteReporter($sender);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Sampler;
|
||||
|
||||
use const Jaeger\SAMPLER_PARAM_TAG_KEY;
|
||||
use const Jaeger\SAMPLER_TYPE_CONST;
|
||||
use const Jaeger\SAMPLER_TYPE_TAG_KEY;
|
||||
|
||||
/**
|
||||
* ConstSampler always returns the same decision.
|
||||
*
|
||||
* @package Jaeger\Sampler
|
||||
*/
|
||||
class ConstSampler implements SamplerInterface
|
||||
{
|
||||
/**
|
||||
* Whether or not the new trace should be sampled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $decision;
|
||||
|
||||
/**
|
||||
* A list of the sampler tags.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $tags = [];
|
||||
|
||||
/**
|
||||
* ConstSampler constructor.
|
||||
*
|
||||
* @param bool $decision
|
||||
*/
|
||||
public function __construct(bool $decision = true)
|
||||
{
|
||||
$this->tags = [
|
||||
SAMPLER_TYPE_TAG_KEY => SAMPLER_TYPE_CONST,
|
||||
SAMPLER_PARAM_TAG_KEY => $decision,
|
||||
];
|
||||
|
||||
$this->decision = $decision;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string $traceId The traceId on the span.
|
||||
* @param string $operation The operation name set on the span.
|
||||
* @return array
|
||||
*/
|
||||
public function isSampled(string $traceId, string $operation = ''): array
|
||||
{
|
||||
return [$this->decision, $this->tags];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Only implemented to satisfy the sampler interface.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
88
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Sampler/ProbabilisticSampler.php
vendored
Normal file
88
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Sampler/ProbabilisticSampler.php
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Sampler;
|
||||
|
||||
use OutOfBoundsException;
|
||||
use const Jaeger\SAMPLER_PARAM_TAG_KEY;
|
||||
use const Jaeger\SAMPLER_TYPE_PROBABILISTIC;
|
||||
use const Jaeger\SAMPLER_TYPE_TAG_KEY;
|
||||
|
||||
/**
|
||||
* A sampler that randomly samples a certain percentage of traces specified
|
||||
* by the samplingRate, in the range between 0.0 and 1.0.
|
||||
*
|
||||
* @package Jaeger\Sampler
|
||||
*/
|
||||
class ProbabilisticSampler implements SamplerInterface
|
||||
{
|
||||
/**
|
||||
* The sampling rate rate between 0.0 and 1.0.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
private $rate;
|
||||
|
||||
/**
|
||||
* A list of the sampler tags.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $tags = [];
|
||||
|
||||
/**
|
||||
* The boundary of the sample sampling rate.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
private $boundary;
|
||||
|
||||
/**
|
||||
* ProbabilisticSampler constructor.
|
||||
*
|
||||
* @param float $rate
|
||||
* @throws OutOfBoundsException
|
||||
*/
|
||||
public function __construct(float $rate)
|
||||
{
|
||||
$this->tags = [
|
||||
SAMPLER_TYPE_TAG_KEY => SAMPLER_TYPE_PROBABILISTIC,
|
||||
SAMPLER_PARAM_TAG_KEY => $rate,
|
||||
];
|
||||
|
||||
if ($rate < 0.0 || $rate > 1.0) {
|
||||
throw new OutOfBoundsException('Sampling rate must be between 0.0 and 1.0.');
|
||||
}
|
||||
|
||||
$this->rate = $rate;
|
||||
if ($rate < 0.5) {
|
||||
$this->boundary = (int)($rate * PHP_INT_MAX);
|
||||
} else {
|
||||
// more precise calculation due to int and float having different precision near PHP_INT_MAX
|
||||
$this->boundary = PHP_INT_MAX - (int)((1 - $rate) * PHP_INT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string $traceId The traceId on the span.
|
||||
* @param string $operation The operation name set on the span.
|
||||
* @return array
|
||||
*/
|
||||
public function isSampled(string $traceId, string $operation = ''): array
|
||||
{
|
||||
return [($traceId < $this->boundary), $this->tags];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Only implemented to satisfy the sampler interface.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
62
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Sampler/RateLimitingSampler.php
vendored
Normal file
62
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Sampler/RateLimitingSampler.php
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Sampler;
|
||||
|
||||
use Jaeger\Util\RateLimiter;
|
||||
|
||||
use const Jaeger\SAMPLER_PARAM_TAG_KEY;
|
||||
use const Jaeger\SAMPLER_TYPE_RATE_LIMITING;
|
||||
use const Jaeger\SAMPLER_TYPE_TAG_KEY;
|
||||
|
||||
class RateLimitingSampler implements SamplerInterface
|
||||
{
|
||||
/**
|
||||
* @var RateLimiter
|
||||
*/
|
||||
private $rateLimiter;
|
||||
|
||||
/**
|
||||
* A list of the sampler tags.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $tags = [];
|
||||
|
||||
public function __construct($maxTracesPerSecond, RateLimiter $rateLimiter)
|
||||
{
|
||||
$this->tags = [
|
||||
SAMPLER_TYPE_TAG_KEY => SAMPLER_TYPE_RATE_LIMITING,
|
||||
SAMPLER_PARAM_TAG_KEY => $maxTracesPerSecond,
|
||||
];
|
||||
|
||||
$maxTracesPerNanosecond = $maxTracesPerSecond / 1000000000.0;
|
||||
$this->rateLimiter = $rateLimiter;
|
||||
$this->rateLimiter->initialize($maxTracesPerNanosecond, $maxTracesPerSecond > 1.0 ? 1.0 : $maxTracesPerSecond);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the new trace should be sampled.
|
||||
*
|
||||
* Implementations should return an array in the format [$decision, $tags].
|
||||
*
|
||||
* @param string $traceId The traceId on the span.
|
||||
* @param string $operation The operation name set on the span.
|
||||
* @return array
|
||||
*/
|
||||
public function isSampled(string $traceId = '', string $operation = '')
|
||||
{
|
||||
return [$this->rateLimiter->checkCredit(1.0), $this->tags];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Only implemented to satisfy the sampler interface.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
29
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Sampler/SamplerInterface.php
vendored
Normal file
29
vendor/jonahgeorge/jaeger-client-php/src/Jaeger/Sampler/SamplerInterface.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Sampler;
|
||||
|
||||
/**
|
||||
* Sampler is responsible for deciding if a new trace should be sampled and captured for storage.
|
||||
*
|
||||
* @package Jaeger\Sampler
|
||||
*/
|
||||
interface SamplerInterface
|
||||
{
|
||||
/**
|
||||
* Whether or not the new trace should be sampled.
|
||||
*
|
||||
* Implementations should return an array in the format [$decision, $tags].
|
||||
*
|
||||
* @param string $traceId The traceId on the span.
|
||||
* @param string $operation The operation name set on the span.
|
||||
* @return array
|
||||
*/
|
||||
public function isSampled(string $traceId, string $operation);
|
||||
|
||||
/**
|
||||
* Release any resources used by the sampler.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close();
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger;
|
||||
|
||||
use OpenTracing\Scope as OTScope;
|
||||
use OpenTracing\Span as OTSpan;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class Scope implements OTScope
|
||||
{
|
||||
/**
|
||||
* @var ScopeManager
|
||||
*/
|
||||
private $scopeManager;
|
||||
|
||||
/**
|
||||
* @var OTSpan
|
||||
*/
|
||||
private $wrapped;
|
||||
|
||||
/**
|
||||
* @var OTScope|null
|
||||
*/
|
||||
private $toRestore;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $finishSpanOnClose;
|
||||
|
||||
/**
|
||||
* Scope constructor.
|
||||
* @param ScopeManager $scopeManager
|
||||
* @param OTSpan $wrapped
|
||||
* @param bool $finishSpanOnClose
|
||||
*/
|
||||
public function __construct(ScopeManager $scopeManager, OTSpan $wrapped, bool $finishSpanOnClose)
|
||||
{
|
||||
$this->scopeManager = $scopeManager;
|
||||
$this->wrapped = $wrapped;
|
||||
$this->finishSpanOnClose = $finishSpanOnClose;
|
||||
$this->toRestore = $scopeManager->getActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
if ($this->scopeManager->getActive() !== $this) {
|
||||
// This shouldn't happen if users call methods in expected order
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->finishSpanOnClose) {
|
||||
$this->wrapped->finish();
|
||||
}
|
||||
|
||||
$this->scopeManager->setActive($this->toRestore);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSpan(): OTSpan
|
||||
{
|
||||
return $this->wrapped;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger;
|
||||
|
||||
use OpenTracing\ScopeManager as OTScopeManager;
|
||||
use OpenTracing\Span as OTSpan;
|
||||
use OpenTracing\Scope as OTScope;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class ScopeManager implements OTScopeManager
|
||||
{
|
||||
/**
|
||||
* @var OTScope
|
||||
*/
|
||||
private $active;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function activate(OTSpan $span, bool $finishSpanOnClose = self::DEFAULT_FINISH_SPAN_ON_CLOSE): OTScope
|
||||
{
|
||||
$this->active = new Scope($this, $span, $finishSpanOnClose);
|
||||
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getActive(): ?OTScope
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scope as active.
|
||||
* @param OTScope|null $scope
|
||||
*/
|
||||
public function setActive(OTScope $scope = null)
|
||||
{
|
||||
$this->active = $scope;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace Jaeger\Sender;
|
||||
|
||||
use Jaeger\Mapper\SpanToJaegerMapper;
|
||||
use Jaeger\Span as JaegerSpan;
|
||||
use Jaeger\Thrift\Agent\AgentClient;
|
||||
use Jaeger\Thrift\Agent\AgentIf;
|
||||
use Jaeger\Thrift\Batch;
|
||||
use Jaeger\Thrift\Process;
|
||||
use Jaeger\Thrift\Span as JaegerThriftSpan;
|
||||
use Jaeger\Thrift\Tag;
|
||||
use Jaeger\Thrift\TagType;
|
||||
use Jaeger\Tracer;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Thrift\Protocol\TBinaryProtocol;
|
||||
use Thrift\Protocol\TCompactProtocol;
|
||||
use Thrift\Transport\TMemoryBuffer;
|
||||
use const Jaeger\JAEGER_HOSTNAME_TAG_KEY;
|
||||
|
||||
class JaegerSender implements SenderInterface
|
||||
{
|
||||
/**
|
||||
* @var JaegerSpan[]
|
||||
*/
|
||||
private $spans = [];
|
||||
|
||||
/**
|
||||
* @var AgentIf
|
||||
*/
|
||||
private $agentClient;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var Tracer
|
||||
*/
|
||||
private $tracer;
|
||||
|
||||
/**
|
||||
* @var SpanToJaegerMapper
|
||||
*/
|
||||
private $mapper;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $jaegerBatchOverheadLength = 512;
|
||||
|
||||
/**
|
||||
* The maximum length of the thrift-objects for a jaeger-batch.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maxBufferLength = 64000;
|
||||
|
||||
/**
|
||||
* @param AgentIf $agentClient
|
||||
* @param LoggerInterface|null $logger
|
||||
* @param SpanToJaegerMapper|null $mapper
|
||||
*/
|
||||
public function __construct(
|
||||
AgentIf $agentClient,
|
||||
LoggerInterface $logger = null,
|
||||
SpanToJaegerMapper $mapper = null
|
||||
) {
|
||||
$this->agentClient = $agentClient;
|
||||
$this->logger = $logger ?? new NullLogger();
|
||||
$this->mapper = $mapper ?? new SpanToJaegerMapper();
|
||||
}
|
||||
|
||||
|
||||
public function flush(): int
|
||||
{
|
||||
$count = count($this->spans);
|
||||
if ($count === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$jaegerThriftSpans = $this->makeJaegerBatch($this->spans);
|
||||
|
||||
try {
|
||||
$this->send($jaegerThriftSpans);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->warning($e->getMessage());
|
||||
}
|
||||
|
||||
$this->spans = [];
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
public function setMaxBufferLength($maxBufferLength)
|
||||
{
|
||||
$this->maxBufferLength = $maxBufferLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JaegerSpan[] $spans
|
||||
* @return array
|
||||
*/
|
||||
private function makeJaegerBatch(array $spans) : array
|
||||
{
|
||||
/** @var JaegerThriftSpan[] $jaegerSpans */
|
||||
$jaegerSpans = [];
|
||||
|
||||
foreach ($spans as $span) {
|
||||
if (empty($this->tracer)) {
|
||||
$this->tracer = $span->getTracer();
|
||||
}
|
||||
|
||||
$jaegerSpans[] = $this->mapper->mapSpanToJaeger($span);
|
||||
}
|
||||
|
||||
return $jaegerSpans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JaegerThriftSpan[] $spans
|
||||
*/
|
||||
private function send(array $spans)
|
||||
{
|
||||
if (empty($this->tracer)) {
|
||||
return ;
|
||||
}
|
||||
|
||||
$chunks = $this->chunkSplit($spans);
|
||||
foreach ($chunks as $chunk) {
|
||||
/** @var JaegerThriftSpan[] $chunk */
|
||||
$this->emitJaegerBatch($chunk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JaegerThriftSpan $span
|
||||
*/
|
||||
private function getBufferLength($span)
|
||||
{
|
||||
$memoryBuffer = new TMemoryBuffer();
|
||||
$span->write(new TBinaryProtocol($memoryBuffer));
|
||||
return $memoryBuffer->available();
|
||||
}
|
||||
|
||||
private function chunkSplit(array $spans): array
|
||||
{
|
||||
$actualBufferSize = $this->jaegerBatchOverheadLength;
|
||||
$chunkId = 0;
|
||||
$chunks = [];
|
||||
|
||||
foreach ($spans as $span) {
|
||||
$spanBufferLength = $this->getBufferLength($span);
|
||||
if (!empty($chunks[$chunkId]) && ($actualBufferSize + $spanBufferLength) > $this->maxBufferLength) {
|
||||
// point to next chunk
|
||||
++$chunkId;
|
||||
|
||||
// reset buffer size
|
||||
$actualBufferSize = $this->jaegerBatchOverheadLength;
|
||||
}
|
||||
|
||||
if (!isset($chunks[$chunkId])) {
|
||||
$chunks[$chunkId] = [];
|
||||
}
|
||||
|
||||
$chunks[$chunkId][] = $span;
|
||||
$actualBufferSize += $spanBufferLength;
|
||||
}
|
||||
|
||||
return $chunks;
|
||||
}
|
||||
|
||||
protected function emitJaegerBatch(array $spans)
|
||||
{
|
||||
/** @var Tag[] $tags */
|
||||
$tags = [];
|
||||
|
||||
foreach ($this->tracer->getTags() as $k => $v) {
|
||||
if (!in_array($k, $this->mapper->getSpecialSpanTags())) {
|
||||
if (strpos($k, $this->mapper->getProcessTagsPrefix()) !== 0) {
|
||||
continue ;
|
||||
}
|
||||
|
||||
$quoted = preg_quote($this->mapper->getProcessTagsPrefix());
|
||||
$k = preg_replace(sprintf('/^%s/', $quoted), '', $k);
|
||||
}
|
||||
|
||||
if ($k === JAEGER_HOSTNAME_TAG_KEY) {
|
||||
$k = "hostname";
|
||||
}
|
||||
|
||||
$tags[] = new Tag([
|
||||
"key" => $k,
|
||||
"vType" => TagType::STRING,
|
||||
"vStr" => $v
|
||||
]);
|
||||
}
|
||||
|
||||
$tags[] = new Tag([
|
||||
"key" => "format",
|
||||
"vType" => TagType::STRING,
|
||||
"vStr" => "jaeger.thrift"
|
||||
]);
|
||||
|
||||
$tags[] = new Tag([
|
||||
"key" => "ip",
|
||||
"vType" => TagType::STRING,
|
||||
"vStr" => $this->tracer->getIpAddress()
|
||||
]);
|
||||
|
||||
$batch = new Batch([
|
||||
"spans" => $spans,
|
||||
"process" => new Process([
|
||||
"serviceName" => $this->tracer->getServiceName(),
|
||||
"tags" => $tags
|
||||
])
|
||||
]);
|
||||
|
||||
$this->agentClient->emitBatch($batch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JaegerSpan $span
|
||||
*/
|
||||
public function append(JaegerSpan $span)
|
||||
{
|
||||
$this->spans[] = $span;
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Sender;
|
||||
|
||||
use Jaeger\Span as JaegerSpan;
|
||||
|
||||
interface SenderInterface
|
||||
{
|
||||
public function flush(): int;
|
||||
public function append(JaegerSpan $span);
|
||||
public function close();
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger\Sender;
|
||||
|
||||
use Exception;
|
||||
use Jaeger\Thrift\Agent\AgentClient;
|
||||
use Jaeger\Thrift\Agent\Zipkin\Annotation;
|
||||
use Jaeger\Thrift\Agent\Zipkin\AnnotationType;
|
||||
use Jaeger\Thrift\Agent\Zipkin\BinaryAnnotation;
|
||||
use Jaeger\Thrift\Agent\Zipkin\Endpoint;
|
||||
use Jaeger\Thrift\Agent\Zipkin\Span as ThriftSpan;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Thrift\Base\TBase;
|
||||
use Thrift\Protocol\TCompactProtocol;
|
||||
use Thrift\Transport\TMemoryBuffer;
|
||||
use Jaeger\Span as JaegerSpan;
|
||||
|
||||
use const OpenTracing\Tags\COMPONENT;
|
||||
|
||||
class UdpSender
|
||||
{
|
||||
const CLIENT_ADDR = "ca";
|
||||
const SERVER_ADDR = "sa";
|
||||
|
||||
/**
|
||||
* @var JaegerSpan[]
|
||||
*/
|
||||
private $spans = [];
|
||||
|
||||
/**
|
||||
* @var AgentClient
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* The maximum length of the thrift-objects for a zipkin-batch.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maxBufferLength;
|
||||
|
||||
/**
|
||||
* The length of the zipkin-batch overhead.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $zipkinBatchOverheadLength = 30;
|
||||
|
||||
/**
|
||||
* UdpSender constructor.
|
||||
*
|
||||
* @param AgentClient $client
|
||||
* @param int $maxBufferLength
|
||||
* @param LoggerInterface|null $logger
|
||||
*/
|
||||
public function __construct(
|
||||
AgentClient $client,
|
||||
int $maxBufferLength,
|
||||
LoggerInterface $logger = null
|
||||
) {
|
||||
$this->client = $client;
|
||||
$this->maxBufferLength = $maxBufferLength;
|
||||
$this->logger = $logger ?? new NullLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JaegerSpan $span
|
||||
*/
|
||||
public function append(JaegerSpan $span)
|
||||
{
|
||||
$this->spans[] = $span;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int the number of flushed spans
|
||||
*/
|
||||
public function flush(): int
|
||||
{
|
||||
$count = count($this->spans);
|
||||
if ($count === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$zipkinSpans = $this->makeZipkinBatch($this->spans);
|
||||
|
||||
try {
|
||||
$this->send($zipkinSpans);
|
||||
} catch (Exception $e) {
|
||||
$this->logger->warning($e->getMessage());
|
||||
}
|
||||
|
||||
$this->spans = [];
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits the thrift-objects.
|
||||
*
|
||||
* @param array|ThriftSpan[]|TBase[] $thrifts
|
||||
*/
|
||||
private function send(array $thrifts)
|
||||
{
|
||||
foreach ($this->chunkSplit($thrifts) as $chunk) {
|
||||
/* @var $chunk ThriftSpan[] */
|
||||
$this->client->emitZipkinBatch($chunk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JaegerSpan[] $spans
|
||||
* @return ThriftSpan[]
|
||||
*/
|
||||
private function makeZipkinBatch(array $spans): array
|
||||
{
|
||||
/** @var ThriftSpan[] */
|
||||
$zipkinSpans = [];
|
||||
|
||||
foreach ($spans as $span) {
|
||||
/** @var JaegerSpan $span */
|
||||
|
||||
$endpoint = $this->makeEndpoint(
|
||||
$span->getTracer()->getIpAddress(),
|
||||
0, // span.port,
|
||||
$span->getTracer()->getServiceName()
|
||||
);
|
||||
|
||||
$timestamp = $span->getStartTime();
|
||||
$duration = $span->getEndTime() - $span->getStartTime();
|
||||
|
||||
$this->addZipkinAnnotations($span, $endpoint);
|
||||
|
||||
$zipkinSpan = new ThriftSpan([
|
||||
'name' => $span->getOperationName(),
|
||||
'id' => $span->getContext()->getSpanId(),
|
||||
'parent_id' => $span->getContext()->getParentId() ?? null,
|
||||
'trace_id' => $span->getContext()->getTraceId(),
|
||||
'annotations' => $this->createAnnotations($span, $endpoint),
|
||||
'binary_annotations' => $span->getTags(),
|
||||
'debug' => $span->isDebug(),
|
||||
'timestamp' => $timestamp,
|
||||
'duration' => $duration,
|
||||
]);
|
||||
|
||||
$zipkinSpans[] = $zipkinSpan;
|
||||
}
|
||||
|
||||
return $zipkinSpans;
|
||||
}
|
||||
|
||||
private function addZipkinAnnotations(JaegerSpan $span, Endpoint $endpoint)
|
||||
{
|
||||
if ($span->isRpc() && $span->peer) {
|
||||
$isClient = $span->isRpcClient();
|
||||
|
||||
$host = $this->makeEndpoint(
|
||||
$span->peer['ipv4'] ?? 0,
|
||||
$span->peer['port'] ?? 0,
|
||||
$span->peer['service_name'] ?? ''
|
||||
);
|
||||
|
||||
$key = ($isClient) ? self::SERVER_ADDR : self::CLIENT_ADDR;
|
||||
|
||||
$peer = $this->makePeerAddressTag($key, $host);
|
||||
$span->tags[$key] = $peer;
|
||||
} else {
|
||||
$tag = $this->makeLocalComponentTag(
|
||||
$span->getComponent() ?? $span->getTracer()->getServiceName(),
|
||||
$endpoint
|
||||
);
|
||||
|
||||
$span->tags[COMPONENT] = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
private function makeLocalComponentTag(string $componentName, Endpoint $endpoint): BinaryAnnotation
|
||||
{
|
||||
return new BinaryAnnotation([
|
||||
'key' => "lc",
|
||||
'value' => $componentName,
|
||||
'annotation_type' => AnnotationType::STRING,
|
||||
'host' => $endpoint,
|
||||
]);
|
||||
}
|
||||
|
||||
private function makeEndpoint(string $ipv4, int $port, string $serviceName): Endpoint
|
||||
{
|
||||
$ipv4 = $this->ipv4ToInt($ipv4);
|
||||
|
||||
return new Endpoint([
|
||||
'ipv4' => $ipv4,
|
||||
'port' => $port,
|
||||
'service_name' => $serviceName,
|
||||
]);
|
||||
}
|
||||
|
||||
private function ipv4ToInt(string $ipv4): int
|
||||
{
|
||||
if ($ipv4 == 'localhost') {
|
||||
$ipv4 = '127.0.0.1';
|
||||
} elseif ($ipv4 == '::1') {
|
||||
$ipv4 = '127.0.0.1';
|
||||
}
|
||||
|
||||
$long = ip2long($ipv4);
|
||||
if (PHP_INT_SIZE === 8) {
|
||||
return $long >> 31 ? $long - (1 << 32) : $long;
|
||||
}
|
||||
return $long;
|
||||
}
|
||||
|
||||
// Used for Zipkin binary annotations like CA/SA (client/server address).
|
||||
// They are modeled as Boolean type with '0x01' as the value.
|
||||
private function makePeerAddressTag(string $key, Endpoint $host): BinaryAnnotation
|
||||
{
|
||||
return new BinaryAnnotation([
|
||||
"key" => $key,
|
||||
"value" => '0x01',
|
||||
"annotation_type" => AnnotationType::BOOL,
|
||||
"host" => $host,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits an array of thrift-objects into several chunks when the buffer limit has been reached.
|
||||
*
|
||||
* @param array|ThriftSpan[]|TBase[] $thrifts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function chunkSplit(array $thrifts): array
|
||||
{
|
||||
$actualBufferSize = $this->zipkinBatchOverheadLength;
|
||||
$chunkId = 0;
|
||||
$chunks = [];
|
||||
|
||||
foreach ($thrifts as $thrift) {
|
||||
$spanBufferLength = $this->getBufferLength($thrift);
|
||||
|
||||
if (!empty($chunks[$chunkId]) && ($actualBufferSize + $spanBufferLength) > $this->maxBufferLength) {
|
||||
// point to next chunk
|
||||
++$chunkId;
|
||||
|
||||
// reset buffer size
|
||||
$actualBufferSize = $this->zipkinBatchOverheadLength;
|
||||
}
|
||||
|
||||
if (!isset($chunks[$chunkId])) {
|
||||
$chunks[$chunkId] = [];
|
||||
}
|
||||
|
||||
$chunks[$chunkId][] = $thrift;
|
||||
$actualBufferSize += $spanBufferLength;
|
||||
}
|
||||
|
||||
return $chunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of a thrift-object.
|
||||
*
|
||||
* @param ThriftSpan|TBase $thrift
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function getBufferLength($thrift): int
|
||||
{
|
||||
$memoryBuffer = new TMemoryBuffer();
|
||||
|
||||
$thrift->write(new TCompactProtocol($memoryBuffer));
|
||||
|
||||
return $memoryBuffer->available();
|
||||
}
|
||||
|
||||
/*
|
||||
* @param JaegerSpan $span
|
||||
* @param Endpoint $endpoint
|
||||
*
|
||||
* @return array|Annotation[]
|
||||
*/
|
||||
private function createAnnotations(JaegerSpan $span, Endpoint $endpoint): array
|
||||
{
|
||||
$annotations = [];
|
||||
|
||||
foreach ($span->getLogs() as $values) {
|
||||
$annotations[] = new Annotation([
|
||||
'timestamp' => $values['timestamp'],
|
||||
'value' => json_encode($values['fields']),
|
||||
'host' => $endpoint,
|
||||
]);
|
||||
}
|
||||
|
||||
return $annotations;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,476 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger;
|
||||
|
||||
use Jaeger\Thrift\Agent\Zipkin\AnnotationType;
|
||||
use Jaeger\Thrift\Agent\Zipkin\BinaryAnnotation;
|
||||
use OpenTracing\Span as OTSpan;
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use OpenTracing\SpanContext as OTSpanContext;
|
||||
use const OpenTracing\Tags\COMPONENT;
|
||||
use const OpenTracing\Tags\PEER_HOST_IPV4;
|
||||
use const OpenTracing\Tags\PEER_PORT;
|
||||
use const OpenTracing\Tags\PEER_SERVICE;
|
||||
use const OpenTracing\Tags\SPAN_KIND;
|
||||
use const OpenTracing\Tags\SPAN_KIND_MESSAGE_BUS_CONSUMER;
|
||||
use const OpenTracing\Tags\SPAN_KIND_MESSAGE_BUS_PRODUCER;
|
||||
use const OpenTracing\Tags\SPAN_KIND_RPC_CLIENT;
|
||||
use const OpenTracing\Tags\SPAN_KIND_RPC_SERVER;
|
||||
|
||||
class Span implements OTSpan
|
||||
{
|
||||
/**
|
||||
* @var Tracer
|
||||
*/
|
||||
private $tracer;
|
||||
|
||||
/**
|
||||
* @var SpanContext
|
||||
*/
|
||||
private $context;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $operationName;
|
||||
|
||||
/**
|
||||
* @var int|float|DateTime|null
|
||||
*/
|
||||
private $startTime;
|
||||
|
||||
/**
|
||||
* @var int|float|DateTime|null
|
||||
*/
|
||||
private $endTime;
|
||||
|
||||
/**
|
||||
* SPAN_RPC_CLIENT
|
||||
* @var null|string
|
||||
*/
|
||||
private $kind;
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*/
|
||||
public $peer;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $component;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $logs = [];
|
||||
|
||||
/**
|
||||
* @var BinaryAnnotation[]
|
||||
*/
|
||||
public $tags = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $debug = false;
|
||||
|
||||
/**
|
||||
* Span constructor.
|
||||
* @param SpanContext $context
|
||||
* @param Tracer $tracer
|
||||
* @param string $operationName
|
||||
* @param array $tags
|
||||
* @param int|float|DateTime|null $startTime
|
||||
*/
|
||||
public function __construct(
|
||||
SpanContext $context,
|
||||
Tracer $tracer,
|
||||
string $operationName,
|
||||
array $tags = [],
|
||||
$startTime = null
|
||||
) {
|
||||
$this->context = $context;
|
||||
$this->tracer = $tracer;
|
||||
|
||||
$this->operationName = $operationName;
|
||||
$this->startTime = $this->microTime($startTime);
|
||||
$this->endTime = null;
|
||||
$this->kind = null;
|
||||
$this->peer = null;
|
||||
$this->component = null;
|
||||
|
||||
foreach ($tags as $key => $value) {
|
||||
$this->setTag($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts time to microtime int
|
||||
* - int represents microseconds
|
||||
* - float represents seconds
|
||||
*
|
||||
* @param int|float|DateTime|null $time
|
||||
* @return int
|
||||
*/
|
||||
protected function microTime($time): int
|
||||
{
|
||||
if ($time === null) {
|
||||
return $this->timestampMicro();
|
||||
}
|
||||
|
||||
if ($time instanceof \DateTimeInterface) {
|
||||
return (int)round($time->format('U.u') * 1000000, 0);
|
||||
}
|
||||
|
||||
if (is_int($time)) {
|
||||
return $time;
|
||||
}
|
||||
|
||||
if (is_float($time)) {
|
||||
return (int)round($time * 1000000, 0);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'Time should be one of the types int|float|DateTime|null, got %s.',
|
||||
gettype($time)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tracer
|
||||
*/
|
||||
public function getTracer(): Tracer
|
||||
{
|
||||
return $this->tracer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDebug(): bool
|
||||
{
|
||||
return $this->debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getStartTime(): int
|
||||
{
|
||||
return $this->startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getEndTime()
|
||||
{
|
||||
return $this->endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOperationName(): string
|
||||
{
|
||||
return $this->operationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getComponent()
|
||||
{
|
||||
// TODO
|
||||
return $this->component;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return SpanContext
|
||||
*/
|
||||
public function getContext(): OTSpanContext
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function finish($finishTime = null, array $logRecords = []): void
|
||||
{
|
||||
if (!$this->isSampled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($logRecords as $logRecord) {
|
||||
$this->log($logRecord);
|
||||
}
|
||||
|
||||
$this->endTime = $this->microTime($finishTime);
|
||||
$this->tracer->reportSpan($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the trace should be measured.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSampled(): bool
|
||||
{
|
||||
$context = $this->getContext();
|
||||
|
||||
return ($context->getFlags() & SAMPLED_FLAG) == SAMPLED_FLAG;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function overwriteOperationName(string $newOperationName): void
|
||||
{
|
||||
// TODO log warning
|
||||
$this->operationName = $newOperationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param array $tags
|
||||
* @return void
|
||||
*/
|
||||
public function setTags($tags)
|
||||
{
|
||||
foreach ($tags as $key => $value) {
|
||||
$this->setTag($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setTag(string $key, $value): void
|
||||
{
|
||||
if ($this->isSampled()) {
|
||||
$special = self::SPECIAL_TAGS[$key] ?? null;
|
||||
$handled = false;
|
||||
|
||||
if ($special !== null && is_callable([$this, $special])) {
|
||||
$handled = $this->$special($value);
|
||||
}
|
||||
|
||||
if (!$handled) {
|
||||
$tag = $this->makeTag($key, $value);
|
||||
$this->tags[$key] = $tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SPECIAL_TAGS = [
|
||||
PEER_SERVICE => 'setPeerService',
|
||||
PEER_HOST_IPV4 => 'setPeerHostIpv4',
|
||||
PEER_PORT => 'setPeerPort',
|
||||
SPAN_KIND => 'setSpanKind',
|
||||
COMPONENT => 'setComponent',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sets a low-cardinality identifier of the module, library,
|
||||
* or package that is generating a span.
|
||||
*
|
||||
* @see Span::setTag()
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
private function setComponent($value): bool
|
||||
{
|
||||
$this->component = $value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function setSpanKind($value): bool
|
||||
{
|
||||
$validSpanKinds = [
|
||||
SPAN_KIND_RPC_CLIENT,
|
||||
SPAN_KIND_RPC_SERVER,
|
||||
SPAN_KIND_MESSAGE_BUS_CONSUMER,
|
||||
SPAN_KIND_MESSAGE_BUS_PRODUCER,
|
||||
];
|
||||
|
||||
if ($value === null || in_array($value, $validSpanKinds, true)) {
|
||||
$this->kind = $value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getKind(): ?string
|
||||
{
|
||||
return $this->kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function setPeerPort($value): bool
|
||||
{
|
||||
if ($this->peer === null) {
|
||||
$this->peer = ['port' => $value];
|
||||
} else {
|
||||
$this->peer['port'] = $value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function setPeerHostIpv4($value): bool
|
||||
{
|
||||
if ($this->peer === null) {
|
||||
$this->peer = ['ipv4' => $value];
|
||||
} else {
|
||||
$this->peer['ipv4'] = $value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function setPeerService($value): bool
|
||||
{
|
||||
if ($this->peer === null) {
|
||||
$this->peer = ['service_name' => $value];
|
||||
} else {
|
||||
$this->peer['service_name'] = $value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isRpc(): bool
|
||||
{
|
||||
return $this->kind == SPAN_KIND_RPC_CLIENT || $this->kind == SPAN_KIND_RPC_SERVER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isRpcClient(): bool
|
||||
{
|
||||
return $this->kind == SPAN_KIND_RPC_CLIENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function log(array $fields = [], $timestamp = null): void
|
||||
{
|
||||
$timestamp = $this->microTime($timestamp);
|
||||
if ($timestamp < $this->getStartTime()) {
|
||||
$timestamp = $this->timestampMicro();
|
||||
}
|
||||
|
||||
$this->logs[] = [
|
||||
'fields' => $fields,
|
||||
'timestamp' => $timestamp,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the logs.
|
||||
*
|
||||
* [
|
||||
* [
|
||||
* 'timestamp' => timestamp in microsecond,
|
||||
* 'fields' => [
|
||||
* 'error' => 'message',
|
||||
* ]
|
||||
* ]
|
||||
* ]
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLogs(): array
|
||||
{
|
||||
return $this->logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addBaggageItem(string $key, string $value): void
|
||||
{
|
||||
$this->context = $this->context->withBaggageItem($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBaggageItem(string $key): ?string
|
||||
{
|
||||
return $this->context->getBaggageItem($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTags(): array
|
||||
{
|
||||
return $this->tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function timestampMicro(): int
|
||||
{
|
||||
return round(microtime(true) * 1000000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return BinaryAnnotation
|
||||
*/
|
||||
private function makeTag(string $key, $value): BinaryAnnotation
|
||||
{
|
||||
$valueType = gettype($value);
|
||||
$annotationType = null;
|
||||
switch ($valueType) {
|
||||
case "boolean":
|
||||
$annotationType = AnnotationType::BOOL;
|
||||
break;
|
||||
case "integer":
|
||||
$annotationType = AnnotationType::I64;
|
||||
break;
|
||||
case "double":
|
||||
$annotationType = AnnotationType::DOUBLE;
|
||||
break;
|
||||
default:
|
||||
$annotationType = AnnotationType::STRING;
|
||||
$value = (string)$value;
|
||||
if (strlen($value) > 1024) {
|
||||
$value = substr($value, 0, 1024);
|
||||
}
|
||||
}
|
||||
|
||||
return new BinaryAnnotation([
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'annotation_type' => $annotationType,
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
namespace Jaeger;
|
||||
|
||||
use ArrayIterator;
|
||||
use OpenTracing\SpanContext as OTSpanContext;
|
||||
|
||||
class SpanContext implements OTSpanContext
|
||||
{
|
||||
private $traceId;
|
||||
|
||||
private $spanId;
|
||||
|
||||
private $parentId;
|
||||
|
||||
private $flags;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $baggage;
|
||||
|
||||
private $debugId;
|
||||
|
||||
/**
|
||||
* SpanContext constructor.
|
||||
*
|
||||
* @param string $traceId
|
||||
* @param string $spanId
|
||||
* @param string $parentId
|
||||
* @param int|null $flags
|
||||
* @param array $baggage
|
||||
* @param int|null $debugId
|
||||
*/
|
||||
public function __construct($traceId, $spanId, $parentId, $flags = null, $baggage = [], $debugId = null)
|
||||
{
|
||||
$this->traceId = $traceId;
|
||||
$this->spanId = $spanId;
|
||||
$this->parentId = $parentId;
|
||||
$this->flags = $flags;
|
||||
$this->baggage = is_array($baggage) ? $baggage : [];
|
||||
$this->debugId = $debugId;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->baggage);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getBaggageItem(string $key): ?string
|
||||
{
|
||||
return array_key_exists($key, $this->baggage) ? $this->baggage[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @return SpanContext
|
||||
*/
|
||||
public function withBaggageItem(string $key, string $value): OTSpanContext
|
||||
{
|
||||
return new self(
|
||||
$this->traceId,
|
||||
$this->spanId,
|
||||
$this->parentId,
|
||||
$this->flags,
|
||||
[$key => $value] + $this->baggage
|
||||
);
|
||||
}
|
||||
|
||||
public function getTraceId()
|
||||
{
|
||||
return $this->traceId;
|
||||
}
|
||||
|
||||
public function getParentId()
|
||||
{
|
||||
return $this->parentId;
|
||||
}
|
||||
|
||||
public function getSpanId()
|
||||
{
|
||||
return $this->spanId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the span context flags.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function getBaggage()
|
||||
{
|
||||
return $this->baggage;
|
||||
}
|
||||
|
||||
public function getDebugId()
|
||||
{
|
||||
return $this->debugId;
|
||||
}
|
||||
|
||||
public function isDebugIdContainerOnly(): bool
|
||||
{
|
||||
return ($this->traceId === null) && ($this->debugId !== null);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue